X-Git-Url: https://git.r.bdr.sh/rbdr/mobius/blobdiff_plain/5c34f8752938764668d829fb284626b9c62c5475..f8e4cd540b87de3e308ec18a2b040b284a741522:/hotline/transaction_test.go diff --git a/hotline/transaction_test.go b/hotline/transaction_test.go index 4c7d372..cdb6f1e 100644 --- a/hotline/transaction_test.go +++ b/hotline/transaction_test.go @@ -1,6 +1,7 @@ package hotline import ( + "fmt" "github.com/stretchr/testify/assert" "testing" ) @@ -21,23 +22,23 @@ func TestReadFields(t *testing.T) { args: args{ paramCount: []byte{0x00, 0x02}, buf: []byte{ - 0x00, 0x65, // ID: fieldData + 0x00, 0x65, // ID: FieldData 0x00, 0x04, // Size: 2 bytes 0x01, 0x02, 0x03, 0x04, // Data - 0x00, 0x66, // ID: fieldUserName + 0x00, 0x66, // ID: FieldUserName 0x00, 0x02, // Size: 2 bytes 0x00, 0x01, // Data }, }, want: []Field{ { - ID: []byte{0x00, 0x65}, - FieldSize: []byte{0x00, 0x04}, + ID: [2]byte{0x00, 0x65}, + FieldSize: [2]byte{0x00, 0x04}, Data: []byte{0x01, 0x02, 0x03, 0x04}, }, { - ID: []byte{0x00, 0x66}, - FieldSize: []byte{0x00, 0x02}, + ID: [2]byte{0x00, 0x66}, + FieldSize: [2]byte{0x00, 0x02}, Data: []byte{0x00, 0x01}, }, }, @@ -57,7 +58,7 @@ func TestReadFields(t *testing.T) { args: args{ paramCount: []byte{0x00, 0x01}, buf: []byte{ - 0x00, 0x65, // ID: fieldData + 0x00, 0x65, // ID: FieldData 0x00, 0x04, // Size: 4 bytes 0x01, 0x02, 0x03, // Data }, @@ -70,10 +71,10 @@ func TestReadFields(t *testing.T) { args: args{ paramCount: []byte{0x00, 0x01}, buf: []byte{ - 0x00, 0x65, // ID: fieldData + 0x00, 0x65, // ID: FieldData 0x00, 0x02, // Size: 2 bytes 0x01, 0x02, // Data - 0x00, 0x65, // ID: fieldData + 0x00, 0x65, // ID: FieldData 0x00, 0x04, // Size: 4 bytes 0x01, 0x02, 0x03, // Data }, @@ -86,7 +87,7 @@ func TestReadFields(t *testing.T) { args: args{ paramCount: []byte{0x00, 0x01}, buf: []byte{ - 0x00, 0x65, // ID: fieldData + 0x00, 0x65, // ID: FieldData 0x00, 0x02, // Size: 2 bytes 0x01, 0x02, 0x03, // Data }, @@ -110,67 +111,300 @@ func TestReadFields(t *testing.T) { } } -func TestReadTransaction(t *testing.T) { - sampleTransaction := &Transaction{ - Flags: byte(0), - IsReply: byte(0), - Type: []byte{0x000, 0x93}, - ID: []byte{0x000, 0x00, 0x00, 0x01}, - ErrorCode: []byte{0x000, 0x00, 0x00, 0x00}, - TotalSize: []byte{0x000, 0x00, 0x00, 0x08}, - DataSize: []byte{0x000, 0x00, 0x00, 0x08}, - ParamCount: []byte{0x00, 0x01}, - Fields: []Field{ - { - ID: []byte{0x00, 0x01}, - FieldSize: []byte{0x00, 0x02}, - Data: []byte{0xff, 0xff}, +func Test_transactionScanner(t *testing.T) { + type args struct { + data []byte + in1 bool + } + tests := []struct { + name string + args args + wantAdvance int + wantToken []byte + wantErr assert.ErrorAssertionFunc + }{ + { + name: "when too few bytes are provided to read the transaction size", + args: args{ + data: []byte{}, + in1: false, + }, + wantAdvance: 0, + wantToken: []byte(nil), + wantErr: assert.NoError, + }, + { + name: "when too few bytes are provided to read the full payload", + args: args{ + data: []byte{ + 0, + 1, + 0, 0, + 0, 00, 00, 04, + 00, 00, 00, 00, + 00, 00, 00, 10, + 00, 00, 00, 10, + }, + in1: false, + }, + wantAdvance: 0, + wantToken: []byte(nil), + wantErr: assert.NoError, + }, + { + name: "when a full transaction is provided", + args: args{ + data: []byte{ + 0, + 1, + 0, 0, + 0, 00, 00, 0x04, + 00, 00, 00, 0x00, + 00, 00, 00, 0x10, + 00, 00, 00, 0x10, + 00, 02, + 00, 0x6c, // 108 - FieldTransferSize + 00, 02, + 0x63, 0x3b, + 00, 0x6b, // 107 = FieldRefNum + 00, 0x04, + 00, 0x02, 0x93, 0x47, + }, + in1: false, + }, + wantAdvance: 36, + wantToken: []byte{ + 0, + 1, + 0, 0, + 0, 00, 00, 0x04, + 00, 00, 00, 0x00, + 00, 00, 00, 0x10, + 00, 00, 00, 0x10, + 00, 02, + 00, 0x6c, // 108 - FieldTransferSize + 00, 02, + 0x63, 0x3b, + 00, 0x6b, // 107 = FieldRefNum + 00, 0x04, + 00, 0x02, 0x93, 0x47, + }, + wantErr: assert.NoError, + }, + { + name: "when a full transaction plus extra bytes are provided", + args: args{ + data: []byte{ + 0, + 1, + 0, 0, + 0, 00, 00, 0x04, + 00, 00, 00, 0x00, + 00, 00, 00, 0x10, + 00, 00, 00, 0x10, + 00, 02, + 00, 0x6c, // 108 - FieldTransferSize + 00, 02, + 0x63, 0x3b, + 00, 0x6b, // 107 = FieldRefNum + 00, 0x04, + 00, 0x02, 0x93, 0x47, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + }, + in1: false, + }, + wantAdvance: 36, + wantToken: []byte{ + 0, + 1, + 0, 0, + 0, 00, 00, 0x04, + 00, 00, 00, 0x00, + 00, 00, 00, 0x10, + 00, 00, 00, 0x10, + 00, 02, + 00, 0x6c, // 108 - FieldTransferSize + 00, 02, + 0x63, 0x3b, + 00, 0x6b, // 107 = FieldRefNum + 00, 0x04, + 00, 0x02, 0x93, 0x47, + }, + wantErr: assert.NoError, + }, + { + name: "when two full transactions are provided", + args: args{ + data: []byte{ + 0, + 1, + 0, 0, + 0, 00, 00, 0x04, + 00, 00, 00, 0x00, + 00, 00, 00, 0x10, + 00, 00, 00, 0x10, + 00, 02, + 00, 0x6c, // 108 - FieldTransferSize + 00, 02, + 0x63, 0x3b, + 00, 0x6b, // 107 = FieldRefNum + 00, 0x04, + 00, 0x02, 0x93, 0x47, + 0, + 1, + 0, 0, + 0, 00, 00, 0x04, + 00, 00, 00, 0x00, + 00, 00, 00, 0x10, + 00, 00, 00, 0x10, + 00, 02, + 00, 0x6c, // 108 - FieldTransferSize + 00, 02, + 0x63, 0x3b, + 00, 0x6b, // 107 = FieldRefNum + 00, 0x04, + 00, 0x02, 0x93, 0x47, + }, + in1: false, + }, + wantAdvance: 36, + wantToken: []byte{ + 0, + 1, + 0, 0, + 0, 00, 00, 0x04, + 00, 00, 00, 0x00, + 00, 00, 00, 0x10, + 00, 00, 00, 0x10, + 00, 02, + 00, 0x6c, // 108 - FieldTransferSize + 00, 02, + 0x63, 0x3b, + 00, 0x6b, // 107 = FieldRefNum + 00, 0x04, + 00, 0x02, 0x93, 0x47, }, + wantErr: assert.NoError, }, } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gotAdvance, gotToken, err := transactionScanner(tt.args.data, tt.args.in1) + if !tt.wantErr(t, err, fmt.Sprintf("transactionScanner(%v, %v)", tt.args.data, tt.args.in1)) { + return + } + assert.Equalf(t, tt.wantAdvance, gotAdvance, "transactionScanner(%v, %v)", tt.args.data, tt.args.in1) + assert.Equalf(t, tt.wantToken, gotToken, "transactionScanner(%v, %v)", tt.args.data, tt.args.in1) + }) + } +} +func TestTransaction_Read(t1 *testing.T) { + type fields struct { + clientID *[]byte + Flags byte + IsReply byte + Type []byte + ID []byte + ErrorCode []byte + TotalSize []byte + DataSize []byte + ParamCount []byte + Fields []Field + readOffset int + } type args struct { - buf []byte + p []byte } tests := []struct { - name string - args args - want *Transaction - want1 int - wantErr bool + name string + fields fields + args args + want int + wantErr assert.ErrorAssertionFunc + wantBytes []byte }{ { - name: "when buf contains all bytes for a single transaction", + name: "returns transaction bytes", + fields: fields{ + Flags: 0x00, + IsReply: 0x01, + Type: []byte{0, 0}, + ID: []byte{0x9a, 0xcb, 0x04, 0x42}, + ErrorCode: []byte{0, 0, 0, 0}, + Fields: []Field{ + NewField(FieldData, []byte("TEST")), + }, + }, args: args{ - buf: sampleTransaction.Payload(), + p: make([]byte, 1024), }, - want: sampleTransaction, - want1: len(sampleTransaction.Payload()), - wantErr: false, + want: 30, + wantErr: assert.NoError, + wantBytes: []byte{0x0, 0x1, 0x0, 0x0, 0x9a, 0xcb, 0x4, 0x42, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0xa, 0x0, 0x1, 0x0, 0x65, 0x0, 0x4, 0x54, 0x45, 0x53, 0x54}, }, { - name: "when len(buf) is less than the length of the transaction", + name: "returns transaction bytes from readOffset", + fields: fields{ + Flags: 0x00, + IsReply: 0x01, + Type: []byte{0, 0}, + ID: []byte{0x9a, 0xcb, 0x04, 0x42}, + ErrorCode: []byte{0, 0, 0, 0}, + Fields: []Field{ + NewField(FieldData, []byte("TEST")), + }, + readOffset: 20, + }, args: args{ - buf: sampleTransaction.Payload()[:len(sampleTransaction.Payload())-1], + p: make([]byte, 1024), }, - want: nil, - want1: 0, - wantErr: true, + want: 10, + wantErr: assert.NoError, + wantBytes: []byte{0x0, 0x1, 0x0, 0x65, 0x0, 0x4, 0x54, 0x45, 0x53, 0x54}, + }, + { + name: "returns io.EOF when all bytes read", + fields: fields{ + Flags: 0x00, + IsReply: 0x01, + Type: []byte{0, 0}, + ID: []byte{0x9a, 0xcb, 0x04, 0x42}, + ErrorCode: []byte{0, 0, 0, 0}, + Fields: []Field{ + NewField(FieldData, []byte("TEST")), + }, + readOffset: 30, + }, + args: args{ + p: make([]byte, 1024), + }, + want: 0, + wantErr: assert.Error, + wantBytes: []byte{}, }, } for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, got1, err := ReadTransaction(tt.args.buf) - if (err != nil) != tt.wantErr { - t.Errorf("ReadTransaction() error = %v, wantErr %v", err, tt.wantErr) - return + t1.Run(tt.name, func(t1 *testing.T) { + t := &Transaction{ + clientID: tt.fields.clientID, + Flags: tt.fields.Flags, + IsReply: tt.fields.IsReply, + Type: tt.fields.Type, + ID: tt.fields.ID, + ErrorCode: tt.fields.ErrorCode, + TotalSize: tt.fields.TotalSize, + DataSize: tt.fields.DataSize, + ParamCount: tt.fields.ParamCount, + Fields: tt.fields.Fields, + readOffset: tt.fields.readOffset, } - if !assert.Equal(t, tt.want, got) { - t.Errorf("ReadTransaction() got = %v, want %v", got, tt.want) - } - if got1 != tt.want1 { - t.Errorf("ReadTransaction() got1 = %v, want %v", got1, tt.want1) + got, err := t.Read(tt.args.p) + if !tt.wantErr(t1, err, fmt.Sprintf("Read(%v)", tt.args.p)) { + return } + assert.Equalf(t1, tt.want, got, "Read(%v)", tt.args.p) + assert.Equalf(t1, tt.wantBytes, tt.args.p[:got], "Read(%v)", tt.args.p) }) } }