1 module tests.protocol_unit; 2 3 4 import cerealed; 5 import unit_threaded; 6 import core.exception; 7 8 9 struct Unit { 10 ushort us; 11 ubyte ub1; 12 ubyte ub2; 13 } 14 15 struct Packet { 16 ubyte ub1; 17 ushort length; 18 ubyte ub2; 19 @ArrayLength("length") Unit[] units; 20 } 21 22 23 void testUnits() { 24 ubyte[] bytes = [3, 0, 4, 9, 0, 7, 1, 2, 0, 6, 2, 3, 0, 5, 4, 5, 0, 4, 9, 8]; 25 auto pkt = decerealise!Packet(bytes); 26 27 pkt.ub1.shouldEqual(3); 28 pkt.length.shouldEqual(4); 29 pkt.ub2.shouldEqual(9); 30 pkt.units.length.shouldEqual(pkt.length); 31 32 pkt.units[1].us.shouldEqual(6); 33 pkt.units[1].ub1.shouldEqual(2); 34 pkt.units[1].ub2.shouldEqual(3); 35 36 auto enc = Cerealiser(); 37 enc ~= pkt; 38 enc.bytes.shouldEqual(bytes); 39 } 40 41 42 struct PacketWithArrayLengthExpr { 43 static struct Header { 44 ubyte ub; 45 ushort us; 46 ushort length; 47 } 48 49 enum headerSize = unalignedSizeof!Header; 50 alias header this; 51 52 Header header; 53 @ArrayLength("length - headerSize") Unit[] units; 54 } 55 56 void testArrayLengthExpr() { 57 immutable ubyte[] bytes = [3, 0, 7, 0, 8, //header 58 0, 7, 1, 2, 59 0, 6, 2, 3, 60 0, 5, 4, 5]; 61 auto pkt = decerealise!PacketWithArrayLengthExpr(bytes); 62 63 pkt.ub.shouldEqual(3); 64 pkt.us.shouldEqual(7); 65 pkt.units.length.shouldEqual(3); 66 67 pkt.units[2].us.shouldEqual(5); 68 pkt.units[2].ub1.shouldEqual(4); 69 pkt.units[2].ub2.shouldEqual(5); 70 71 auto enc = Cerealiser(); 72 enc ~= pkt; 73 enc.bytes.shouldEqual(bytes); 74 } 75 76 77 struct NegativeStruct { 78 enum len = -1; 79 ushort us; 80 @ArrayLength("len") Unit[] units; 81 } 82 83 void testNegativeLength() { 84 immutable ubyte[] bytes = [1, 2, 3, 4, 5]; 85 decerealise!NegativeStruct(bytes).shouldThrow!CerealException; 86 } 87 88 89 void testNotEnoughBytes() { 90 immutable ubyte[] bytes = [3, 0, 7, 0, 8, //header 91 0, 7]; //truncated 92 decerealise!PacketWithArrayLengthExpr(bytes).shouldThrow!CerealException; 93 } 94 95 96 struct PacketWithLengthInBytes { 97 static struct Header { 98 ubyte ub; 99 ushort lengthNoHeader; 100 } 101 102 enum headerSize = unalignedSizeof!Header; 103 alias header this; 104 105 Header header; 106 @LengthInBytes("lengthNoHeader - headerSize") Unit[] units; 107 } 108 109 void testLengthInBytes() { 110 immutable ubyte[] bytes = [ 7, 0, 11, //header (11 bytes = hdr + 2 units of 4 bytes each) 111 0, 3, 1, 2, 112 0, 9, 3, 4, 113 ]; 114 auto pkt = decerealise!PacketWithLengthInBytes(bytes); 115 116 pkt.ub.shouldEqual(7); 117 pkt.lengthNoHeader.shouldEqual(11); 118 pkt.units.length.shouldEqual(2); 119 120 pkt.units[0].us.shouldEqual(3); 121 pkt.units[0].ub1.shouldEqual(1); 122 pkt.units[0].ub2.shouldEqual(2); 123 124 pkt.units[1].us.shouldEqual(9); 125 pkt.units[1].ub1.shouldEqual(3); 126 pkt.units[1].ub2.shouldEqual(4); 127 128 auto enc = Cerealiser(); 129 enc ~= pkt; 130 enc.bytes.shouldEqual(bytes); 131 } 132 133 134 struct BigUnit { 135 int i1; 136 int i2; 137 } 138 139 struct BigUnitPacket { 140 enum headerSize = totalLength.sizeof; 141 ushort totalLength; 142 @LengthInBytes("totalLength - headerSize") BigUnit[] units; 143 } 144 145 void testLengthInBytesOneUnit() { 146 immutable ubyte[] bytes = [ 0, 10, //totalLength = 1 unit of size 8 + header size of 1 147 0, 0, 0, 1, 0, 0, 0, 2 148 ]; 149 auto pkt = decerealise!BigUnitPacket(bytes); 150 151 pkt.totalLength.shouldEqual(bytes.length); 152 pkt.units.length.shouldEqual(1); 153 pkt.units[0].i1.shouldEqual(1); 154 pkt.units[0].i2.shouldEqual(2); 155 156 auto enc = Cerealiser(); 157 enc ~= pkt; 158 enc.bytes.shouldEqual(bytes); 159 } 160 161 162 @("RestOfPacket with LengthInBytes") 163 unittest { 164 struct Small { 165 ushort v; 166 } 167 struct Unit { 168 ushort length; 169 @LengthInBytes("length - 2") Small[] smalls; 170 } 171 struct Struct { 172 @RestOfPacket Unit[] units; 173 } 174 immutable ubyte[] bytes = 175 [ 176 0, 6, //length 177 0, 1, 0, 2, // smalls 178 0, 4, //length 179 0, 3, //smalls 180 ]; 181 182 auto dec = Decerealiser(bytes); 183 auto pkt = dec.value!Struct; 184 185 pkt.shouldEqual( 186 Struct([Unit(6, 187 [ 188 Small(1), 189 Small(2), 190 ] 191 ), 192 Unit(4, 193 [ 194 Small(3), 195 ] 196 )])); 197 }