X-Git-Url: https://git.r.bdr.sh/rbdr/mobius/blobdiff_plain/a55350daaf83498b7a237c027ad0dd2377f06fee..a2ef262a164fc735b9b8471ac0c8001eea2b9bf6:/hotline/tracker_test.go diff --git a/hotline/tracker_test.go b/hotline/tracker_test.go index b5c5c55..14c0363 100644 --- a/hotline/tracker_test.go +++ b/hotline/tracker_test.go @@ -1,8 +1,10 @@ package hotline import ( + "bytes" "fmt" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "io" "reflect" "testing" @@ -191,3 +193,157 @@ func Test_serverScanner(t *testing.T) { }) } } + +type mockConn struct { + readBuffer *bytes.Buffer + writeBuffer *bytes.Buffer + closed bool +} + +func (m *mockConn) Read(b []byte) (n int, err error) { + return m.readBuffer.Read(b) +} + +func (m *mockConn) Write(b []byte) (n int, err error) { + return m.writeBuffer.Write(b) +} + +func (m *mockConn) Close() error { + m.closed = true + return nil +} + +func TestGetListing(t *testing.T) { + tests := []struct { + name string + mockConn *mockConn + wantErr bool + wantResult []ServerRecord + }{ + { + name: "Successful retrieval", + mockConn: &mockConn{ + readBuffer: bytes.NewBuffer([]byte{ + // TrackerHeader + 0x48, 0x54, 0x52, 0x4B, // Protocol "HTRK" + 0x00, 0x01, // Version 1 + // ServerInfoHeader + 0x00, 0x01, // MsgType (1) + 0x00, 0x14, // MsgDataSize (20) + 0x00, 0x02, // SrvCount (2) + 0x00, 0x02, // SrvCountDup (2) + // ServerRecord 1 + 192, 168, 1, 1, // IP address + 0x1F, 0x90, // Port 8080 + 0x00, 0x10, // NumUsers 16 + 0x00, 0x00, // Unused + 0x04, // NameSize + 'S', 'e', 'r', 'v', // Name + 0x0B, // DescriptionSize + 'M', 'y', ' ', 'S', 'e', 'r', 'v', 'e', 'r', ' ', '1', // Description + // ServerRecord 2 + 10, 0, 0, 1, // IP address + 0x1F, 0x91, // Port 8081 + 0x00, 0x05, // NumUsers 5 + 0x00, 0x00, // Unused + 0x04, // NameSize + 'S', 'e', 'r', 'v', // Name + 0x0B, // DescriptionSize + 'M', 'y', ' ', 'S', 'e', 'r', 'v', 'e', 'r', ' ', '2', // Description + }), + writeBuffer: &bytes.Buffer{}, + }, + wantErr: false, + wantResult: []ServerRecord{ + { + IPAddr: [4]byte{192, 168, 1, 1}, + Port: [2]byte{0x1F, 0x90}, + NumUsers: [2]byte{0x00, 0x10}, + Unused: [2]byte{0x00, 0x00}, + NameSize: 4, + Name: []byte("Serv"), + DescriptionSize: 11, + Description: []byte("My Server 1"), + }, + { + IPAddr: [4]byte{10, 0, 0, 1}, + Port: [2]byte{0x1F, 0x91}, + NumUsers: [2]byte{0x00, 0x05}, + Unused: [2]byte{0x00, 0x00}, + NameSize: 4, + Name: []byte("Serv"), + DescriptionSize: 11, + Description: []byte("My Server 2"), + }, + }, + }, + { + name: "Write error", + mockConn: &mockConn{ + readBuffer: &bytes.Buffer{}, + writeBuffer: &bytes.Buffer{}, + }, + wantErr: true, + wantResult: nil, + }, + { + name: "Read error on TrackerHeader", + mockConn: &mockConn{ + readBuffer: bytes.NewBuffer([]byte{ + // incomplete data to cause read error + 0x48, + }), + writeBuffer: &bytes.Buffer{}, + }, + wantErr: true, + wantResult: nil, + }, + { + name: "Read error on ServerInfoHeader", + mockConn: &mockConn{ + readBuffer: bytes.NewBuffer([]byte{ + // TrackerHeader + 0x48, 0x54, 0x52, 0x4B, // Protocol "HTRK" + 0x00, 0x01, // Version 1 + // incomplete ServerInfoHeader + 0x00, + }), + writeBuffer: &bytes.Buffer{}, + }, + wantErr: true, + wantResult: nil, + }, + { + name: "Scanner error", + mockConn: &mockConn{ + readBuffer: bytes.NewBuffer([]byte{ + // TrackerHeader + 0x48, 0x54, 0x52, 0x4B, // Protocol "HTRK" + 0x00, 0x01, // Version 1 + // ServerInfoHeader + 0x00, 0x01, // MsgType (1) + 0x00, 0x14, // MsgDataSize (20) + 0x00, 0x01, // SrvCount (1) + 0x00, 0x01, // SrvCountDup (1) + // incomplete ServerRecord to cause scanner error + 192, 168, 1, 1, + }), + writeBuffer: &bytes.Buffer{}, + }, + wantErr: true, + wantResult: nil, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := GetListing(tt.mockConn) + if tt.wantErr { + require.Error(t, err) + } else { + require.NoError(t, err) + assert.Equal(t, tt.wantResult, got) + } + }) + } +}