382 lines
12 KiB
Go
382 lines
12 KiB
Go
package generate
|
|
|
|
// import "fmt"
|
|
import "testing"
|
|
|
|
// TODO: once everything has been ironed out, test that the public API of the
|
|
// generator is equal to something specific
|
|
|
|
var exampleProtocol = defaultProtocol()
|
|
|
|
func init() {
|
|
exampleProtocol.Messages[0x0000] = Message {
|
|
Name: "Connect",
|
|
Type: TypeTableDefined {
|
|
Fields: map[uint16] Field {
|
|
0x0000: Field { Name: "Name", Type: TypeString { } },
|
|
0x0001: Field { Name: "Password", Type: TypeString { } },
|
|
},
|
|
},
|
|
}
|
|
exampleProtocol.Messages[0x0001] = Message {
|
|
Name: "UserList",
|
|
Type: TypeTableDefined {
|
|
Fields: map[uint16] Field {
|
|
0x0000: Field { Name: "Users", Type: TypeArray { Element: TypeNamed { Name: "User" } } },
|
|
},
|
|
},
|
|
}
|
|
exampleProtocol.Messages[0x0002] = Message {
|
|
Name: "Pulse",
|
|
Type: TypeTableDefined {
|
|
Fields: map[uint16] Field {
|
|
0x0000: Field { Name: "Index", Type: TypeInt { Bits: 5 } },
|
|
0x0001: Field { Name: "Offset", Type: TypeInt { Bits: 16, Signed: true }},
|
|
0x0002: Field { Name: "X", Type: TypeFloat { Bits: 16 }},
|
|
0x0003: Field { Name: "Y", Type: TypeFloat { Bits: 32 }},
|
|
0x0004: Field { Name: "Z", Type: TypeFloat { Bits: 64 }},
|
|
},
|
|
},
|
|
}
|
|
exampleProtocol.Messages[0x0003] = Message {
|
|
Name: "NestedArray",
|
|
Type: TypeArray { Element: TypeArray { Element: TypeInt { Bits: 8 } } },
|
|
}
|
|
exampleProtocol.Messages[0x0004] = Message {
|
|
Name: "Integers",
|
|
Type: TypeTableDefined {
|
|
Fields: map[uint16] Field {
|
|
0x0000: Field { Name: "U5", Type: TypeInt { Bits: 5 } },
|
|
0x0001: Field { Name: "U8", Type: TypeInt { Bits: 8 } },
|
|
0x0002: Field { Name: "U16", Type: TypeInt { Bits: 16 } },
|
|
0x0003: Field { Name: "U32", Type: TypeInt { Bits: 32 } },
|
|
0x0004: Field { Name: "U64", Type: TypeInt { Bits: 64 } },
|
|
0x0006: Field { Name: "I8", Type: TypeInt { Bits: 8, Signed: true } },
|
|
0x0007: Field { Name: "I16", Type: TypeInt { Bits: 16, Signed: true } },
|
|
0x0008: Field { Name: "I32", Type: TypeInt { Bits: 32, Signed: true } },
|
|
0x0009: Field { Name: "I64", Type: TypeInt { Bits: 64, Signed: true } },
|
|
0x000B: Field { Name: "NI8", Type: TypeInt { Bits: 8, Signed: true } },
|
|
0x000C: Field { Name: "NI16",Type: TypeInt { Bits: 16, Signed: true } },
|
|
0x000D: Field { Name: "NI32",Type: TypeInt { Bits: 32, Signed: true } },
|
|
0x000E: Field { Name: "NI64",Type: TypeInt { Bits: 64, Signed: true } },
|
|
},
|
|
},
|
|
}
|
|
exampleProtocol.Types["User"] = TypeTableDefined {
|
|
Fields: map[uint16] Field {
|
|
0x0000: Field { Name: "Name", Type: TypeString { } },
|
|
0x0001: Field { Name: "Bio", Type: TypeString { } },
|
|
0x0002: Field { Name: "Followers", Type: TypeInt { Bits: 32 } },
|
|
},
|
|
}
|
|
}
|
|
|
|
func TestGenerateRunEncodeDecode(test *testing.T) {
|
|
testGenerateRun(test, &exampleProtocol, "encode-decode", `
|
|
// imports
|
|
`, `
|
|
log.Println("MessageConnect")
|
|
messageConnect := MessageConnect {
|
|
Name: "rarity",
|
|
Password: "gems",
|
|
}
|
|
testEncodeDecode(
|
|
&messageConnect,
|
|
tu.S(0xE1, 0x02).AddVar(
|
|
[]byte { 0x00, 0x00, 0x86, 'r', 'a', 'r', 'i', 't', 'y' },
|
|
[]byte { 0x00, 0x01, 0x84, 'g', 'e', 'm', 's' },
|
|
))
|
|
log.Println("MessageUserList")
|
|
messageUserList := MessageUserList {
|
|
Users: []User {
|
|
User {
|
|
Name: "rarity",
|
|
Bio: "asdjads",
|
|
Followers: 0x324,
|
|
},
|
|
User {
|
|
Name: "deez nuts",
|
|
Bio: "logy",
|
|
Followers: 0x8000,
|
|
},
|
|
User {
|
|
Name: "creekflow",
|
|
Bio: "im creekflow",
|
|
Followers: 0x3894,
|
|
},
|
|
},
|
|
}
|
|
testEncodeDecode(
|
|
&messageUserList,
|
|
tu.S(0xE1, 0x01, 0x00, 0x00,
|
|
0xC1, 0x03, 0xE1,
|
|
).Add(0x03).AddVar(
|
|
[]byte { 0x00, 0x00, 0x86, 'r', 'a', 'r', 'i', 't', 'y' },
|
|
[]byte { 0x00, 0x01, 0x87, 'a', 's', 'd', 'j', 'a', 'd', 's' },
|
|
[]byte { 0x00, 0x02, 0x23, 0x00, 0x00, 0x03, 0x24 },
|
|
).Add(0x03).AddVar(
|
|
[]byte { 0x00, 0x00, 0x89, 'd', 'e', 'e', 'z', ' ', 'n', 'u', 't', 's' },
|
|
[]byte { 0x00, 0x01, 0x84, 'l', 'o', 'g', 'y' },
|
|
[]byte { 0x00, 0x02, 0x23, 0x00, 0x00, 0x80, 0x00 },
|
|
).Add(0x03).AddVar(
|
|
[]byte { 0x00, 0x00, 0x89, 'c', 'r', 'e', 'e', 'k', 'f', 'l', 'o', 'w' },
|
|
[]byte { 0x00, 0x01, 0x8C, 'i', 'm', ' ', 'c', 'r', 'e', 'e', 'k', 'f',
|
|
'l', 'o', 'w' },
|
|
[]byte { 0x00, 0x02, 0x23, 0x00, 0x00, 0x38, 0x94 },
|
|
))
|
|
log.Println("MessagePulse")
|
|
messagePulse := MessagePulse {
|
|
Index: 9,
|
|
Offset: -0x3521,
|
|
X: 45.375,
|
|
Y: 294.1,
|
|
Z: 384729384.234892034,
|
|
}
|
|
testEncodeDecode(
|
|
&messagePulse,
|
|
tu.S(0xE1, 0x05).AddVar(
|
|
[]byte { 0x00, 0x00, 0x09 },
|
|
[]byte { 0x00, 0x01, 0x41, 0xCA, 0xDF },
|
|
[]byte { 0x00, 0x02, 0x61, 0x51, 0xAC },
|
|
[]byte { 0x00, 0x03, 0x63, 0x43, 0x93, 0x0C, 0xCD },
|
|
[]byte { 0x00, 0x04, 0x67, 0x41, 0xB6, 0xEE, 0x81, 0x28, 0x3C, 0x21, 0xE2 },
|
|
))
|
|
log.Println("MessageNestedArray")
|
|
uint8s := func(n int) []uint8 {
|
|
array := make([]uint8, n)
|
|
for index := range array {
|
|
array[index] = uint8(index + 1) | 0xF0
|
|
}
|
|
return array
|
|
}
|
|
messageNestedArray := MessageNestedArray {
|
|
uint8s(6),
|
|
uint8s(35),
|
|
}
|
|
testEncodeDecode(
|
|
&messageNestedArray,
|
|
tu.S(0xC1, 0x02, 0xC1,
|
|
0x06, 0x20, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6,
|
|
35, 0x20, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6,
|
|
0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC,
|
|
0xFD, 0xFE, 0xFF, 0xF0, 0xF1, 0xF2,
|
|
0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
|
|
0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE,
|
|
0xFF, 0xF0, 0xF1, 0xF2, 0xF3))
|
|
log.Println("MessageIntegers")
|
|
messageIntegers := MessageIntegers {
|
|
U5: 0x13,
|
|
U8: 0xC9,
|
|
U16: 0x34C9,
|
|
U32: 0x10E134C9,
|
|
U64: 0x639109BC10E134C9,
|
|
I8: 0x35,
|
|
I16: 0x34C9,
|
|
I32: 0x10E134C9,
|
|
I64: 0x639109BC10E134C9,
|
|
NI8: -0x35,
|
|
NI16: -0x34C9,
|
|
NI32: -0x10E134C9,
|
|
NI64: -0x639109BC10E134C9,
|
|
}
|
|
testEncodeDecode(
|
|
&messageIntegers,
|
|
tu.S(0xE1, 13).AddVar(
|
|
[]byte { 0x00, 0x00, 0x13 },
|
|
[]byte { 0x00, 0x01, 0x20, 0xC9 },
|
|
[]byte { 0x00, 0x02, 0x21, 0x34, 0xC9 },
|
|
[]byte { 0x00, 0x03, 0x23, 0x10, 0xE1, 0x34, 0xC9 },
|
|
[]byte { 0x00, 0x04, 0x27, 0x63, 0x91, 0x09, 0xBC, 0x10, 0xE1, 0x34, 0xC9 },
|
|
[]byte { 0x00, 0x06, 0x40, 0x35 },
|
|
[]byte { 0x00, 0x07, 0x41, 0x34, 0xC9 },
|
|
[]byte { 0x00, 0x08, 0x43, 0x10, 0xE1, 0x34, 0xC9 },
|
|
[]byte { 0x00, 0x09, 0x47, 0x63, 0x91, 0x09, 0xBC, 0x10, 0xE1, 0x34, 0xC9 },
|
|
[]byte { 0x00, 0x0B, 0x40, 0xCB },
|
|
[]byte { 0x00, 0x0C, 0x41, 0xCB, 0x37 },
|
|
[]byte { 0x00, 0x0D, 0x43, 0xEF, 0x1E, 0xCB, 0x37 },
|
|
[]byte { 0x00, 0x0E, 0x47, 0x9C, 0x6E, 0xF6, 0x43, 0xEF, 0x1E, 0xCB, 0x37 },
|
|
))
|
|
`)
|
|
}
|
|
|
|
func TestGenerateRunDecodeWrongType(test *testing.T) {
|
|
protocol := defaultProtocol()
|
|
protocol.Messages[0x0000] = Message {
|
|
Name: "Uint5",
|
|
Type: TypeInt { Bits: 5 },
|
|
}
|
|
protocol.Messages[0x0001] = Message {
|
|
Name: "Uint8",
|
|
Type: TypeInt { Bits: 8 },
|
|
}
|
|
protocol.Messages[0x0002] = Message {
|
|
Name: "Uint16",
|
|
Type: TypeInt { Bits: 16 },
|
|
}
|
|
protocol.Messages[0x0003] = Message {
|
|
Name: "Uint32",
|
|
Type: TypeInt { Bits: 32 },
|
|
}
|
|
protocol.Messages[0x0004] = Message {
|
|
Name: "Uint64",
|
|
Type: TypeInt { Bits: 64 },
|
|
}
|
|
protocol.Messages[0x0005] = Message {
|
|
Name: "Int8",
|
|
Type: TypeInt { Bits: 8 },
|
|
}
|
|
protocol.Messages[0x0006] = Message {
|
|
Name: "Int16",
|
|
Type: TypeInt { Bits: 16 },
|
|
}
|
|
protocol.Messages[0x0007] = Message {
|
|
Name: "Int32",
|
|
Type: TypeInt { Bits: 32 },
|
|
}
|
|
protocol.Messages[0x0008] = Message {
|
|
Name: "Int64",
|
|
Type: TypeInt { Bits: 64 },
|
|
}
|
|
protocol.Messages[0x0009] = Message {
|
|
Name: "String",
|
|
Type: TypeString { },
|
|
}
|
|
protocol.Messages[0x000A] = Message {
|
|
Name: "Buffer",
|
|
Type: TypeBuffer { },
|
|
}
|
|
protocol.Messages[0x000B] = Message {
|
|
Name: "StringArray",
|
|
Type: TypeArray { Element: TypeString { } },
|
|
}
|
|
protocol.Messages[0x000C] = Message {
|
|
Name: "Table",
|
|
Type: TypeTable { },
|
|
}
|
|
protocol.Messages[0x000D] = Message {
|
|
Name: "TableDefined",
|
|
Type: TypeTableDefined {
|
|
Fields: map[uint16] Field {
|
|
0x0000: Field { Name: "Name", Type: TypeString { } },
|
|
0x0001: Field { Name: "Password", Type: TypeString { } },
|
|
},
|
|
},
|
|
}
|
|
|
|
testGenerateRun(test, &protocol, "decode-wrong-type", `
|
|
// imports
|
|
`, `
|
|
datas := [][]byte {
|
|
/* int8 */ []byte { byte(tape.LSI.WithCN(0)), 0x45 },
|
|
/* int16 */ []byte { byte(tape.LSI.WithCN(1)), 0x45, 0x67 },
|
|
/* int32 */ []byte { byte(tape.LSI.WithCN(3)), 0x45, 0x67, 0x89, 0xAB },
|
|
/* int64 */ []byte { byte(tape.LSI.WithCN(7)), 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23 },
|
|
/* uint5 */ []byte { byte(tape.SI.WithCN(12)) },
|
|
/* uint8 */ []byte { byte(tape.LI.WithCN(0)), 0x45 },
|
|
/* uint16 */ []byte { byte(tape.LI.WithCN(1)), 0x45, 0x67 },
|
|
/* uint32 */ []byte { byte(tape.LI.WithCN(3)), 0x45, 0x67, 0x89, 0xAB },
|
|
/* uint64 */ []byte { byte(tape.LI.WithCN(7)), 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23 },
|
|
/* string */ []byte { byte(tape.SBA.WithCN(7)), 'p', 'u', 'p', 'e', 'v', 'e', 'r' },
|
|
/* []byte */ []byte { byte(tape.SBA.WithCN(5)), 'b', 'l', 'a', 'r', 'g' },
|
|
/* []string */ []byte {
|
|
byte(tape.OTA.WithCN(0)), 2, byte(tape.LBA.WithCN(0)),
|
|
0x08, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23,
|
|
0x05, 0x11, 0x11, 0x11, 0x11, 0x11,
|
|
},
|
|
/* map[uint16] any */ []byte {
|
|
byte(tape.KTV.WithCN(0)), 2,
|
|
0x02, 0x23, byte(tape.LSI.WithCN(1)), 0x45, 0x67,
|
|
0x02, 0x23, byte(tape.LI.WithCN(3)), 0x45, 0x67, 0x89, 0xAB,
|
|
},
|
|
}
|
|
|
|
|
|
for index, data := range datas {
|
|
log.Printf("data %2d %v [%s]", index, tape.Tag(data[0]), tu.HexBytes(data[1:]))
|
|
// integers should only assign to other integers
|
|
if index > 8 {
|
|
cas := func(destination Message) {
|
|
n, err := destination.Decode(tape.NewDecoder(bytes.NewBuffer(data)))
|
|
if err != nil { log.Fatalf("error: %v | n: %d", err, n) }
|
|
reflectValue := reflect.ValueOf(destination).Elem()
|
|
if reflectValue.CanInt() {
|
|
if reflectValue.Int() != 0 {
|
|
log.Fatalf(
|
|
"destination not zero: %v",
|
|
reflectValue.Elem().Interface())
|
|
}
|
|
} else {
|
|
if reflectValue.Uint() != 0 {
|
|
log.Fatalf(
|
|
"destination not zero: %v",
|
|
reflectValue.Elem().Interface())
|
|
}
|
|
}
|
|
if n != len(data) {
|
|
log.Fatalf("n not equal: %d != %d", n, len(data))
|
|
}
|
|
}
|
|
log.Println("- MessageInt8")
|
|
{ var dest MessageInt8; cas(&dest) }
|
|
log.Println("- MessageInt16")
|
|
{ var dest MessageInt16; cas(&dest) }
|
|
log.Println("- MessageInt32")
|
|
{ var dest MessageInt32; cas(&dest) }
|
|
log.Println("- MessageInt64")
|
|
{ var dest MessageInt64; cas(&dest) }
|
|
log.Println("- MessageUint8")
|
|
{ var dest MessageUint8; cas(&dest) }
|
|
log.Println("- MessageUint16")
|
|
{ var dest MessageUint16; cas(&dest) }
|
|
log.Println("- MessageUint32")
|
|
{ var dest MessageUint32; cas(&dest) }
|
|
log.Println("- MessageUint64")
|
|
{ var dest MessageUint64; cas(&dest) }
|
|
}
|
|
arrayCase := func(destination Message) {
|
|
n, err := destination.Decode(tape.NewDecoder(bytes.NewBuffer(data)),)
|
|
if err != nil { log.Fatalf("error: %v | n: %d", err, n) }
|
|
reflectDestination := reflect.ValueOf(destination)
|
|
reflectValue := reflectDestination.Elem()
|
|
if reflectValue.Len() != 0 {
|
|
log.Fatalf("len(destination) not zero: %v", reflectValue.Interface())
|
|
}
|
|
if n != len(data) {
|
|
log.Fatalf("n not equal: %d != %d", n, len(data))
|
|
}
|
|
}
|
|
anyCase := func(destination Message) {
|
|
n, err := destination.Decode(tape.NewDecoder(bytes.NewBuffer(data)),)
|
|
if err != nil { log.Fatalf("error: %v | n: %d", err, n) }
|
|
reflectDestination := reflect.ValueOf(destination)
|
|
reflectValue := reflectDestination.Elem()
|
|
if reflectValue == reflect.Zero(reflectValue.Type()) {
|
|
log.Fatalf("len(destination) not zero: %v", reflectValue.Interface())
|
|
}
|
|
if n != len(data) {
|
|
log.Fatalf("n not equal: %d != %d", n, len(data))
|
|
}
|
|
}
|
|
// SBA/LBA types should only assign to other SBA/LBA types
|
|
if index != 9 && index != 10 {
|
|
log.Println("- MessageString")
|
|
{ var dest MessageString; arrayCase(&dest) }
|
|
log.Println("- MessageBuffer")
|
|
{ var dest MessageBuffer; arrayCase(&dest) }
|
|
}
|
|
// arrays should only assign to other arrays
|
|
if index != 11 {
|
|
log.Println("- MessageStringArray")
|
|
{ var dest MessageStringArray; arrayCase(&dest) }
|
|
}
|
|
// tables should only assign to other tables
|
|
if index != 12 {
|
|
log.Println("- MessageTable")
|
|
{ var dest = make(MessageTable); arrayCase(&dest) }
|
|
log.Println("- MessageTableDefined")
|
|
{ var dest MessageTableDefined; anyCase(&dest) }
|
|
}
|
|
}
|
|
`)
|
|
}
|