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