Matthias Andreas Benkard | 261532a | 2021-12-12 20:09:27 +0100 | [diff] [blame] | 1 | package eu.mulk.jgvariant.core; |
| 2 | |
| 3 | import static java.nio.ByteOrder.LITTLE_ENDIAN; |
| 4 | import static java.nio.charset.StandardCharsets.UTF_8; |
| 5 | import static org.junit.jupiter.api.Assertions.assertEquals; |
| 6 | |
| 7 | import eu.mulk.jgvariant.core.Value.Array; |
| 8 | import eu.mulk.jgvariant.core.Value.Bool; |
| 9 | import eu.mulk.jgvariant.core.Value.Int32; |
| 10 | import eu.mulk.jgvariant.core.Value.Int8; |
| 11 | import eu.mulk.jgvariant.core.Value.Maybe; |
| 12 | import eu.mulk.jgvariant.core.Value.Str; |
| 13 | import eu.mulk.jgvariant.core.Value.Structure; |
| 14 | import java.nio.ByteBuffer; |
| 15 | import java.util.List; |
| 16 | import java.util.Optional; |
| 17 | import org.junit.jupiter.api.Test; |
| 18 | |
| 19 | /** |
| 20 | * Tests based on the examples given in <a |
| 21 | * href="https://people.gnome.org/~desrt/gvariant-serialisation.pdf">~desrt/gvariant-serialisation.pdf</a>. |
| 22 | */ |
| 23 | class DecoderTest { |
| 24 | |
| 25 | @Test |
| 26 | void testString() { |
| 27 | var data = new byte[] {0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x00}; |
| 28 | var decoder = Decoder.ofStr(UTF_8); |
| 29 | assertEquals(new Str("hello world"), decoder.decode(ByteBuffer.wrap(data))); |
| 30 | } |
| 31 | |
| 32 | @Test |
| 33 | void testMaybe() { |
| 34 | var data = |
| 35 | new byte[] {0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x00, 0x00}; |
| 36 | var decoder = Decoder.ofMaybe(Decoder.ofStr(UTF_8)); |
| 37 | assertEquals( |
| 38 | new Maybe<>(Optional.of(new Str("hello world"))), decoder.decode(ByteBuffer.wrap(data))); |
| 39 | } |
| 40 | |
| 41 | @Test |
| 42 | void testBooleanArray() { |
| 43 | var data = new byte[] {0x01, 0x00, 0x00, 0x01, 0x01}; |
Matthias Andreas Benkard | 4c32c39 | 2021-12-12 21:23:53 +0100 | [diff] [blame^] | 44 | var decoder = Decoder.ofArray(Decoder.ofBool()); |
Matthias Andreas Benkard | 261532a | 2021-12-12 20:09:27 +0100 | [diff] [blame] | 45 | assertEquals( |
| 46 | new Array<>(List.of(Bool.TRUE, Bool.FALSE, Bool.FALSE, Bool.TRUE, Bool.TRUE)), |
| 47 | decoder.decode(ByteBuffer.wrap(data))); |
| 48 | } |
| 49 | |
| 50 | @Test |
| 51 | void testStructure() { |
| 52 | var data = |
| 53 | new byte[] { |
| 54 | 0x66, 0x6F, 0x6F, 0x00, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, 0x04 |
| 55 | }; |
| 56 | |
| 57 | record TestRecord(Str s, Int32 i) {} |
| 58 | |
| 59 | var decoder = Decoder.ofStructure(TestRecord.class, Decoder.ofStr(UTF_8), Decoder.ofInt32()); |
| 60 | assertEquals( |
| 61 | new Structure<>(new TestRecord(new Str("foo"), new Int32(-1))), |
| 62 | decoder.decode(ByteBuffer.wrap(data))); |
| 63 | } |
| 64 | |
| 65 | @Test |
| 66 | void testComplexStructureArray() { |
| 67 | var data = |
| 68 | new byte[] { |
| 69 | 0x68, |
| 70 | 0x69, |
| 71 | 0x00, |
| 72 | 0x00, |
| 73 | (byte) 0xfe, |
| 74 | (byte) 0xff, |
| 75 | (byte) 0xff, |
| 76 | (byte) 0xff, |
| 77 | 0x03, |
| 78 | 0x00, |
| 79 | 0x00, |
| 80 | 0x00, |
| 81 | 0x62, |
| 82 | 0x79, |
| 83 | 0x65, |
| 84 | 0x00, |
| 85 | (byte) 0xff, |
| 86 | (byte) 0xff, |
| 87 | (byte) 0xff, |
| 88 | (byte) 0xff, |
| 89 | 0x04, |
| 90 | 0x09, |
| 91 | 0x15 |
| 92 | }; |
| 93 | |
| 94 | record TestRecord(Str s, Int32 i) {} |
| 95 | |
| 96 | var decoder = |
| 97 | Decoder.ofArray( |
| 98 | Decoder.ofStructure( |
| 99 | TestRecord.class, |
| 100 | Decoder.ofStr(UTF_8), |
| 101 | Decoder.ofInt32().withByteOrder(LITTLE_ENDIAN))); |
| 102 | assertEquals( |
| 103 | new Array<>( |
| 104 | List.of( |
| 105 | new Structure<>(new TestRecord(new Str("hi"), new Int32(-2))), |
| 106 | new Structure<>(new TestRecord(new Str("bye"), new Int32(-1))))), |
| 107 | decoder.decode(ByteBuffer.wrap(data))); |
| 108 | } |
| 109 | |
| 110 | @Test |
| 111 | void testStringArray() { |
| 112 | var data = |
| 113 | new byte[] { |
| 114 | 0x69, 0x00, 0x63, 0x61, 0x6E, 0x00, 0x68, 0x61, 0x73, 0x00, 0x73, 0x74, 0x72, 0x69, 0x6E, |
| 115 | 0x67, 0x73, 0x3F, 0x00, 0x02, 0x06, 0x0a, 0x13 |
| 116 | }; |
| 117 | var decoder = Decoder.ofArray(Decoder.ofStr(UTF_8)); |
| 118 | assertEquals( |
| 119 | new Array<>(List.of(new Str("i"), new Str("can"), new Str("has"), new Str("strings?"))), |
| 120 | decoder.decode(ByteBuffer.wrap(data))); |
| 121 | } |
| 122 | |
| 123 | @Test |
| 124 | void testNestedStructure() { |
| 125 | var data = |
| 126 | new byte[] { |
| 127 | 0x69, 0x63, 0x61, 0x6E, 0x00, 0x68, 0x61, 0x73, 0x00, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, |
| 128 | 0x73, 0x3F, 0x00, 0x04, 0x0d, 0x05 |
| 129 | }; |
| 130 | |
| 131 | record TestChild(Int8 b, Str s) {} |
| 132 | record TestParent(Structure<TestChild> tc, Array<Str> as) {} |
| 133 | |
| 134 | var decoder = |
| 135 | Decoder.ofStructure( |
| 136 | TestParent.class, |
| 137 | Decoder.ofStructure(TestChild.class, Decoder.ofInt8(), Decoder.ofStr(UTF_8)), |
| 138 | Decoder.ofArray(Decoder.ofStr(UTF_8))); |
| 139 | |
| 140 | assertEquals( |
| 141 | new Structure<>( |
| 142 | new TestParent( |
| 143 | new Structure<>(new TestChild(new Int8((byte) 0x69), new Str("can"))), |
| 144 | new Array<>(List.of(new Str("has"), new Str("strings?"))))), |
| 145 | decoder.decode(ByteBuffer.wrap(data))); |
| 146 | } |
| 147 | |
| 148 | @Test |
| 149 | void testSimpleStructure() { |
| 150 | var data = new byte[] {0x60, 0x70}; |
| 151 | |
| 152 | record TestRecord(Int8 b1, Int8 b2) {} |
| 153 | |
| 154 | var decoder = |
| 155 | Decoder.ofStructure( |
| 156 | TestRecord.class, |
| 157 | Decoder.ofInt8().withByteOrder(LITTLE_ENDIAN), |
| 158 | Decoder.ofInt8().withByteOrder(LITTLE_ENDIAN)); |
| 159 | |
| 160 | assertEquals( |
| 161 | new Structure<>(new TestRecord(new Int8((byte) 0x60), new Int8((byte) 0x70))), |
| 162 | decoder.decode(ByteBuffer.wrap(data))); |
| 163 | } |
| 164 | |
| 165 | @Test |
| 166 | void testPaddedStructureRight() { |
| 167 | var data = new byte[] {0x60, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00}; |
| 168 | |
| 169 | record TestRecord(Int32 b1, Int8 b2) {} |
| 170 | |
| 171 | var decoder = |
| 172 | Decoder.ofStructure( |
| 173 | TestRecord.class, |
| 174 | Decoder.ofInt32().withByteOrder(LITTLE_ENDIAN), |
| 175 | Decoder.ofInt8().withByteOrder(LITTLE_ENDIAN)); |
| 176 | |
| 177 | assertEquals( |
| 178 | new Structure<>(new TestRecord(new Int32(0x60), new Int8((byte) 0x70))), |
| 179 | decoder.decode(ByteBuffer.wrap(data))); |
| 180 | } |
| 181 | |
| 182 | @Test |
| 183 | void testPaddedStructureLeft() { |
| 184 | var data = new byte[] {0x60, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00}; |
| 185 | |
| 186 | record TestRecord(Int8 b1, Int32 b2) {} |
| 187 | |
| 188 | var decoder = |
| 189 | Decoder.ofStructure( |
| 190 | TestRecord.class, |
| 191 | Decoder.ofInt8().withByteOrder(LITTLE_ENDIAN), |
| 192 | Decoder.ofInt32().withByteOrder(LITTLE_ENDIAN)); |
| 193 | |
| 194 | assertEquals( |
| 195 | new Structure<>(new TestRecord(new Int8((byte) 0x60), new Int32(0x70))), |
| 196 | decoder.decode(ByteBuffer.wrap(data))); |
| 197 | } |
| 198 | |
| 199 | @Test |
| 200 | void testSimpleStructureArray() { |
| 201 | var data = |
| 202 | new byte[] { |
| 203 | 0x60, |
| 204 | 0x00, |
| 205 | 0x00, |
| 206 | 0x00, |
| 207 | 0x70, |
| 208 | 0x00, |
| 209 | 0x00, |
| 210 | 0x00, |
| 211 | (byte) 0x88, |
| 212 | 0x02, |
| 213 | 0x00, |
| 214 | 0x00, |
| 215 | (byte) 0xF7, |
| 216 | 0x00, |
| 217 | 0x00, |
| 218 | 0x00 |
| 219 | }; |
| 220 | |
| 221 | record TestRecord(Int32 b1, Int8 b2) {} |
| 222 | |
| 223 | var decoder = |
| 224 | Decoder.ofArray( |
| 225 | Decoder.ofStructure( |
| 226 | TestRecord.class, |
| 227 | Decoder.ofInt32().withByteOrder(LITTLE_ENDIAN), |
| 228 | Decoder.ofInt8().withByteOrder(LITTLE_ENDIAN))); |
| 229 | |
| 230 | assertEquals( |
| 231 | new Array<>( |
| 232 | List.of( |
| 233 | new Structure<>(new TestRecord(new Int32(96), new Int8((byte) 0x70))), |
| 234 | new Structure<>(new TestRecord(new Int32(648), new Int8((byte) 0xf7))))), |
| 235 | decoder.decode(ByteBuffer.wrap(data))); |
| 236 | } |
| 237 | |
| 238 | @Test |
| 239 | void testByteArray() { |
| 240 | var data = new byte[] {0x04, 0x05, 0x06, 0x07}; |
| 241 | |
| 242 | var decoder = Decoder.ofArray(Decoder.ofInt8()); |
| 243 | |
| 244 | assertEquals( |
| 245 | new Array<>( |
| 246 | List.of( |
| 247 | new Int8((byte) 0x04), |
| 248 | new Int8((byte) 0x05), |
| 249 | new Int8((byte) 0x06), |
| 250 | new Int8((byte) 0x07))), |
| 251 | decoder.decode(ByteBuffer.wrap(data))); |
| 252 | } |
| 253 | |
| 254 | @Test |
| 255 | void testIntegerArray() { |
| 256 | var data = new byte[] {0x04, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00}; |
| 257 | |
| 258 | var decoder = Decoder.ofArray(Decoder.ofInt32().withByteOrder(LITTLE_ENDIAN)); |
| 259 | |
| 260 | assertEquals( |
| 261 | new Array<>(List.of(new Int32(4), new Int32(258))), decoder.decode(ByteBuffer.wrap(data))); |
| 262 | } |
| 263 | |
| 264 | @Test |
| 265 | void testDictionaryEntry() { |
| 266 | var data = |
| 267 | new byte[] {0x61, 0x20, 0x6B, 0x65, 0x79, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x06}; |
| 268 | |
| 269 | record TestEntry(Str key, Int32 value) {} |
| 270 | |
| 271 | var decoder = |
| 272 | Decoder.ofStructure( |
| 273 | TestEntry.class, Decoder.ofStr(UTF_8), Decoder.ofInt32().withByteOrder(LITTLE_ENDIAN)); |
| 274 | assertEquals( |
| 275 | new Structure<>(new TestEntry(new Str("a key"), new Int32(514))), |
| 276 | decoder.decode(ByteBuffer.wrap(data))); |
| 277 | } |
| 278 | } |