grcon/client/simple_client_test.go
2022-03-05 17:31:46 +01:00

369 lines
9.6 KiB
Go

package client_test
import (
"testing"
"github.com/hamburghammer/grcon"
"github.com/hamburghammer/grcon/client"
)
func TestSimpleClient_Auth(t *testing.T) {
t.Run("successful auth", func(t *testing.T) {
mockIdGen := &MockIdGenerator{Ids: []grcon.PacketId{1}}
mock := &MockRemoteConsole{In: []grcon.Packet{
{Id: 1, Type: grcon.SERVERDATA_RESPONSE_VALUE, Body: []byte("")},
{Id: 1, Type: grcon.SERVERDATA_AUTH_RESPONSE, Body: []byte("")},
}}
simpleClient := client.SimpleClient{
RemoteConsole: mock,
IdGenFunc: mockIdGen.GetNextId,
}
err := simpleClient.Auth("foo")
if err != nil {
t.Error(err)
t.FailNow()
}
})
t.Run("pre empty response", func(t *testing.T) {
t.Run("not match type", func(t *testing.T) {
mockIdGen := &MockIdGenerator{Ids: []grcon.PacketId{1}}
mock := &MockRemoteConsole{In: []grcon.Packet{
{Id: 1, Type: grcon.SERVERDATA_AUTH_RESPONSE, Body: []byte("")},
}}
simpleClient := client.SimpleClient{
RemoteConsole: mock,
IdGenFunc: mockIdGen.GetNextId,
}
err := simpleClient.Auth("foo")
_, ok := err.(client.InvalidResponseTypeError)
if err != nil && !ok {
t.Errorf("expected: InvalidResponseTypeError\ngot: %T\n", err)
t.Error(err)
t.FailNow()
}
})
t.Run("not matching id", func(t *testing.T) {
mockIdGen := &MockIdGenerator{Ids: []grcon.PacketId{1}}
mock := &MockRemoteConsole{In: []grcon.Packet{
{Id: 2, Type: grcon.SERVERDATA_RESPONSE_VALUE, Body: []byte("")},
}}
simpleClient := client.SimpleClient{
RemoteConsole: mock,
IdGenFunc: mockIdGen.GetNextId,
}
err := simpleClient.Auth("foo")
_, ok := err.(client.ResponseIdMismatchError)
if err != nil && !ok {
t.Errorf("expected: ResponseIdMismatchError\ngot: %T\n", err)
t.Error(err)
t.FailNow()
}
})
t.Run("not empty body", func(t *testing.T) {
mockIdGen := &MockIdGenerator{Ids: []grcon.PacketId{1}}
mock := &MockRemoteConsole{In: []grcon.Packet{
{Id: 1, Type: grcon.SERVERDATA_RESPONSE_VALUE, Body: []byte("ooops")},
}}
simpleClient := client.SimpleClient{
RemoteConsole: mock,
IdGenFunc: mockIdGen.GetNextId,
}
err := simpleClient.Auth("foo")
_, ok := err.(client.ResponseBodyError)
if err != nil && !ok {
t.Errorf("expected: ResponseBodyError\ngot: %T\n", err)
t.Error(err)
t.FailNow()
}
})
})
t.Run("auth response", func(t *testing.T) {
t.Run("not match type", func(t *testing.T) {
mockIdGen := &MockIdGenerator{Ids: []grcon.PacketId{1}}
mock := &MockRemoteConsole{In: []grcon.Packet{
{Id: 1, Type: grcon.SERVERDATA_RESPONSE_VALUE, Body: []byte("")},
{Id: 1, Type: grcon.SERVERDATA_RESPONSE_VALUE, Body: []byte("")},
}}
simpleClient := client.SimpleClient{
RemoteConsole: mock,
IdGenFunc: mockIdGen.GetNextId,
}
err := simpleClient.Auth("foo")
_, ok := err.(client.InvalidResponseTypeError)
if err != nil && !ok {
t.Errorf("expected: InvalidResponseTypeError\ngot: %T\n", err)
t.Error(err)
t.FailNow()
}
})
t.Run("auth failed", func(t *testing.T) {
mockIdGen := &MockIdGenerator{Ids: []grcon.PacketId{1}}
mock := &MockRemoteConsole{In: []grcon.Packet{
{Id: 1, Type: grcon.SERVERDATA_RESPONSE_VALUE, Body: []byte("")},
{Id: -1, Type: grcon.SERVERDATA_AUTH_RESPONSE, Body: []byte("")},
}}
simpleClient := client.SimpleClient{
RemoteConsole: mock,
IdGenFunc: mockIdGen.GetNextId,
}
err := simpleClient.Auth("foo")
_, ok := err.(client.AuthFailedError)
if err != nil && !ok {
t.Errorf("expected: AuthFailedError\ngot: %T\n", err)
t.Error(err)
t.FailNow()
}
})
t.Run("not matching ids", func(t *testing.T) {
mockIdGen := &MockIdGenerator{Ids: []grcon.PacketId{1}}
mock := &MockRemoteConsole{In: []grcon.Packet{
{Id: 1, Type: grcon.SERVERDATA_RESPONSE_VALUE, Body: []byte("")},
{Id: 2, Type: grcon.SERVERDATA_AUTH_RESPONSE, Body: []byte("")},
}}
simpleClient := client.SimpleClient{
RemoteConsole: mock,
IdGenFunc: mockIdGen.GetNextId,
}
err := simpleClient.Auth("foo")
_, ok := err.(client.ResponseIdMismatchError)
if err != nil && !ok {
t.Errorf("expected: ResponseIdMismatchError\ngot: %T\n", err)
t.Error(err)
t.FailNow()
}
})
})
t.Run("written packet", func(t *testing.T) {
mockIdGen := &MockIdGenerator{Ids: []grcon.PacketId{1}}
mock := &MockRemoteConsole{In: []grcon.Packet{
{Id: 1, Type: grcon.SERVERDATA_RESPONSE_VALUE, Body: []byte("")},
{Id: 1, Type: grcon.SERVERDATA_AUTH_RESPONSE, Body: []byte("")},
}}
simpleClient := client.SimpleClient{
RemoteConsole: mock,
IdGenFunc: mockIdGen.GetNextId,
}
err := simpleClient.Auth("foo")
if err != nil {
t.Error(err)
t.FailNow()
}
got := mock.Out
if len(got) < 1 {
t.Errorf("expected at leased 1 packet but got %d\n", len(got))
}
gotPacket := got[0]
if gotPacket.Id != 1 {
t.Error("expected id 1 but got something different")
}
if gotPacket.Type != grcon.SERVERDATA_AUTH {
t.Error("packet was not of type auth")
}
if string(gotPacket.Body) != "foo" {
t.Error("body/password did not match")
}
})
}
func TestSimpleClient_Exec(t *testing.T) {
t.Run("successful execution", func(t *testing.T) {
mockIdGen := &MockIdGenerator{Ids: []grcon.PacketId{1, 2}}
mock := &MockRemoteConsole{In: []grcon.Packet{
{Id: 1, Type: grcon.SERVERDATA_RESPONSE_VALUE, Body: []byte("bar")},
{Id: 2, Type: grcon.SERVERDATA_RESPONSE_VALUE, Body: []byte("")},
}}
simpleClient := client.SimpleClient{
RemoteConsole: mock,
IdGenFunc: mockIdGen.GetNextId,
}
got, err := simpleClient.Exec("foo")
if err != nil {
t.Error(err)
t.FailNow()
}
if string(got) != "bar" {
t.Errorf("response did not match:\nexpected: %s\ngot: %s\n", "bar", string(got))
}
})
t.Run("successful multi packet execution", func(t *testing.T) {
mockIdGen := &MockIdGenerator{Ids: []grcon.PacketId{1, 2}}
mock := &MockRemoteConsole{In: []grcon.Packet{
{Id: 1, Type: grcon.SERVERDATA_RESPONSE_VALUE, Body: []byte("foo")},
{Id: 1, Type: grcon.SERVERDATA_RESPONSE_VALUE, Body: []byte("bar")},
{Id: 2, Type: grcon.SERVERDATA_RESPONSE_VALUE, Body: []byte("")},
}}
simpleClient := client.SimpleClient{
RemoteConsole: mock,
IdGenFunc: mockIdGen.GetNextId,
}
got, err := simpleClient.Exec("foo")
if err != nil {
t.Error(err)
t.FailNow()
}
if string(got) != "foobar" {
t.Errorf("response did not match:\nexpected: %s\ngot: %s\n", "bar", string(got))
}
})
t.Run("write cmd packet", func(t *testing.T) {
mockIdGen := &MockIdGenerator{Ids: []grcon.PacketId{1, 2}}
mock := &MockRemoteConsole{In: []grcon.Packet{
{Id: 1, Type: grcon.SERVERDATA_RESPONSE_VALUE, Body: []byte("")},
{Id: 2, Type: grcon.SERVERDATA_RESPONSE_VALUE, Body: []byte("")},
}}
simpleClient := client.SimpleClient{
RemoteConsole: mock,
IdGenFunc: mockIdGen.GetNextId,
}
_, err := simpleClient.Exec("foo")
if err != nil {
t.Error(err)
t.FailNow()
}
got := mock.Out
if len(got) < 1 {
t.Error("written less than 1 packet")
t.FailNow()
}
gotPacket := got[0]
if gotPacket.Id != 1 {
t.Error("id missmatch")
}
if gotPacket.Type != grcon.SERVERDATA_EXECCOMMAND {
t.Error("type missmatch")
}
if string(gotPacket.Body) != "foo" {
t.Error("body missmatch")
}
})
t.Run("write delimiter packet", func(t *testing.T) {
mockIdGen := &MockIdGenerator{Ids: []grcon.PacketId{1, 2}}
mock := &MockRemoteConsole{In: []grcon.Packet{
{Id: 1, Type: grcon.SERVERDATA_RESPONSE_VALUE, Body: []byte("")},
{Id: 2, Type: grcon.SERVERDATA_RESPONSE_VALUE, Body: []byte("")},
}}
simpleClient := client.SimpleClient{
RemoteConsole: mock,
IdGenFunc: mockIdGen.GetNextId,
}
_, err := simpleClient.Exec("foo")
if err != nil {
t.Error(err)
t.FailNow()
}
got := mock.Out
if len(got) < 2 {
t.Error("written less than 2 packet")
t.FailNow()
}
gotPacket := got[1]
if gotPacket.Id != 2 {
t.Error("id missmatch")
}
if gotPacket.Type != grcon.SERVERDATA_RESPONSE_VALUE {
t.Error("type missmatch")
}
if string(gotPacket.Body) != "" {
t.Error("body missmatch")
}
})
t.Run("invalid response type error", func(t *testing.T) {
mockIdGen := &MockIdGenerator{Ids: []grcon.PacketId{1, 2}}
mock := &MockRemoteConsole{In: []grcon.Packet{
{Id: 1, Type: grcon.SERVERDATA_AUTH_RESPONSE, Body: []byte("bar")},
}}
simpleClient := client.SimpleClient{
RemoteConsole: mock,
IdGenFunc: mockIdGen.GetNextId,
}
_, err := simpleClient.Exec("foo")
_, ok := err.(client.InvalidResponseTypeError)
if err != nil && !ok {
t.Error(err)
t.FailNow()
}
})
t.Run("id response missmatch type error", func(t *testing.T) {
mockIdGen := &MockIdGenerator{Ids: []grcon.PacketId{1, 2}}
mock := &MockRemoteConsole{In: []grcon.Packet{
{Id: 3, Type: grcon.SERVERDATA_RESPONSE_VALUE, Body: []byte("bar")},
}}
simpleClient := client.SimpleClient{
RemoteConsole: mock,
IdGenFunc: mockIdGen.GetNextId,
}
_, err := simpleClient.Exec("foo")
_, ok := err.(client.ResponseIdMismatchError)
if err != nil && !ok {
t.Error(err)
t.FailNow()
}
})
}
// Mock
type MockIdGenerator struct {
Ids []grcon.PacketId
nextId int
}
func (i *MockIdGenerator) GetNextId() grcon.PacketId {
id := i.Ids[i.nextId]
i.nextId++
return id
}
type MockRemoteConsole struct {
Out []grcon.Packet
In []grcon.Packet
nextIn int
}
func (m *MockRemoteConsole) Read() (grcon.Packet, error) {
packet := m.In[m.nextIn]
m.nextIn++
return packet, nil
}
func (m *MockRemoteConsole) Write(packet grcon.Packet) error {
if m.Out == nil {
m.Out = make([]grcon.Packet, 0, 2)
}
m.Out = append(m.Out, packet)
return nil
}