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) - 1 { log.Fatalf("n not equal: %d != %d", n, len(data) - 1) } } 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) - 1 { log.Fatalf("n not equal: %d != %d", n, len(data) - 1) } } // 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; arrayCase(&dest) } } } `) }