package hotline
import (
+ "bytes"
"fmt"
"github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
"io"
- "reflect"
"testing"
)
0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76,
0x04,
0x46, 0x6f, 0x6f, 0x7a,
+ 0x00,
},
},
}
Description: tt.fields.Description,
}
- if got, _ := io.ReadAll(tr); !reflect.DeepEqual(got, tt.want) {
+ if got, _ := io.ReadAll(tr); !assert.Equal(t, tt.want, got) {
t.Errorf("Read() = %v, want %v", got, tt.want)
}
})
})
}
}
+
+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)
+ }
+ })
+ }
+}