Repository: markus-wa/demoinfocs-golang (go)

Issue:
another "no-panic" issue
I faced another debugging problem with new "no-panic" behaviour:
```go
var dummyInt int

p.RegisterEventHandler(func(e events.DataTablesParsed) {
	players := p.ServerClasses().FindByName("CCSPlayer")
	players.OnEntityCreated(func(playerEntity *st.Entity) {
		prop := playerEntity.FindPropertyI("m_bIsLookingAtWeapon")
		if prop != nil {
			prop.Bind(&dummyInt, st.ValTypeBoolInt)
		}
	})
})

err = p.ParseToEnd()
if err != nil {
	panic(err)
}
```

Since `dummyInt` is `int` and `st.ValTypeBoolInt` implies that it should be `bool`, we get this error at runtime with `v1.8.0` or newer:
```
panic: interface conversion: interface {} is *int, not *bool

goroutine 1 [running]:
main.main()
	C:/Users/admin/go/src/demoinfocs-test-cases/main.go:69 +0x1d5
```

where 69th line is, of cource, `panic(err)` so we cannot track down the issue exactly.

While with `v1.7.6` we got
```
panic: interface conversion: interface {} is *int, not *bool [recovered]
	panic: interface conversion: interface {} is *int, not *bool [recovered]
	panic: interface conversion: interface {} is *int, not *bool

goroutine 20 [running]:
github.com/markus-wa/godispatch.callConsumerCode.func1()
	C:/Users/admin/go/pkg/mod/github.com/markus-wa/godispatch@v1.2.1/dispatch.go:104 +0x8f
panic(0x874c60, 0xc000d8c3c0)
	C:/Program Files/Go/src/runtime/panic.go:522 +0x1c3
github.com/markus-wa/demoinfocs-golang.recoverFromUnexpectedEOF(...)
	C:/Users/admin/go/pkg/mod/github.com/markus-wa/demoinfocs-golang@v1.7.6/parsing.go:120
github.com/markus-wa/demoinfocs-golang.(*Parser).handlePacketEntities.func1(0xc000106000)
	C:/Users/admin/go/pkg/mod/github.com/markus-wa/demoinfocs-golang@v1.7.6/entities.go:14 +0x139
panic(0x874c60, 0xc000d8c3c0)
	C:/Program Files/Go/src/runtime/panic.go:522 +0x1c3
github.com/markus-wa/demoinfocs-golang/sendtables.(*Property).Bind.func2(0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
	C:/Users/admin/go/pkg/mod/github.com/markus-wa/demoinfocs-golang@v1.7.6/sendtables/entity.go:372 +0x65
github.com/markus-wa/demoinfocs-golang/sendtables.(*Property).OnUpdate(...)
	C:/Users/admin/go/pkg/mod/github.com/markus-wa/demoinfocs-golang@v1.7.6/sendtables/entity.go:341
github.com/markus-wa/demoinfocs-golang/sendtables.(*Property).Bind(0xc000bf25e0, 0x83d580, 0xc00006e120, 0x6)
	C:/Users/admin/go/pkg/mod/github.com/markus-wa/demoinfocs-golang@v1.7.6/sendtables/entity.go:400 +0xb6
main.main.func1.1(0xc000058420)
	C:/Users/admin/go/src/demoinfocs-test-cases/main.go:62 +0x9e
github.com/markus-wa/demoinfocs-golang/sendtables.(*ServerClass).newEntity(0xc0004866e0, 0xc0003c8690, 0x1, 0x8800000000000000)
	C:/Users/admin/go/pkg/mod/github.com/markus-wa/demoinfocs-golang@v1.7.6/sendtables/sendtables.go:120 +0x2f5
github.com/markus-wa/demoinfocs-golang/sendtables.(*SendTableParser).ReadEnterPVS(0xc0000fc150, 0xc0003c8690, 0x1, 0xd59be0)
	C:/Users/admin/go/pkg/mod/github.com/markus-wa/demoinfocs-golang@v1.7.6/sendtables/st_parser.go:290 +0xcd
github.com/markus-wa/demoinfocs-golang.(*Parser).handlePacketEntities(0xc000106000, 0xc000888300)
	C:/Users/admin/go/pkg/mod/github.com/markus-wa/demoinfocs-golang@v1.7.6/entities.go:43 +0x26b
reflect.Value.call(0x84e0a0, 0xc0000644a0, 0x13, 0x8ea727, 0x4, 0xc000057f68, 0x1, 0x1, 0xc00008f470, 0x98afc0, ...)
	C:/Program Files/Go/src/reflect/value.go:447 +0x468
reflect.Value.Call(0x84e0a0, 0xc0000644a0, 0x13, 0xc000057f68, 0x1, 0x1, 0x6, 0xd38b20, 0xc000382000)
	C:/Program Files/Go/src/reflect/value.go:308 +0xab
github.com/markus-wa/godispatch.callConsumerCode(0x84e0a0, 0xc0000644a0, 0x13, 0xc000057f68, 0x1, 0x1)
	C:/Users/admin/go/pkg/mod/github.com/markus-wa/godispatch@v1.2.1/dispatch.go:107 +0x87
github.com/markus-wa/godispatch.(*Dispatcher).Dispatch(0xc000106020, 0x8d41e0, 0xc000888300)
	C:/Users/admin/go/pkg/mod/github.com/markus-wa/godispatch@v1.2.1/dispatch.go:93 +0x24e
github.com/markus-wa/godispatch.(*Dispatcher).dispatchQueue(0xc000106020, 0xc000058060)
	C:/Users/admin/go/pkg/mod/github.com/markus-wa/godispatch@v1.2.1/dispatch.go:155 +0xfc
created by github.com/markus-wa/godispatch.(*Dispatcher).AddQueues
	C:/Users/admin/go/pkg/mod/github.com/markus-wa/godispatch@v1.2.1/dispatch.go:141 +0x158
```

