proto-socket/go/communicator_test.go
toki 14e4cd56d0 feat: add WebSocket/WSS support and Go implementation
- 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
2026-04-11 08:33:46 +09:00

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
})
}