View Javadoc
1   package org.djutils.serialization;
2   
3   import static org.junit.jupiter.api.Assertions.assertEquals;
4   import static org.junit.jupiter.api.Assertions.assertFalse;
5   import static org.junit.jupiter.api.Assertions.assertNotEquals;
6   import static org.junit.jupiter.api.Assertions.assertNull;
7   import static org.junit.jupiter.api.Assertions.assertTrue;
8   import static org.junit.jupiter.api.Assertions.fail;
9   
10  import java.io.File;
11  import java.io.UnsupportedEncodingException;
12  import java.nio.ByteOrder;
13  import java.util.ArrayList;
14  import java.util.Arrays;
15  import java.util.List;
16  
17  import org.djunits.unit.AccelerationUnit;
18  import org.djunits.unit.AreaUnit;
19  import org.djunits.unit.DimensionlessUnit;
20  import org.djunits.unit.ElectricalCurrentUnit;
21  import org.djunits.unit.ElectricalResistanceUnit;
22  import org.djunits.unit.EnergyUnit;
23  import org.djunits.unit.LengthUnit;
24  import org.djunits.unit.SpeedUnit;
25  import org.djunits.unit.TimeUnit;
26  import org.djunits.value.ValueRuntimeException;
27  import org.djunits.value.storage.StorageType;
28  import org.djunits.value.vdouble.matrix.ElectricalCurrentMatrix;
29  import org.djunits.value.vdouble.scalar.Dimensionless;
30  import org.djunits.value.vdouble.scalar.Length;
31  import org.djunits.value.vdouble.vector.ElectricalCurrentVector;
32  import org.djunits.value.vdouble.vector.LengthVector;
33  import org.djunits.value.vdouble.vector.TimeVector;
34  import org.djunits.value.vdouble.vector.base.DoubleVector;
35  import org.djunits.value.vfloat.matrix.FloatElectricalResistanceMatrix;
36  import org.djunits.value.vfloat.scalar.FloatArea;
37  import org.djunits.value.vfloat.vector.FloatElectricalResistanceVector;
38  import org.djutils.decoderdumper.HexDumper;
39  import org.djutils.serialization.serializers.BasicSerializer;
40  import org.djutils.serialization.serializers.Pointer;
41  import org.djutils.serialization.util.SerialDataDumper;
42  import org.junit.jupiter.api.Test;
43  
44  /**
45   * Test message conversions.
46   * <p>
47   * Copyright (c) 2019-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
48   * BSD-style license. See <a href="https://sim0mq.org/docs/current/license.html">OpenTrafficSim License</a>.
49   * </p>
50   * @author <a href="https://www.tudelft.nl/averbraeck">Alexander Verbraeck</a>
51   * @author <a href="https://www.tudelft.nl/staff/p.knoppers/">Peter Knoppers</a>
52   */
53  public class Tests
54  {
55  
56      /**
57       * Basic test encoding and decoding of the basic types.
58       * @throws SerializationException when that happens uncaught this test has failed
59       */
60      @Test
61      public void simpleTests() throws SerializationException
62      {
63          int intValue = 123;
64          Integer integerValue = -456;
65          short shortValue = 234;
66          Short shortValue2 = -345;
67          long longValue = 98765L;
68          Long longValue2 = -98765L;
69          Byte byteValue = 12;
70          byte byteValue2 = -23;
71          float floatValue = 1.234f;
72          Float floatValue2 = -3.456f;
73          double doubleValue = 4.56789;
74          Double doubleValue2 = -4.56789;
75          boolean boolValue = true;
76          Boolean boolValue2 = false;
77          Character charValue = 'a';
78          char charValue2 = 'b';
79          String stringValue = "abcDEF123!@#ȦȧȨ\u0776\u0806\u080e";
80          Object[] objects = new Object[] {intValue, integerValue, shortValue, shortValue2, longValue, longValue2, byteValue,
81                  byteValue2, floatValue, floatValue2, doubleValue, doubleValue2, boolValue, boolValue2, charValue, charValue2,
82                  stringValue};
83          for (EndianUtil endianUtil : new EndianUtil[] {EndianUtil.BIG_ENDIAN, EndianUtil.LITTLE_ENDIAN})
84          {
85              for (boolean encodeUTF8 : new boolean[] {false, true})
86              {
87                  // System.out.println("" + endianUtil + ", UTF8=" + encodeUTF8);
88                  byte[] serialized = encodeUTF8 ? TypedMessage.encodeUTF8(endianUtil, objects)
89                          : TypedMessage.encodeUTF16(endianUtil, objects);
90                  System.out.print(HexDumper.hexDumper(serialized));
91                  System.out.print(SerialDataDumper.serialDataDumper(endianUtil, serialized));
92                  for (boolean primitive : new boolean[] {false, true})
93                  {
94                      Object[] decodedObjects = primitive ? TypedMessage.decodeToPrimitiveDataTypes(serialized, endianUtil)
95                              : TypedMessage.decodeToObjectDataTypes(serialized, endianUtil);
96                      assertEquals(objects.length, decodedObjects.length, "Size of decoded matches");
97                      for (int i = 0; i < objects.length; i++)
98                      {
99                          assertEquals(objects[i], decodedObjects[i],
100                                 "decoded object at index " + i + "(" + objects[i] + ") equals corresponding object in input");
101                     }
102                 }
103             }
104         }
105     }
106 
107     /**
108      * Test encoding and decoding of Strings with more exotic characters for UTF-8 and UTF-16.
109      * @throws SerializationException when that happens uncaught this test has failed
110      * @throws UnsupportedEncodingException when UTF-8 en/decoding fails
111      */
112     @Test
113     public void testStrings() throws SerializationException, UnsupportedEncodingException
114     {
115         String abc = "abc";
116         String copyright = "" + '\u00A9';
117         String xi = "" + '\u03BE';
118         String permille = "" + '\u2030';
119         String smiley = "\uD83D\uDE00";
120         String complex = smiley + copyright + xi + permille;
121 
122         testString(3, 6, abc);
123         testString(2, 2, copyright);
124         testString(3, 2, permille);
125         testString(2, 2, xi);
126         testString(4, 4, smiley);
127 
128         compare(TypedMessage.encodeUTF8(EndianUtil.BIG_ENDIAN, permille),
129                 new byte[] {9, 0, 0, 0, 3, (byte) 0xE2, (byte) 0x80, (byte) 0xB0});
130         compare(TypedMessage.encodeUTF16(EndianUtil.BIG_ENDIAN, permille),
131                 new byte[] {10, 0, 0, 0, 1, (byte) 0x20, (byte) 0x30});
132 
133         compare(TypedMessage.encodeUTF8(EndianUtil.BIG_ENDIAN, smiley),
134                 new byte[] {9, 0, 0, 0, 4, (byte) 0xF0, (byte) 0x9F, (byte) 0x98, (byte) 0x80});
135         compare(TypedMessage.encodeUTF16(EndianUtil.BIG_ENDIAN, smiley),
136                 new byte[] {10, 0, 0, 0, 2, (byte) 0xD8, (byte) 0x3D, (byte) 0xDE, (byte) 0x00});
137 
138         Object[] objects = new Object[] {copyright, xi, permille, smiley, abc, complex};
139         for (EndianUtil endianUtil : new EndianUtil[] {EndianUtil.BIG_ENDIAN, EndianUtil.LITTLE_ENDIAN})
140         {
141             for (boolean encodeUTF8 : new boolean[] {false, true})
142             {
143                 byte[] serialized = encodeUTF8 ? TypedMessage.encodeUTF8(endianUtil, objects)
144                         : TypedMessage.encodeUTF16(endianUtil, objects);
145                 System.out.print(HexDumper.hexDumper(serialized));
146                 System.out.print(SerialDataDumper.serialDataDumper(endianUtil, serialized));
147                 Object[] decodedObjects = TypedMessage.decodeToObjectDataTypes(serialized, endianUtil);
148                 assertEquals(objects.length, decodedObjects.length, "Size of decoded matches");
149                 for (int i = 0; i < objects.length; i++)
150                 {
151                     assertEquals(objects[i], decodedObjects[i],
152                             "decoded object at index " + i + "(" + objects[i] + ") equals corresponding object in input");
153                 }
154             }
155         }
156 
157     }
158 
159     /**
160      * Compare two byte arrays.
161      * @param actual the calculated byte array
162      * @param expected the expected byte array
163      */
164     private void compare(final byte[] actual, final byte[] expected)
165     {
166         assertEquals(expected.length, actual.length);
167         for (int i = 0; i < expected.length; i++)
168         {
169             assertEquals(expected[i], actual[i], "byte " + i + " expected: " + expected[i] + ", actual: " + actual[i]);
170         }
171     }
172 
173     /**
174      * Test encoding and decoding of one String for UTF-8 and UTF-16.
175      * @param expected8 expected length of UTF-8 encoding
176      * @param expected16 expected length of UTF-16 encoding
177      * @param s the string to test
178      * @throws SerializationException when that happens uncaught this test has failed
179      * @throws UnsupportedEncodingException when UTF-8 en/decoding fails
180      */
181     private void testString(final int expected8, final int expected16, final String s)
182             throws SerializationException, UnsupportedEncodingException
183     {
184         assertEquals(expected8, s.getBytes("UTF-8").length);
185         assertEquals(expected16, s.getBytes("UTF-16BE").length);
186         assertEquals(expected16, s.getBytes("UTF-16LE").length);
187 
188         byte[] b8 = TypedMessage.encodeUTF8(EndianUtil.BIG_ENDIAN, s);
189         byte[] b16BE = TypedMessage.encodeUTF16(EndianUtil.BIG_ENDIAN, s);
190         byte[] b16LE = TypedMessage.encodeUTF16(EndianUtil.LITTLE_ENDIAN, s);
191 
192         assertEquals(expected8, b8.length - 5);
193         assertEquals(expected16, b16BE.length - 5);
194         assertEquals(expected16, b16LE.length - 5);
195 
196         // get the number from the byte arrays
197         assertEquals(9, b8[0]);
198         assertEquals(expected8, EndianUtil.BIG_ENDIAN.decodeInt(b8, 1));
199         assertEquals(10, b16BE[0]);
200         assertEquals(expected16 / 2, EndianUtil.BIG_ENDIAN.decodeInt(b16BE, 1));
201         // TODO: assertEquals(10, b16LE[0]); the code for UTF-16LE will be different from 10 in a next version of djutils
202         assertEquals(expected16 / 2, EndianUtil.LITTLE_ENDIAN.decodeInt(b16LE, 1));
203     }
204 
205     /**
206      * Test encoding and decoding of arrays.
207      * @throws SerializationException when that happens uncaught this test has failed
208      */
209     @Test
210     public void testArrays() throws SerializationException
211     {
212         int[] integer = new int[] {1, 2, 3};
213         Integer[] integerValues2 = new Integer[] {-1, -2, -3};
214         short[] shortValues = new short[] {10, 20, 30};
215         Short[] shortValues2 = new Short[] {-10, -20, -30};
216         long[] longValues = new long[] {1000, 2000, 3000};
217         Long[] longValues2 = new Long[] {-1000L, -2000L, -3000L};
218         byte[] byteValues = new byte[] {12, 13, 14};
219         Byte[] byteValues2 = new Byte[] {-12, -13, -14};
220         boolean[] boolValues = new boolean[] {false, true, true};
221         Boolean[] boolValues2 = new Boolean[] {true, true, false};
222         float[] floatValues = new float[] {12.3f, 23.4f, 34.5f};
223         Float[] floatValues2 = new Float[] {-12.3f, -23.4f, -34.5f};
224         double[] doubleValues = new double[] {23.45, 34.56, 45.67};
225         Double[] doubleValues2 = new Double[] {-23.45, -34.56, -45.67};
226         Object[] objects = new Object[] {integer, integerValues2, shortValues, shortValues2, longValues, longValues2,
227                 byteValues, byteValues2, floatValues, floatValues2, doubleValues, doubleValues2, boolValues, boolValues2};
228         for (EndianUtil endianUtil : new EndianUtil[] {EndianUtil.BIG_ENDIAN, EndianUtil.LITTLE_ENDIAN})
229         {
230             for (boolean encodeUTF8 : new boolean[] {false, true})
231             {
232                 byte[] serialized = encodeUTF8 ? TypedMessage.encodeUTF8(endianUtil, objects)
233                         : TypedMessage.encodeUTF16(endianUtil, objects);
234                 System.out.print(HexDumper.hexDumper(serialized));
235                 System.out.print(SerialDataDumper.serialDataDumper(endianUtil, serialized));
236                 for (boolean primitive : new boolean[] {false, true})
237                 {
238                     Object[] decodedObjects = primitive ? TypedMessage.decodeToPrimitiveDataTypes(serialized, endianUtil)
239                             : TypedMessage.decodeToObjectDataTypes(serialized, endianUtil);
240                     assertEquals(objects.length, decodedObjects.length, "Size of decoded matches");
241                     for (int i = 0; i < objects.length; i++)
242                     {
243                         assertTrue(deepEquals0(makePrimitive(objects[i]), makePrimitive(decodedObjects[i])),
244                                 "decoded object at index " + i + "(" + objects[i] + ") equals corresponding object in input");
245                     }
246                 }
247             }
248         }
249     }
250 
251     /**
252      * Test encoding and decoding of arrays.
253      * @throws SerializationException when that happens uncaught this test has failed
254      */
255     @Test
256     public void testMatrices() throws SerializationException
257     {
258         int[][] integer = new int[][] {{1, 2, 3}, {4, 5, 6}};
259         Integer[][] integerValues2 = new Integer[][] {{-1, -2, -3}, {-4, -5, -6}};
260         short[][] shortValues = new short[][] {{10, 20, 30}, {40, 50, 60}};
261         Short[][] shortValues2 = new Short[][] {{-10, -20, -30}, {-40, -50, -60}};
262         long[][] longValues = new long[][] {{1000, 2000, 3000}, {3000, 4000, 5000}};
263         Long[][] longValues2 = new Long[][] {{-1000L, -2000L, -3000L}, {-3000L, -4000L, -5000L}};
264         byte[][] byteValues = new byte[][] {{12, 13, 14}, {15, 16, 17}};
265         Byte[][] byteValues2 = new Byte[][] {{-12, -13, -14}, {-15, -16, -17}};
266         boolean[][] boolValues = new boolean[][] {{false, true, true}, {false, false, false}};
267         Boolean[][] boolValues2 = new Boolean[][] {{true, true, false}, {true, true, true}};
268         float[][] floatValues = new float[][] {{12.3f, 23.4f, 34.5f}, {44.4f, 55.5f, 66.6f}};
269         Float[][] floatValues2 = new Float[][] {{-12.3f, -23.4f, -34.5f}, {-11.1f, -22.2f, -33.3f}};
270         double[][] doubleValues = new double[][] {{23.45, 34.56, 45.67}, {55.5, 66.6, 77.7}};
271         Double[][] doubleValues2 = new Double[][] {{-23.45, -34.56, -45.67}, {-22.2, -33.3, -44.4}};
272         Object[] objects = new Object[] {integer, integerValues2, shortValues, shortValues2, longValues, longValues2,
273                 byteValues, byteValues2, floatValues, floatValues2, doubleValues, doubleValues2, boolValues, boolValues2};
274         for (EndianUtil endianUtil : new EndianUtil[] {EndianUtil.BIG_ENDIAN, EndianUtil.LITTLE_ENDIAN})
275         {
276             for (boolean encodeUTF8 : new boolean[] {false, true})
277             {
278                 byte[] serialized = encodeUTF8 ? TypedMessage.encodeUTF8(endianUtil, objects)
279                         : TypedMessage.encodeUTF16(endianUtil, objects);
280                 System.out.print(HexDumper.hexDumper(serialized));
281                 System.out.print(SerialDataDumper.serialDataDumper(endianUtil, serialized));
282                 for (boolean primitive : new boolean[] {false, true})
283                 {
284                     Object[] decodedObjects = primitive ? TypedMessage.decodeToPrimitiveDataTypes(serialized, endianUtil)
285                             : TypedMessage.decodeToObjectDataTypes(serialized, endianUtil);
286                     assertEquals(objects.length, decodedObjects.length, "Size of decoded matches");
287                     for (int i = 0; i < objects.length; i++)
288                     {
289                         assertTrue(deepEquals0(makePrimitive(objects[i]), makePrimitive(decodedObjects[i])),
290                                 "decoded object at index " + i + "(" + objects[i] + ") equals corresponding object in input");
291                     }
292                 }
293             }
294         }
295     }
296 
297     /**
298      * Test encoding and decoding of strongly typed quantities (DJUNITS).
299      * @throws SerializationException when that happens uncaught, this test has failed
300      * @throws ValueRuntimeException when that happens uncaught, this test has failed
301      */
302     @Test
303     public void testDJunits() throws SerializationException, ValueRuntimeException
304     {
305         Length length = new Length(123.4, LengthUnit.FOOT);
306         Dimensionless value = new Dimensionless(345.6, DimensionlessUnit.SI);
307         FloatArea area = new FloatArea(66.66f, AreaUnit.ACRE);
308         ElectricalCurrentVector currents =
309                 new ElectricalCurrentVector(new double[] {1.2, 2.3, 3.4}, ElectricalCurrentUnit.MILLIAMPERE, StorageType.DENSE);
310         FloatElectricalResistanceVector resistors = new FloatElectricalResistanceVector(new float[] {1.2f, 4.7f, 6.8f},
311                 ElectricalResistanceUnit.KILOOHM, StorageType.DENSE);
312         ElectricalCurrentMatrix currentMatrix = new ElectricalCurrentMatrix(new double[][] {{1.2, 2.3, 3.4}, {5.5, 6.6, 7.7}},
313                 ElectricalCurrentUnit.MILLIAMPERE, StorageType.DENSE);
314         FloatElectricalResistanceMatrix resistorMatrix = new FloatElectricalResistanceMatrix(
315                 new float[][] {{1.2f, 4.7f, 6.8f}, {2.2f, 3.3f, 4.4f}}, ElectricalResistanceUnit.KILOOHM, StorageType.DENSE);
316 
317         Object[] objects = new Object[] {length, value, area, currents, resistors, currentMatrix, resistorMatrix};
318         for (EndianUtil endianUtil : new EndianUtil[] {EndianUtil.BIG_ENDIAN, EndianUtil.LITTLE_ENDIAN})
319         {
320             byte[] serialized = TypedMessage.encodeUTF16(endianUtil, objects);
321             System.out.print(HexDumper.hexDumper(serialized));
322             System.out.print(SerialDataDumper.serialDataDumper(endianUtil, serialized));
323             for (boolean primitive : new boolean[] {false, true})
324             {
325                 Object[] decodedObjects = primitive ? TypedMessage.decodeToPrimitiveDataTypes(serialized, endianUtil)
326                         : TypedMessage.decodeToObjectDataTypes(serialized, endianUtil);
327                 assertEquals(objects.length, decodedObjects.length, "Size of decoded matches");
328                 for (int i = 0; i < objects.length; i++)
329                 {
330                     assertTrue(deepEquals0(makePrimitive(objects[i]), makePrimitive(decodedObjects[i])),
331                             "decoded object at index " + i + "(" + objects[i] + ") equals corresponding object in input");
332                 }
333             }
334         }
335     }
336 
337     /**
338      * Test stored information about djunits SerializationUnits.
339      * @throws SerializationException when that happens uncaught, this test has failed
340      * @throws ValueRuntimeException when that happens uncaught, this test has failed
341      */
342     @Test
343     public void testSerializationUnits() throws SerializationException, ValueRuntimeException
344     {
345         SerializationUnits areaSerUnit = SerializationUnits.AREA;
346         assertEquals("Area", areaSerUnit.getName());
347         assertEquals("Area (m2)", areaSerUnit.getDescription());
348         assertEquals(5, areaSerUnit.getCode());
349         assertEquals(AreaUnit.class, areaSerUnit.getDjunitsType());
350         assertEquals("[m^2]", areaSerUnit.getSiUnit());
351 
352         assertEquals(LengthUnit.class, SerializationUnits.getUnitClass((byte) 16));
353         assertEquals(16, SerializationUnits.getUnitCode(LengthUnit.INCH));
354         assertEquals(areaSerUnit, SerializationUnits.getUnitType((byte) 5));
355         assertEquals(areaSerUnit, SerializationUnits.getUnitType(AreaUnit.ARE));
356 
357         assertNotEquals(SerializationUnits.RADIOACTIVITY, areaSerUnit);
358         assertNotEquals(new Object(), areaSerUnit);
359         assertNotEquals(SerializationUnits.RADIOACTIVITY.hashCode(), areaSerUnit.hashCode());
360         assertNotEquals(new Object().hashCode(), areaSerUnit.hashCode());
361     }
362 
363     /**
364      * Test stored information about djunits display types.
365      * @throws SerializationException when that happens uncaught, this test has failed
366      * @throws ValueRuntimeException when that happens uncaught, this test has failed
367      */
368     @Test
369     public void testDJunitDisplayTypes() throws SerializationException, ValueRuntimeException
370     {
371         SerializationUnits areaSerUnit = SerializationUnits.AREA;
372         DisplayType aream2 = DisplayType.AREA_SQUARE_METER;
373         DisplayType areaacre = DisplayType.AREA_ACRE;
374         DisplayType masskg = DisplayType.MASS_KILOGRAM;
375         assertEquals("m2", aream2.getAbbreviation());
376         assertEquals(0, aream2.getByteCode());
377         assertEquals(18, areaacre.getByteCode());
378         assertEquals(AreaUnit.SQUARE_METER, aream2.getDjunitsType());
379         assertEquals(AreaUnit.ACRE, areaacre.getDjunitsType());
380         assertEquals(0, aream2.getIntCode());
381         assertEquals(18, areaacre.getIntCode());
382         assertEquals("SQUARE_METER", aream2.getName());
383         assertEquals("ACRE", areaacre.getName());
384         assertEquals(areaSerUnit, aream2.getUnitType());
385         assertEquals(areaacre.getUnitType(), aream2.getUnitType());
386 
387         assertEquals(8, DisplayType.getByteCode(ElectricalResistanceUnit.STATOHM));
388         assertEquals(areaacre, DisplayType.getDisplayType(AreaUnit.ACRE));
389         assertEquals(DisplayType.ENERGY_CALORIE, DisplayType.getDisplayType((byte) 11, 30));
390         assertEquals(areaacre, DisplayType.getDisplayType(areaSerUnit, 18));
391         assertEquals(30, DisplayType.getIntCode(EnergyUnit.CALORIE));
392         assertEquals(EnergyUnit.CALORIE, DisplayType.getUnit((byte) 11, 30));
393         assertEquals(AreaUnit.ACRE, DisplayType.getUnit(areaSerUnit, 18));
394 
395         assertNotEquals(aream2, areaacre);
396         assertNotEquals(masskg, areaacre);
397         assertNotEquals(new Object(), areaacre);
398         assertNotEquals(aream2.hashCode(), areaacre.hashCode());
399         assertNotEquals(masskg.hashCode(), areaacre.hashCode());
400         assertNotEquals(new Object().hashCode(), areaacre.hashCode());
401     }
402 
403     /** Class used to test serialization of classes that implement SerializableObject. */
404     static class Compound implements SerializableObject<Compound>
405     {
406         /** Field 1. */
407         @SuppressWarnings("checkstyle:visibilitymodifier")
408         public Integer intValue;
409 
410         /** Field 2. */
411         @SuppressWarnings("checkstyle:visibilitymodifier")
412         public Double doubleValue;
413 
414         @Override
415         public int hashCode()
416         {
417             final int prime = 31;
418             int result = 1;
419             result = prime * result + ((this.doubleValue == null) ? 0 : this.doubleValue.hashCode());
420             result = prime * result + ((this.intValue == null) ? 0 : this.intValue.hashCode());
421             return result;
422         }
423 
424         @SuppressWarnings("checkstyle:needbraces")
425         @Override
426         public boolean equals(final Object obj)
427         {
428             if (this == obj)
429                 return true;
430             if (obj == null)
431                 return false;
432             if (getClass() != obj.getClass())
433                 return false;
434             Compound other = (Compound) obj;
435             if (this.doubleValue == null)
436             {
437                 if (other.doubleValue != null)
438                     return false;
439             }
440             else if (!this.doubleValue.equals(other.doubleValue))
441                 return false;
442             if (this.intValue == null)
443             {
444                 if (other.intValue != null)
445                     return false;
446             }
447             else if (!this.intValue.equals(other.intValue))
448                 return false;
449             return true;
450         }
451 
452         @Override
453         public String toString()
454         {
455             return "Compound [intValue=" + this.intValue + ", doubleValue=" + this.doubleValue + "]";
456         }
457 
458         /**
459          * Construct a new Compound object.
460          * @param intValue int; the value to assign to intValue
461          * @param doubleValue double; the value to assign to doubleValue
462          */
463         Compound(final int intValue, final double doubleValue)
464         {
465             this.intValue = intValue;
466             this.doubleValue = doubleValue;
467         }
468 
469         @Override
470         public List<Object> exportAsList()
471         {
472             List<Object> result = new ArrayList<>();
473             result.add(this.intValue);
474             result.add(this.doubleValue);
475             return result;
476         }
477 
478     }
479 
480     /**
481      * Test the compound array encoder and decoder.
482      * @throws SerializationException when that happens uncaught, this test has failed
483      */
484     @Test
485     public void testCompoundArrays() throws SerializationException
486     {
487         Compound[] testArray = new Compound[] {new Compound(1, 0.1), new Compound(2, 0.2), new Compound(3, 0.3)};
488         Object[] objects = new Object[] {testArray};
489         for (EndianUtil endianUtil : new EndianUtil[] {EndianUtil.BIG_ENDIAN, EndianUtil.LITTLE_ENDIAN})
490         {
491             for (boolean encodeUTF8 : new boolean[] {false, true})
492             {
493                 // System.out.println("Encoding " + (encodeUTF8 ? "UTF8" : "UTF16") + ", " + endianUtil);
494                 byte[] serialized = encodeUTF8 ? TypedMessage.encodeUTF8(endianUtil, objects)
495                         : TypedMessage.encodeUTF16(endianUtil, objects);
496                 // System.out.print(HexDumper.hexDumper(serialized));
497                 for (boolean primitive : new boolean[] {false, true})
498                 {
499                     Object[] decodedObjects = primitive ? TypedMessage.decodeToPrimitiveDataTypes(serialized, endianUtil)
500                             : TypedMessage.decodeToObjectDataTypes(serialized, endianUtil);
501                     assertEquals(objects.length, decodedObjects.length, "Size of decoded matches");
502                     // Replace all List objects in the result by corresponding new Compound objects
503                     for (int i = 0; i < objects.length; i++)
504                     {
505                         Object o = decodedObjects[i];
506                         if (o instanceof TypedMessage.MinimalSerializableObject[])
507                         {
508                             TypedMessage.MinimalSerializableObject[] in = ((TypedMessage.MinimalSerializableObject[]) o);
509                             Compound[] out = new Compound[in.length];
510                             for (int j = 0; j < in.length; j++)
511                             {
512                                 List<Object> fields = in[j].exportAsList();
513                                 Integer intValue = (Integer) fields.get(0);
514                                 Double doubleValue = (Double) fields.get(1);
515                                 out[j] = new Compound(intValue, doubleValue);
516                             }
517                             decodedObjects[i] = out;
518                         }
519                     }
520                     for (int i = 0; i < objects.length; i++)
521                     {
522                         if (objects[i] instanceof Compound[])
523                         {
524                             Compound[] in = (Compound[]) objects[i];
525                             assertTrue(decodedObjects[i] instanceof Compound[], "decoded object is now also a Compound[]");
526                             Compound[] out = (Compound[]) objects[i];
527                             assertEquals(in.length, out.length, "Compound arrays have same length");
528                             for (int j = 0; j < in.length; j++)
529                             {
530                                 assertEquals(in[j], out[j], "reconstructed compound object matches input");
531                             }
532                         }
533                         else
534                         {
535                             assertTrue(deepEquals0(makePrimitive(objects[i]), makePrimitive(decodedObjects[i])),
536                                     "decoded object at index " + i + "(" + objects[i]
537                                             + ") equals corresponding object in input");
538                         }
539                     }
540                 }
541             }
542         }
543     }
544 
545     /**
546      * Test serialization and deserialization of arrays of Djutils vectors.
547      * @throws ValueRuntimeException if that happens uncaught; this test has failed
548      * @throws SerializationException if that happens uncaught; this test has failed
549      */
550     @Test
551     public void testArrayOfDjutilsVectors() throws ValueRuntimeException, SerializationException
552     {
553         DoubleVector<?, ?, ?>[] array =
554                 new DoubleVector[] {new LengthVector(new double[] {0.1, 0.2, 0.3}, LengthUnit.INCH, StorageType.DENSE),
555                         new TimeVector(new double[] {10.1, 20.2, 30.3}, TimeUnit.BASE_MINUTE, StorageType.DENSE)};
556         Object[] objects = new Object[] {array};
557         for (EndianUtil endianUtil : new EndianUtil[] {EndianUtil.BIG_ENDIAN, EndianUtil.LITTLE_ENDIAN})
558         {
559             for (boolean encodeUTF8 : new boolean[] {false, true})
560             {
561                 // System.out.println("Encoding " + (encodeUTF8 ? "UTF8" : "UTF16") + ", " + endianUtil);
562                 byte[] serialized = encodeUTF8 ? TypedMessage.encodeUTF8(endianUtil, objects)
563                         : TypedMessage.encodeUTF16(endianUtil, objects);
564                 System.out.print(HexDumper.hexDumper(serialized));
565                 System.out.print(SerialDataDumper.serialDataDumper(endianUtil, serialized));
566                 for (boolean primitive : new boolean[] {false, true})
567                 {
568                     Object[] decodedObjects = primitive ? TypedMessage.decodeToPrimitiveDataTypes(serialized, endianUtil)
569                             : TypedMessage.decodeToObjectDataTypes(serialized, endianUtil);
570                     assertEquals(objects.length, decodedObjects.length, "Size of decoded matches");
571                     for (int i = 0; i < objects.length; i++)
572                     {
573                         if (objects[i] instanceof DoubleVector<?, ?, ?>[])
574                         {
575                             DoubleVector<?, ?, ?>[] arrayIn = (DoubleVector<?, ?, ?>[]) objects[i];
576                             DoubleVector<?, ?, ?>[] arrayOut = (DoubleVector<?, ?, ?>[]) decodedObjects[i];
577                             for (int j = 0; j < arrayOut.length; j++)
578                             {
579                                 assertEquals(arrayIn[j], arrayOut[j], "Decoded Djutils array vector element matches");
580                             }
581                         }
582                         else
583                         {
584                             assertTrue(deepEquals0(makePrimitive(objects[i]), makePrimitive(decodedObjects[i])),
585                                     "decoded object at index " + i + "(" + objects[i]
586                                             + ") equals corresponding object in input");
587                         }
588                     }
589                 }
590             }
591         }
592     }
593 
594     /**
595      * Test that jagged matrices are detected and cause a SerializationException.
596      */
597     @Test
598     public void testJaggedMatrices()
599     {
600         int[][] integer = new int[][] {{1, 2, 3}, {5, 6}};
601         Integer[][] integerValues2 = new Integer[][] {{-1, -2}, {-4, -5, -6}};
602         short[][] shortValues = new short[][] {{10, 20}, {40, 50, 60}};
603         Short[][] shortValues2 = new Short[][] {{-10, -20, -30}, {-40, -50}};
604         long[][] longValues = new long[][] {{1000, 2000, 3000}, {3000, 4000}};
605         Long[][] longValues2 = new Long[][] {{-1000L, -2000L}, {-3000L, -4000L, -5000L}};
606         byte[][] byteValues = new byte[][] {{12, 13}, {15, 16, 17}};
607         Byte[][] byteValues2 = new Byte[][] {{-12, -13, -14}, {-15, -16}};
608         boolean[][] boolValues = new boolean[][] {{false, true, true}, {false, false}};
609         Boolean[][] boolValues2 = new Boolean[][] {{true, true}, {true, true, true}};
610         float[][] floatValues = new float[][] {{12.3f, 23.4f}, {44.4f, 55.5f, 66.6f}};
611         Float[][] floatValues2 = new Float[][] {{-12.3f, -23.4f, -34.5f}, {-11.1f, -22.2f}};
612         double[][] doubleValues = new double[][] {{23.45, 34.56, 45.67}, {55.5, 66.6}};
613         Double[][] doubleValues2 = new Double[][] {{-23.45, -34.56}, {-22.2, -33.3, -44.4}};
614         Object[] objects = new Object[] {integer, integerValues2, shortValues, shortValues2, longValues, longValues2,
615                 byteValues, byteValues2, floatValues, floatValues2, doubleValues, doubleValues2, boolValues, boolValues2};
616         for (EndianUtil endianUtil : new EndianUtil[] {EndianUtil.BIG_ENDIAN, EndianUtil.LITTLE_ENDIAN})
617         {
618             for (Object object : objects)
619             {
620                 Object[] singleObjectArray = new Object[] {object};
621                 try
622                 {
623                     TypedMessage.encodeUTF16(endianUtil, singleObjectArray);
624                     fail("Jagged array should have thrown a SerializationException");
625                 }
626                 catch (SerializationException se)
627                 {
628                     // Ignore expected exception
629                 }
630                 try
631                 {
632                     TypedMessage.encodeUTF8(endianUtil, singleObjectArray);
633                     fail("Jagged array should have thrown a SerializationException");
634                 }
635                 catch (SerializationException se)
636                 {
637                     // Ignore expected exception
638                 }
639             }
640         }
641     }
642 
643     /**
644      * Test that the encoder throws a SerializationException when given something that it does not know how to serialize.
645      */
646     @Test
647     public void testUnhandledObject()
648     {
649         File file = new File("whatever");
650         Object[] objects = new Object[] {file};
651         for (EndianUtil endianUtil : new EndianUtil[] {EndianUtil.BIG_ENDIAN, EndianUtil.LITTLE_ENDIAN})
652         {
653             try
654             {
655                 TypedMessage.encodeUTF16(endianUtil, objects);
656                 fail("Non serializable object should have thrown a SerializationException");
657             }
658             catch (SerializationException se)
659             {
660                 // Ignore expected exception
661             }
662 
663             Integer[][] badMatrix = new Integer[0][0];
664             objects = new Object[] {badMatrix};
665             try
666             {
667                 TypedMessage.encodeUTF16(endianUtil, objects);
668                 fail("Zero sized matrix should have thrown a SerializationException");
669             }
670             catch (SerializationException se)
671             {
672                 // Ignore expected exception
673             }
674         }
675     }
676 
677     /**
678      * Test the Pointer class.
679      */
680     @Test
681     public void pointerTest()
682     {
683         Pointer pointer = new Pointer();
684         assertEquals(0, pointer.get(), "initial offset is 0");
685         assertEquals(0, pointer.getAndIncrement(10), "initial offset is 0");
686         assertEquals(10, pointer.get(), "offset is now 10");
687         pointer.inc(20);
688         assertEquals(30, pointer.get(), "offset is now 30");
689         assertTrue(pointer.toString().startsWith("Pointer"), "ToString method returns something descriptive");
690     }
691 
692     /**
693      * Convert an array, or matrix of Byte, Short, Integer, etc. to an array/matrix of byte, short, int, etc.
694      * @param in Object; the array to convert
695      * @return Object; the converted input (if conversion was possible), or the unconverted input.
696      */
697     static Object makePrimitive(final Object in)
698     {
699         if (in instanceof Byte[])
700         {
701             Byte[] byteIn = (Byte[]) in;
702             byte[] result = new byte[byteIn.length];
703             for (int i = 0; i < result.length; i++)
704             {
705                 result[i] = byteIn[i];
706             }
707             return result;
708         }
709         if (in instanceof Short[])
710         {
711             Short[] shortIn = (Short[]) in;
712             short[] result = new short[shortIn.length];
713             for (int i = 0; i < result.length; i++)
714             {
715                 result[i] = shortIn[i];
716             }
717             return result;
718         }
719         if (in instanceof Integer[])
720         {
721             Integer[] integerIn = (Integer[]) in;
722             int[] result = new int[integerIn.length];
723             for (int i = 0; i < result.length; i++)
724             {
725                 result[i] = integerIn[i];
726             }
727             return result;
728         }
729         if (in instanceof Long[])
730         {
731             Long[] longIn = (Long[]) in;
732             long[] result = new long[longIn.length];
733             for (int i = 0; i < result.length; i++)
734             {
735                 result[i] = longIn[i];
736             }
737             return result;
738         }
739         if (in instanceof Float[])
740         {
741             Float[] floatIn = (Float[]) in;
742             float[] result = new float[floatIn.length];
743             for (int i = 0; i < result.length; i++)
744             {
745                 result[i] = floatIn[i];
746             }
747             return result;
748         }
749         if (in instanceof Double[])
750         {
751             Double[] doubleIn = (Double[]) in;
752             double[] result = new double[doubleIn.length];
753             for (int i = 0; i < result.length; i++)
754             {
755                 result[i] = doubleIn[i];
756             }
757             return result;
758         }
759         if (in instanceof Boolean[])
760         {
761             Boolean[] booleanIn = (Boolean[]) in;
762             boolean[] result = new boolean[booleanIn.length];
763             for (int i = 0; i < result.length; i++)
764             {
765                 result[i] = booleanIn[i];
766             }
767             return result;
768         }
769         if (in instanceof Byte[][])
770         {
771             Byte[][] byteIn = (Byte[][]) in;
772             byte[][] result = new byte[byteIn.length][byteIn[0].length];
773             for (int i = 0; i < result.length; i++)
774             {
775                 for (int j = 0; j < result[0].length; j++)
776                 {
777                     result[i][j] = byteIn[i][j];
778                 }
779             }
780             return result;
781         }
782         if (in instanceof Short[][])
783         {
784             Short[][] shortIn = (Short[][]) in;
785             short[][] result = new short[shortIn.length][shortIn[0].length];
786             for (int i = 0; i < result.length; i++)
787             {
788                 for (int j = 0; j < result[0].length; j++)
789                 {
790                     result[i][j] = shortIn[i][j];
791                 }
792             }
793             return result;
794         }
795         if (in instanceof Integer[][])
796         {
797             Integer[][] integerIn = (Integer[][]) in;
798             int[][] result = new int[integerIn.length][integerIn[0].length];
799             for (int i = 0; i < result.length; i++)
800             {
801                 for (int j = 0; j < result[0].length; j++)
802                 {
803                     result[i][j] = integerIn[i][j];
804                 }
805             }
806             return result;
807         }
808         if (in instanceof Long[][])
809         {
810             Long[][] longIn = (Long[][]) in;
811             long[][] result = new long[longIn.length][longIn[0].length];
812             for (int i = 0; i < result.length; i++)
813             {
814                 for (int j = 0; j < result[0].length; j++)
815                 {
816                     result[i][j] = longIn[i][j];
817                 }
818             }
819             return result;
820         }
821         if (in instanceof Float[][])
822         {
823             Float[][] floatIn = (Float[][]) in;
824             float[][] result = new float[floatIn.length][floatIn[0].length];
825             for (int i = 0; i < result.length; i++)
826             {
827                 for (int j = 0; j < result[0].length; j++)
828                 {
829                     result[i][j] = floatIn[i][j];
830                 }
831             }
832             return result;
833         }
834         if (in instanceof Double[][])
835         {
836             Double[][] doubleIn = (Double[][]) in;
837             double[][] result = new double[doubleIn.length][doubleIn[0].length];
838             for (int i = 0; i < result.length; i++)
839             {
840                 for (int j = 0; j < result[0].length; j++)
841                 {
842                     result[i][j] = doubleIn[i][j];
843                 }
844             }
845             return result;
846         }
847         if (in instanceof Boolean[][])
848         {
849             Boolean[][] booleanIn = (Boolean[][]) in;
850             boolean[][] result = new boolean[booleanIn.length][booleanIn[0].length];
851             for (int i = 0; i < result.length; i++)
852             {
853                 for (int j = 0; j < result[0].length; j++)
854                 {
855                     result[i][j] = booleanIn[i][j];
856                 }
857             }
858             return result;
859         }
860         return in;
861     }
862 
863     /**
864      * Compare two arrays of any type (stolen from java.util.Arrays).
865      * @param e1 Object (should be some kind of array)
866      * @param e2 Object (should be some kind of array)
867      * @return boolean; true of the arrays have the same type, size and all elements in the arrays are equal to their
868      *         counterpart
869      */
870     static boolean deepEquals0(final Object e1, final Object e2)
871     {
872         if (e1 instanceof Object[] && e2 instanceof Object[])
873         {
874             return Arrays.deepEquals((Object[]) e1, (Object[]) e2);
875         }
876         if (e1 instanceof byte[] && e2 instanceof byte[])
877         {
878             return Arrays.equals((byte[]) e1, (byte[]) e2);
879         }
880         if (e1 instanceof short[] && e2 instanceof short[])
881         {
882             return Arrays.equals((short[]) e1, (short[]) e2);
883         }
884         if (e1 instanceof int[] && e2 instanceof int[])
885         {
886             return Arrays.equals((int[]) e1, (int[]) e2);
887         }
888         if (e1 instanceof long[] && e2 instanceof long[])
889         {
890             return Arrays.equals((long[]) e1, (long[]) e2);
891         }
892         if (e1 instanceof char[] && e2 instanceof char[])
893         {
894             return Arrays.equals((char[]) e1, (char[]) e2);
895         }
896         if (e1 instanceof float[] && e2 instanceof float[])
897         {
898             return Arrays.equals((float[]) e1, (float[]) e2);
899         }
900         if (e1 instanceof double[] && e2 instanceof double[])
901         {
902             return Arrays.equals((double[]) e1, (double[]) e2);
903         }
904         if (e1 instanceof boolean[] && e2 instanceof boolean[])
905         {
906             return Arrays.equals((boolean[]) e1, (boolean[]) e2);
907         }
908         return e1.equals(e2);
909     }
910 
911     /**
912      * Test the UnitType class.
913      */
914     @Test
915     public void testUnitType()
916     {
917         byte code = 127;
918         Class<AccelerationUnit> unitClass = AccelerationUnit.class;
919         String name = "AccelerationName";
920         String description = "AccelerationDescription";
921         String siUnit = "[m/s^2]";
922         SerializationUnits testAccelerationUnitType = new SerializationUnits(code, unitClass, name, description, siUnit);
923         assertEquals(code, testAccelerationUnitType.getCode(), "code is returned");
924         assertEquals(unitClass, testAccelerationUnitType.getDjunitsType(), "unit class is returned");
925         assertEquals(name, testAccelerationUnitType.getName(), "name is returned");
926         assertEquals(description, testAccelerationUnitType.getDescription(), "description is returned");
927         assertEquals(siUnit, testAccelerationUnitType.getSiUnit(), "SI unit is returned");
928         assertTrue(testAccelerationUnitType.toString().startsWith("UnitType"), "toString returns something descriptive");
929 
930         byte undefined = 126;
931         assertEquals(testAccelerationUnitType, SerializationUnits.getUnitType(code), "new unit is in the byte type map");
932         assertNull(SerializationUnits.getUnitType(undefined), "undefined byte returns null");
933         assertEquals(unitClass, SerializationUnits.getUnitClass(code), "djunits type is returned");
934         assertNull(SerializationUnits.getUnitClass(undefined), "undefined byte returns null");
935         assertEquals(SerializationUnits.SPEED, SerializationUnits.getUnitType((byte) 22),
936                 "speed type can be found by byte code");
937         assertEquals(SerializationUnits.SPEED, SerializationUnits.getUnitType(SpeedUnit.SI),
938                 "speed type can be found by unit type");
939         assertEquals(SerializationUnits.SPEED, SerializationUnits.getUnitType(SpeedUnit.FOOT_PER_SECOND),
940                 "speed type can be found by non SI unit type");
941         assertEquals(22, SerializationUnits.getUnitCode(SpeedUnit.SI), "speed unit code can be found by unit type");
942     }
943 
944     /**
945      * Test all constructors for SerializationException.
946      */
947     @Test
948     public final void serializationExceptionTest()
949     {
950         String message = "MessageString";
951         Exception e = new SerializationException(message);
952         assertEquals(message, e.getMessage(), "message should be our message");
953         assertEquals(null, e.getCause(), "cause should be null");
954         e = new SerializationException();
955         assertEquals(null, e.getCause(), "cause should be null");
956         String causeString = "CauseString";
957         Throwable cause = new Throwable(causeString);
958         e = new SerializationException(cause);
959         assertEquals(cause, e.getCause(), "cause should not be our cause");
960         assertEquals(causeString, e.getCause().getMessage(), "cause description should be our cause string");
961         e = new SerializationException(message, cause);
962         assertEquals(message, e.getMessage(), "message should be our message");
963         assertEquals(cause, e.getCause(), "cause should not be our cause");
964         assertEquals(causeString, e.getCause().getMessage(), "cause description should be our cause string");
965         for (boolean enableSuppression : new boolean[] {true, false})
966         {
967             for (boolean writableStackTrace : new boolean[] {true, false})
968             {
969                 e = new SerializationException(message, cause, enableSuppression, writableStackTrace);
970                 assertTrue(null != e, "Exception should not be null");
971                 assertEquals(message, e.getMessage(), "message should be our message");
972                 assertEquals(cause, e.getCause(), "cause should not be our cause");
973                 assertEquals(causeString, e.getCause().getMessage(), "cause description should be our cause string");
974                 // Don't know how to check if suppression is enabled/disabled
975                 StackTraceElement[] stackTrace = new StackTraceElement[1];
976                 stackTrace[0] = new StackTraceElement("a", "b", "c", 1234);
977                 try
978                 {
979                     e.setStackTrace(stackTrace);
980                 }
981                 catch (Exception e1)
982                 {
983                     assertTrue(writableStackTrace, "Stack trace should be writable");
984                     continue;
985                 }
986                 // You wouldn't believe it, but a call to setStackTrace if non-writable is silently ignored
987                 StackTraceElement[] retrievedStackTrace = e.getStackTrace();
988                 if (retrievedStackTrace.length > 0)
989                 {
990                     assertTrue(writableStackTrace, "stack trace should be writable");
991                 }
992             }
993         }
994     }
995 
996     /**
997      * Test all constructors for SerializationRuntimeException.
998      */
999     @Test
1000     public final void serializationRuntimeExceptionTest()
1001     {
1002         String message = "MessageString";
1003         Exception e = new SerializationRuntimeException(message);
1004         assertEquals(message, e.getMessage(), "message should be our message");
1005         assertEquals(null, e.getCause(), "cause should be null");
1006         e = new SerializationRuntimeException();
1007         assertEquals(null, e.getCause(), "cause should be null");
1008         String causeString = "CauseString";
1009         Throwable cause = new Throwable(causeString);
1010         e = new SerializationRuntimeException(cause);
1011         assertEquals(cause, e.getCause(), "cause should not be our cause");
1012         assertEquals(causeString, e.getCause().getMessage(), "cause description should be our cause string");
1013         e = new SerializationRuntimeException(message, cause);
1014         assertEquals(message, e.getMessage(), "message should be our message");
1015         assertEquals(cause, e.getCause(), "cause should not be our cause");
1016         assertEquals(causeString, e.getCause().getMessage(), "cause description should be our cause string");
1017         for (boolean enableSuppression : new boolean[] {true, false})
1018         {
1019             for (boolean writableStackTrace : new boolean[] {true, false})
1020             {
1021                 e = new SerializationRuntimeException(message, cause, enableSuppression, writableStackTrace);
1022                 assertTrue(null != e, "Exception should not be null");
1023                 assertEquals(message, e.getMessage(), "message should be our message");
1024                 assertEquals(cause, e.getCause(), "cause should not be our cause");
1025                 assertEquals(causeString, e.getCause().getMessage(), "cause description should be our cause string");
1026                 // Don't know how to check if suppression is enabled/disabled
1027                 StackTraceElement[] stackTrace = new StackTraceElement[1];
1028                 stackTrace[0] = new StackTraceElement("a", "b", "c", 1234);
1029                 try
1030                 {
1031                     e.setStackTrace(stackTrace);
1032                 }
1033                 catch (Exception e1)
1034                 {
1035                     assertTrue(writableStackTrace, "Stack trace should be writable");
1036                     continue;
1037                 }
1038                 // You wouldn't believe it, but a call to setStackTrace if non-writable is silently ignored
1039                 StackTraceElement[] retrievedStackTrace = e.getStackTrace();
1040                 if (retrievedStackTrace.length > 0)
1041                 {
1042                     assertTrue(writableStackTrace, "stack trace should be writable");
1043                 }
1044             }
1045         }
1046     }
1047 
1048     /**
1049      * Test the remainder of the EndianUtil class.
1050      */
1051     @Test
1052     public void testEndianUtil()
1053     {
1054         assertTrue(EndianUtil.BIG_ENDIAN.isBigEndian(), "EndianUtil.BIG_ENDIAN is big endian");
1055         assertFalse(EndianUtil.LITTLE_ENDIAN.isBigEndian(), "EndianUtil.LITTLE_ENDIAN is not big endian");
1056         assertEquals(ByteOrder.nativeOrder().equals(ByteOrder.BIG_ENDIAN), EndianUtil.isPlatformBigEndian(),
1057                 "Platform endianness matches what EndianUtil says");
1058         assertTrue(EndianUtil.bigEndian().isBigEndian(), "EndianUtil.BIG_ENDIAN is big endian");
1059         assertFalse(EndianUtil.littleEndian().isBigEndian(), "EndianUtil.LITTLE_ENDIAN is not big endian");
1060         assertTrue(EndianUtil.BIG_ENDIAN.toString().startsWith("EndianUtil"), "EndianUtil has descriptive toString method");
1061     }
1062 
1063     /**
1064      * Test the toString and dataClassName methods of the BasicSerializer.
1065      */
1066     @Test
1067     public void testBasicSerializer()
1068     {
1069         byte code = 123;
1070         String dataClassName = "dataClass";
1071         BasicSerializer<Byte> testSerializer = new BasicSerializer<Byte>(code, dataClassName)
1072         {
1073 
1074             @Override
1075             public int size(final Byte object) throws SerializationException
1076             {
1077                 // Auto-generated method stub; never called
1078                 return 0;
1079             }
1080 
1081             @Override
1082             public int sizeWithPrefix(final Byte object) throws SerializationException
1083             {
1084                 // Auto-generated method stub; never called
1085                 return 0;
1086             }
1087 
1088             @Override
1089             public void serialize(final Byte object, final byte[] buffer, final Pointer pointer, final EndianUtil endianUtil)
1090                     throws SerializationException
1091             {
1092                 // Auto-generated method stub; never called
1093             }
1094 
1095             @Override
1096             public void serializeWithPrefix(final Byte object, final byte[] buffer, final Pointer pointer,
1097                     final EndianUtil endianUtil) throws SerializationException
1098             {
1099                 // Auto-generated method stub; never called
1100             }
1101 
1102             @Override
1103             public Byte deSerialize(final byte[] buffer, final Pointer pointer, final EndianUtil endianUtil)
1104                     throws SerializationException
1105             {
1106                 // Auto-generated method stub; never called
1107                 return null;
1108             }
1109 
1110             @Override
1111             public int getNumberOfDimensions()
1112             {
1113                 // Auto-generated method stub
1114                 return 0;
1115             }
1116         };
1117         // We only want to test two methods; so we don't have to provide real implementation for other methods
1118         assertEquals(dataClassName, testSerializer.dataClassName(), "data class name is returned");
1119         assertTrue(testSerializer.toString().startsWith("BasicSerializer"), "toString returns something descriptive");
1120     }
1121 
1122 }