which is much more informative 😃 

Pull request:
core: bring back panicking behvaiour from pre-1.8.0
fixes #200 

Patch:
diff --git a/net_messages.go b/net_messages.go
index b1daa1a..e117ed7 100644
--- a/net_messages.go
+++ b/net_messages.go
@@ -12,7 +12,7 @@ const entitySentinel = 9999
 
 func (p *Parser) handlePacketEntities(pe *msg.CSVCMsg_PacketEntities) {
 	defer func() {
-		p.setError(recoverFromPanic(recover()))
+		p.setError(recoverFromUnexpectedEOF(recover()))
 	}()
 
 	r := bit.NewSmallBitReader(bytes.NewReader(pe.EntityData))
diff --git a/parsing.go b/parsing.go
index e7aa008..5881098 100644
--- a/parsing.go
+++ b/parsing.go
@@ -98,7 +98,7 @@ func (p *Parser) ParseToEnd() (err error) {
 		}
 
 		if err == nil {
-			err = recoverFromPanic(recover())
+			err = recoverFromUnexpectedEOF(recover())
 		}
 	}()
 
@@ -126,7 +126,7 @@ func (p *Parser) ParseToEnd() (err error) {
 	}
 }
 
-func recoverFromPanic(r interface{}) error {
+func recoverFromUnexpectedEOF(r interface{}) error {
 	if r == nil {
 		return nil
 	}
@@ -138,12 +138,8 @@ func recoverFromPanic(r interface{}) error {
 	switch err := r.(type) {
 	case dispatch.ConsumerCodePanic:
 		panic(err.Value())
-	case error:
-		return err
-	case string:
-		return errors.New(err)
 	default:
-		return fmt.Errorf("unexpected error: %v", err)
+		panic(err)
 	}
 }
 
@@ -174,7 +170,7 @@ func (p *Parser) ParseNextFrame() (moreFrames bool, err error) {
 		}
 
 		if err == nil {
-			err = recoverFromPanic(recover())
+			err = recoverFromUnexpectedEOF(recover())
 		}
 	}()
 
diff --git a/stringtables.go b/stringtables.go
index 18b0f81..4dd0332 100644
--- a/stringtables.go
+++ b/stringtables.go
@@ -99,7 +99,7 @@ func (p *Parser) parseSingleStringTable(name string) {
 }
 
 func (p *Parser) handleUpdateStringTable(tab *msg.CSVCMsg_UpdateStringTable) {
-	// No need for recoverFromPanic here as we do that in processStringTable already
+	// No need for recoverFromUnexpectedEOF here as we do that in processStringTable already
 
 	cTab := p.stringTables[tab.TableId]
 	switch cTab.Name {
@@ -117,7 +117,7 @@ func (p *Parser) handleUpdateStringTable(tab *msg.CSVCMsg_UpdateStringTable) {
 }
 
 func (p *Parser) handleCreateStringTable(tab *msg.CSVCMsg_CreateStringTable) {
-	// No need for recoverFromPanic here as we do that in processStringTable already
+	// No need for recoverFromUnexpectedEOF here as we do that in processStringTable already
 
 	p.processStringTable(tab)
 
@@ -128,7 +128,7 @@ func (p *Parser) handleCreateStringTable(tab *msg.CSVCMsg_CreateStringTable) {
 
 func (p *Parser) processStringTable(tab *msg.CSVCMsg_CreateStringTable) {
 	defer func() {
-		p.setError(recoverFromPanic(recover()))
+		p.setError(recoverFromUnexpectedEOF(recover()))
 	}()
 
 	if tab.Name == stNameModelPreCache {


Test patch:
diff --git a/parser_test.go b/parser_test.go
index 29c82de..6fa8f0e 100644
--- a/parser_test.go
+++ b/parser_test.go
@@ -66,16 +66,15 @@ func TestParser_Progress_NoHeader(t *testing.T) {
 	assert.Zero(t, (&Parser{header: &common.DemoHeader{}}).Progress())
 }
 
-func TestRecoverFromPanic(t *testing.T) {
-	assert.Nil(t, recoverFromPanic(nil))
-	assert.Equal(t, ErrUnexpectedEndOfDemo, recoverFromPanic(io.ErrUnexpectedEOF))
-	assert.Equal(t, ErrUnexpectedEndOfDemo, recoverFromPanic(io.EOF))
-
-	err := errors.New("test")
-	assert.Equal(t, err, recoverFromPanic(err))
-
-	assert.Equal(t, "test", recoverFromPanic("test").Error())
-	assert.Equal(t, "unexpected error: 1", recoverFromPanic(1).Error())
+func TestRecoverFromUnexpectedEOF(t *testing.T) {
+	assert.Nil(t, recoverFromUnexpectedEOF(nil))
+	assert.Equal(t, ErrUnexpectedEndOfDemo, recoverFromUnexpectedEOF(io.ErrUnexpectedEOF))
+	assert.Equal(t, ErrUnexpectedEndOfDemo, recoverFromUnexpectedEOF(io.EOF))
+
+	assert.Panics(t, func() {
+		r := recoverFromUnexpectedEOF(errors.New("test"))
+		assert.Failf(t, "expected panic, got recovery", "recovered value = '%v'", r)
+	})
 }
 
 type consumerCodePanicMock struct {
@@ -92,7 +91,7 @@ func (ucp consumerCodePanicMock) Value() interface{} {
 
 func TestRecoverFromPanic_ConsumerCodePanic(t *testing.T) {
 	assert.PanicsWithValue(t, 1, func() {
-		err := recoverFromPanic(consumerCodePanicMock{value: 1})
+		err := recoverFromUnexpectedEOF(consumerCodePanicMock{value: 1})
 		assert.Nil(t, err)
 	})
 }