- Add WebSocket binary frame support to protocol specification - Update README and PROTOCOL.md to reflect dual TCP/WebSocket transport - Add Go implementation with TCP, WebSocket, and heartbeat support - Include .claude settings configuration
99 lines
2.2 KiB
Go
99 lines
2.2 KiB
Go
package toki_socket
|
|
|
|
import (
|
|
"sync"
|
|
"testing"
|
|
"time"
|
|
|
|
"google.golang.org/protobuf/proto"
|
|
|
|
"toki-labs.com/toki_socket/go/packets"
|
|
)
|
|
|
|
type fakeTransport struct {
|
|
mu sync.Mutex
|
|
packets []*packets.PacketBase
|
|
}
|
|
|
|
func (f *fakeTransport) WritePacket(base *packets.PacketBase) error {
|
|
f.mu.Lock()
|
|
defer f.mu.Unlock()
|
|
f.packets = append(f.packets, base)
|
|
return nil
|
|
}
|
|
|
|
func (f *fakeTransport) Close() error {
|
|
return nil
|
|
}
|
|
|
|
func (f *fakeTransport) sent() []*packets.PacketBase {
|
|
f.mu.Lock()
|
|
defer f.mu.Unlock()
|
|
return append([]*packets.PacketBase{}, f.packets...)
|
|
}
|
|
|
|
func testParserMap() ParserMap {
|
|
return ParserMap{
|
|
TypeNameOf(&packets.TestData{}): func(b []byte) (proto.Message, error) {
|
|
m := &packets.TestData{}
|
|
return m, proto.Unmarshal(b, m)
|
|
},
|
|
}
|
|
}
|
|
|
|
func TestSendRequestTypeMismatch(t *testing.T) {
|
|
transport := &fakeTransport{}
|
|
communicator := NewCommunicator(transport, testParserMap())
|
|
defer communicator.shutdown()
|
|
|
|
errCh := make(chan error, 1)
|
|
go func() {
|
|
_, err := SendRequestTyped[*packets.TestData, *packets.TestData](
|
|
communicator,
|
|
&packets.TestData{Index: 1, Message: "hello"},
|
|
time.Second,
|
|
)
|
|
errCh <- err
|
|
}()
|
|
|
|
var requestNonce int32
|
|
for deadline := time.Now().Add(time.Second); time.Now().Before(deadline); {
|
|
sent := transport.sent()
|
|
if len(sent) == 1 {
|
|
requestNonce = sent[0].GetNonce()
|
|
break
|
|
}
|
|
time.Sleep(time.Millisecond)
|
|
}
|
|
if requestNonce == 0 {
|
|
t.Fatal("request packet was not sent")
|
|
}
|
|
|
|
hb, err := proto.Marshal(&packets.HeartBeat{})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
communicator.OnReceivedData(TypeNameOf(&packets.HeartBeat{}), hb, 0, requestNonce)
|
|
|
|
err = <-errCh
|
|
if err == nil {
|
|
t.Fatal("expected response type mismatch error")
|
|
}
|
|
}
|
|
|
|
func TestListenerAndRequestListenerConflict(t *testing.T) {
|
|
transport := &fakeTransport{}
|
|
communicator := NewCommunicator(transport, testParserMap())
|
|
defer communicator.shutdown()
|
|
|
|
AddListenerTyped[*packets.TestData](communicator, func(*packets.TestData) {})
|
|
|
|
defer func() {
|
|
if recover() == nil {
|
|
t.Fatal("expected panic")
|
|
}
|
|
}()
|
|
AddRequestListenerTyped[*packets.TestData, *packets.TestData](communicator, func(req *packets.TestData) (*packets.TestData, error) {
|
|
return req, nil
|
|
})
|
|
}
|