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-2019 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         public Integer intValue;
411 
412         /** Field 2. */
413         public Double doubleValue;
414 
415         @Override
416         public int hashCode()
417         {
418             final int prime = 31;
419             int result = 1;
420             result = prime * result + ((this.doubleValue == null) ? 0 : this.doubleValue.hashCode());
421             result = prime * result + ((this.intValue == null) ? 0 : this.intValue.hashCode());
422             return result;
423         }
424 
425         @SuppressWarnings("checkstyle:needbraces")
426         @Override
427         public boolean equals(final Object obj)
428         {
429             if (this == obj)
430                 return true;
431             if (obj == null)
432                 return false;
433             if (getClass() != obj.getClass())
434                 return false;
435             Compound other = (Compound) obj;
436             if (this.doubleValue == null)
437             {
438                 if (other.doubleValue != null)
439                     return false;
440             }
441             else if (!this.doubleValue.equals(other.doubleValue))
442                 return false;
443             if (this.intValue == null)
444             {
445                 if (other.intValue != null)
446                     return false;
447             }
448             else if (!this.intValue.equals(other.intValue))
449                 return false;
450             return true;
451         }
452 
453         @Override
454         public String toString()
455         {
456             return "Compound [intValue=" + this.intValue + ", doubleValue=" + this.doubleValue + "]";
457         }
458 
459         /**
460          * Construct a new Compound object.
461          * @param intValue int; the value to assign to intValue
462          * @param doubleValue double; the value to assign to doubleValue
463          */
464         Compound(final int intValue, final double doubleValue)
465         {
466             this.intValue = intValue;
467             this.doubleValue = doubleValue;
468         }
469 
470         @Override
471         public List<Object> exportAsList()
472         {
473             List<Object> result = new ArrayList<>();
474             result.add(this.intValue);
475             result.add(this.doubleValue);
476             return result;
477         }
478 
479     }
480 
481     /**
482      * Test the compound array encoder and decoder.
483      * @throws SerializationException when that happens uncaught, this test has failed
484      */
485     @Test
486     public void testCompoundArrays() throws SerializationException
487     {
488         Compound[] testArray = new Compound[] {new Compound(1, 0.1), new Compound(2, 0.2), new Compound(3, 0.3)};
489         Object[] objects = new Object[] {testArray};
490         for (EndianUtil endianUtil : new EndianUtil[] {EndianUtil.BIG_ENDIAN, EndianUtil.LITTLE_ENDIAN})
491         {
492             for (boolean encodeUTF8 : new boolean[] {false, true})
493             {
494                 // System.out.println("Encoding " + (encodeUTF8 ? "UTF8" : "UTF16") + ", " + endianUtil);
495                 byte[] serialized = encodeUTF8 ? TypedMessage.encodeUTF8(endianUtil, objects)
496                         : TypedMessage.encodeUTF16(endianUtil, objects);
497                 // System.out.print(HexDumper.hexDumper(serialized));
498                 for (boolean primitive : new boolean[] {false, true})
499                 {
500                     Object[] decodedObjects = primitive ? TypedMessage.decodeToPrimitiveDataTypes(serialized, endianUtil)
501                             : TypedMessage.decodeToObjectDataTypes(serialized, endianUtil);
502                     assertEquals("Size of decoded matches", objects.length, decodedObjects.length);
503                     // Replace all List objects in the result by corresponding new Compound objects
504                     for (int i = 0; i < objects.length; i++)
505                     {
506                         Object o = decodedObjects[i];
507                         if (o instanceof TypedMessage.MinimalSerializableObject[])
508                         {
509                             TypedMessage.MinimalSerializableObject[] in = ((TypedMessage.MinimalSerializableObject[]) o);
510                             Compound[] out = new Compound[in.length];
511                             for (int j = 0; j < in.length; j++)
512                             {
513                                 List<Object> fields = in[j].exportAsList();
514                                 Integer intValue = (Integer) fields.get(0);
515                                 Double doubleValue = (Double) fields.get(1);
516                                 out[j] = new Compound(intValue, doubleValue);
517                             }
518                             decodedObjects[i] = out;
519                         }
520                     }
521                     for (int i = 0; i < objects.length; i++)
522                     {
523                         if (objects[i] instanceof Compound[])
524                         {
525                             Compound[] in = (Compound[]) objects[i];
526                             assertTrue("decoded object is now also a Compound[]", decodedObjects[i] instanceof Compound[]);
527                             Compound[] out = (Compound[]) objects[i];
528                             assertEquals("Compound arrays have same length", in.length, out.length);
529                             for (int j = 0; j < in.length; j++)
530                             {
531                                 assertEquals("reconstructed compound object matches input", in[j], out[j]);
532                             }
533                         }
534                         else
535                         {
536                             assertTrue(
537                                     "decoded object at index " + i + "(" + objects[i]
538                                             + ") equals corresponding object in input",
539                                     deepEquals0(makePrimitive(objects[i]), makePrimitive(decodedObjects[i])));
540                         }
541                     }
542                 }
543             }
544         }
545     }
546 
547     /**
548      * Test serialization and deserialization of arrays of Djutils vectors.
549      * @throws ValueRuntimeException if that happens uncaught; this test has failed
550      * @throws SerializationException if that happens uncaught; this test has failed
551      */
552     @SuppressWarnings("unchecked")
553     @Test
554     public void testArrayOfDjutilsVectors() throws ValueRuntimeException, SerializationException
555     {
556         AbstractDoubleVector<?, ?, ?>[] array = new AbstractDoubleVector[] {
557                 DoubleVector.instantiate(new double[] {0.1, 0.2, 0.3}, LengthUnit.INCH, StorageType.DENSE),
558                 DoubleVector.instantiate(new double[] {10.1, 20.2, 30.3}, TimeUnit.BASE_MINUTE, StorageType.DENSE)};
559         Object[] objects = new Object[] {array};
560         for (EndianUtil endianUtil : new EndianUtil[] {EndianUtil.BIG_ENDIAN, EndianUtil.LITTLE_ENDIAN})
561         {
562             for (boolean encodeUTF8 : new boolean[] {false, true})
563             {
564                 // System.out.println("Encoding " + (encodeUTF8 ? "UTF8" : "UTF16") + ", " + endianUtil);
565                 byte[] serialized = encodeUTF8 ? TypedMessage.encodeUTF8(endianUtil, objects)
566                         : TypedMessage.encodeUTF16(endianUtil, objects);
567                 System.out.print(HexDumper.hexDumper(serialized));
568                 System.out.print(SerialDataDumper.serialDataDumper(endianUtil, serialized));
569                 for (boolean primitive : new boolean[] {false, true})
570                 {
571                     Object[] decodedObjects = primitive ? TypedMessage.decodeToPrimitiveDataTypes(serialized, endianUtil)
572                             : TypedMessage.decodeToObjectDataTypes(serialized, endianUtil);
573                     assertEquals("Size of decoded matches", objects.length, decodedObjects.length);
574                     for (int i = 0; i < objects.length; i++)
575                     {
576                         if (objects[i] instanceof AbstractDoubleVector<?, ?, ?>[])
577                         {
578                             AbstractDoubleVector<?, ?, ?>[] arrayIn = (AbstractDoubleVector<?, ?, ?>[]) objects[i];
579                             AbstractDoubleVector<?, ?, ?>[] arrayOut = (AbstractDoubleVector<?, ?, ?>[]) decodedObjects[i];
580                             for (int j = 0; j < arrayOut.length; j++)
581                             {
582                                 assertEquals("Decoded Djutils array vector element matches", arrayIn[j], arrayOut[j]);
583                             }
584                         }
585                         else
586                         {
587                             assertTrue(
588                                     "decoded object at index " + i + "(" + objects[i]
589                                             + ") equals corresponding object in input",
590                                     deepEquals0(makePrimitive(objects[i]), makePrimitive(decodedObjects[i])));
591                         }
592                     }
593                 }
594             }
595         }
596     }
597 
598     /**
599      * Test that jagged matrices are detected and cause a SerializationException.
600      */
601     @Test
602     public void testJaggedMatrices()
603     {
604         int[][] integer = new int[][] {{1, 2, 3}, {5, 6}};
605         Integer[][] integerValues2 = new Integer[][] {{-1, -2}, {-4, -5, -6}};
606         short[][] shortValues = new short[][] {{10, 20}, {40, 50, 60}};
607         Short[][] shortValues2 = new Short[][] {{-10, -20, -30}, {-40, -50}};
608         long[][] longValues = new long[][] {{1000, 2000, 3000}, {3000, 4000}};
609         Long[][] longValues2 = new Long[][] {{-1000L, -2000L}, {-3000L, -4000L, -5000L}};
610         byte[][] byteValues = new byte[][] {{12, 13}, {15, 16, 17}};
611         Byte[][] byteValues2 = new Byte[][] {{-12, -13, -14}, {-15, -16}};
612         boolean[][] boolValues = new boolean[][] {{false, true, true}, {false, false}};
613         Boolean[][] boolValues2 = new Boolean[][] {{true, true}, {true, true, true}};
614         float[][] floatValues = new float[][] {{12.3f, 23.4f}, {44.4f, 55.5f, 66.6f}};
615         Float[][] floatValues2 = new Float[][] {{-12.3f, -23.4f, -34.5f}, {-11.1f, -22.2f}};
616         double[][] doubleValues = new double[][] {{23.45, 34.56, 45.67}, {55.5, 66.6}};
617         Double[][] doubleValues2 = new Double[][] {{-23.45, -34.56}, {-22.2, -33.3, -44.4}};
618         Object[] objects = new Object[] {integer, integerValues2, shortValues, shortValues2, longValues, longValues2,
619                 byteValues, byteValues2, floatValues, floatValues2, doubleValues, doubleValues2, boolValues, boolValues2};
620         for (EndianUtil endianUtil : new EndianUtil[] {EndianUtil.BIG_ENDIAN, EndianUtil.LITTLE_ENDIAN})
621         {
622             for (Object object : objects)
623             {
624                 Object[] singleObjectArray = new Object[] {object};
625                 try
626                 {
627                     TypedMessage.encodeUTF16(endianUtil, singleObjectArray);
628                     fail("Jagged array should have thrown a SerializationException");
629                 }
630                 catch (SerializationException se)
631                 {
632                     // Ignore expected exception
633                 }
634                 try
635                 {
636                     TypedMessage.encodeUTF8(endianUtil, singleObjectArray);
637                     fail("Jagged array should have thrown a SerializationException");
638                 }
639                 catch (SerializationException se)
640                 {
641                     // Ignore expected exception
642                 }
643             }
644         }
645     }
646 
647     /**
648      * Test that the encoder throws a SerializationException when given something that it does not know how to serialize.
649      */
650     @Test
651     public void testUnhandledObject()
652     {
653         File file = new File("whatever");
654         Object[] objects = new Object[] {file};
655         for (EndianUtil endianUtil : new EndianUtil[] {EndianUtil.BIG_ENDIAN, EndianUtil.LITTLE_ENDIAN})
656         {
657             try
658             {
659                 TypedMessage.encodeUTF16(endianUtil, objects);
660                 fail("Non serializable object should have thrown a SerializationException");
661             }
662             catch (SerializationException se)
663             {
664                 // Ignore expected exception
665             }
666 
667             Integer[][] badMatrix = new Integer[0][0];
668             objects = new Object[] {badMatrix};
669             try
670             {
671                 TypedMessage.encodeUTF16(endianUtil, objects);
672                 fail("Zero sized matrix should have thrown a SerializationException");
673             }
674             catch (SerializationException se)
675             {
676                 // Ignore expected exception
677             }
678         }
679     }
680 
681     /**
682      * Test the Pointer class.
683      */
684     @Test
685     public void pointerTest()
686     {
687         Pointer pointer = new Pointer();
688         assertEquals("initial offset is 0", 0, pointer.get());
689         assertEquals("initial offset is 0", 0, pointer.getAndIncrement(10));
690         assertEquals("offset is now 10", 10, pointer.get());
691         pointer.inc(20);
692         assertEquals("offset is now 30", 30, pointer.get());
693         assertTrue("ToString method returns something descriptive", pointer.toString().startsWith("Pointer"));
694     }
695 
696     /**
697      * Convert an array, or matrix of Byte, Short, Integer, etc. to an array/matrix of byte, short, int, etc.
698      * @param in Object; the array to convert
699      * @return Object; the converted input (if conversion was possible), or the unconverted input.
700      */
701     static Object makePrimitive(final Object in)
702     {
703         if (in instanceof Byte[])
704         {
705             Byte[] byteIn = (Byte[]) in;
706             byte[] result = new byte[byteIn.length];
707             for (int i = 0; i < result.length; i++)
708             {
709                 result[i] = byteIn[i];
710             }
711             return result;
712         }
713         if (in instanceof Short[])
714         {
715             Short[] shortIn = (Short[]) in;
716             short[] result = new short[shortIn.length];
717             for (int i = 0; i < result.length; i++)
718             {
719                 result[i] = shortIn[i];
720             }
721             return result;
722         }
723         if (in instanceof Integer[])
724         {
725             Integer[] integerIn = (Integer[]) in;
726             int[] result = new int[integerIn.length];
727             for (int i = 0; i < result.length; i++)
728             {
729                 result[i] = integerIn[i];
730             }
731             return result;
732         }
733         if (in instanceof Long[])
734         {
735             Long[] longIn = (Long[]) in;
736             long[] result = new long[longIn.length];
737             for (int i = 0; i < result.length; i++)
738             {
739                 result[i] = longIn[i];
740             }
741             return result;
742         }
743         if (in instanceof Float[])
744         {
745             Float[] floatIn = (Float[]) in;
746             float[] result = new float[floatIn.length];
747             for (int i = 0; i < result.length; i++)
748             {
749                 result[i] = floatIn[i];
750             }
751             return result;
752         }
753         if (in instanceof Double[])
754         {
755             Double[] doubleIn = (Double[]) in;
756             double[] result = new double[doubleIn.length];
757             for (int i = 0; i < result.length; i++)
758             {
759                 result[i] = doubleIn[i];
760             }
761             return result;
762         }
763         if (in instanceof Boolean[])
764         {
765             Boolean[] booleanIn = (Boolean[]) in;
766             boolean[] result = new boolean[booleanIn.length];
767             for (int i = 0; i < result.length; i++)
768             {
769                 result[i] = booleanIn[i];
770             }
771             return result;
772         }
773         if (in instanceof Byte[][])
774         {
775             Byte[][] byteIn = (Byte[][]) in;
776             byte[][] result = new byte[byteIn.length][byteIn[0].length];
777             for (int i = 0; i < result.length; i++)
778             {
779                 for (int j = 0; j < result[0].length; j++)
780                 {
781                     result[i][j] = byteIn[i][j];
782                 }
783             }
784             return result;
785         }
786         if (in instanceof Short[][])
787         {
788             Short[][] shortIn = (Short[][]) in;
789             short[][] result = new short[shortIn.length][shortIn[0].length];
790             for (int i = 0; i < result.length; i++)
791             {
792                 for (int j = 0; j < result[0].length; j++)
793                 {
794                     result[i][j] = shortIn[i][j];
795                 }
796             }
797             return result;
798         }
799         if (in instanceof Integer[][])
800         {
801             Integer[][] integerIn = (Integer[][]) in;
802             int[][] result = new int[integerIn.length][integerIn[0].length];
803             for (int i = 0; i < result.length; i++)
804             {
805                 for (int j = 0; j < result[0].length; j++)
806                 {
807                     result[i][j] = integerIn[i][j];
808                 }
809             }
810             return result;
811         }
812         if (in instanceof Long[][])
813         {
814             Long[][] longIn = (Long[][]) in;
815             long[][] result = new long[longIn.length][longIn[0].length];
816             for (int i = 0; i < result.length; i++)
817             {
818                 for (int j = 0; j < result[0].length; j++)
819                 {
820                     result[i][j] = longIn[i][j];
821                 }
822             }
823             return result;
824         }
825         if (in instanceof Float[][])
826         {
827             Float[][] floatIn = (Float[][]) in;
828             float[][] result = new float[floatIn.length][floatIn[0].length];
829             for (int i = 0; i < result.length; i++)
830             {
831                 for (int j = 0; j < result[0].length; j++)
832                 {
833                     result[i][j] = floatIn[i][j];
834                 }
835             }
836             return result;
837         }
838         if (in instanceof Double[][])
839         {
840             Double[][] doubleIn = (Double[][]) in;
841             double[][] result = new double[doubleIn.length][doubleIn[0].length];
842             for (int i = 0; i < result.length; i++)
843             {
844                 for (int j = 0; j < result[0].length; j++)
845                 {
846                     result[i][j] = doubleIn[i][j];
847                 }
848             }
849             return result;
850         }
851         if (in instanceof Boolean[][])
852         {
853             Boolean[][] booleanIn = (Boolean[][]) in;
854             boolean[][] result = new boolean[booleanIn.length][booleanIn[0].length];
855             for (int i = 0; i < result.length; i++)
856             {
857                 for (int j = 0; j < result[0].length; j++)
858                 {
859                     result[i][j] = booleanIn[i][j];
860                 }
861             }
862             return result;
863         }
864         return in;
865     }
866 
867     /**
868      * Compare two arrays of any type (stolen from java.util.Arrays).
869      * @param e1 Object (should be some kind of array)
870      * @param e2 Object (should be some kind of array)
871      * @return boolean; true of the arrays have the same type, size and all elements in the arrays are equal to their
872      *         counterpart
873      */
874     static boolean deepEquals0(final Object e1, final Object e2)
875     {
876         if (e1 instanceof Object[] && e2 instanceof Object[])
877         {
878             return Arrays.deepEquals((Object[]) e1, (Object[]) e2);
879         }
880         if (e1 instanceof byte[] && e2 instanceof byte[])
881         {
882             return Arrays.equals((byte[]) e1, (byte[]) e2);
883         }
884         if (e1 instanceof short[] && e2 instanceof short[])
885         {
886             return Arrays.equals((short[]) e1, (short[]) e2);
887         }
888         if (e1 instanceof int[] && e2 instanceof int[])
889         {
890             return Arrays.equals((int[]) e1, (int[]) e2);
891         }
892         if (e1 instanceof long[] && e2 instanceof long[])
893         {
894             return Arrays.equals((long[]) e1, (long[]) e2);
895         }
896         if (e1 instanceof char[] && e2 instanceof char[])
897         {
898             return Arrays.equals((char[]) e1, (char[]) e2);
899         }
900         if (e1 instanceof float[] && e2 instanceof float[])
901         {
902             return Arrays.equals((float[]) e1, (float[]) e2);
903         }
904         if (e1 instanceof double[] && e2 instanceof double[])
905         {
906             return Arrays.equals((double[]) e1, (double[]) e2);
907         }
908         if (e1 instanceof boolean[] && e2 instanceof boolean[])
909         {
910             return Arrays.equals((boolean[]) e1, (boolean[]) e2);
911         }
912         return e1.equals(e2);
913     }
914 
915     /**
916      * Test the UnitType class.
917      */
918     @Test
919     public void testUnitType()
920     {
921         byte code = 127;
922         Class<AccelerationUnit> unitClass = AccelerationUnit.class;
923         String name = "AccelerationName";
924         String description = "AccelerationDescription";
925         String siUnit = "[m/s^2]";
926         SerializationUnits testAccelerationUnitType = new SerializationUnits(code, unitClass, name, description, siUnit);
927         assertEquals("code is returned", code, testAccelerationUnitType.getCode());
928         assertEquals("unit class is returned", unitClass, testAccelerationUnitType.getDjunitsType());
929         assertEquals("name is returned", name, testAccelerationUnitType.getName());
930         assertEquals("description is returned", description, testAccelerationUnitType.getDescription());
931         assertEquals("SI unit is returned", siUnit, testAccelerationUnitType.getSiUnit());
932         assertTrue("toString returns something descriptive", testAccelerationUnitType.toString().startsWith("UnitType"));
933 
934         byte undefined = 126;
935         assertEquals("new unit is in the byte type map", testAccelerationUnitType, SerializationUnits.getUnitType(code));
936         assertNull("undefined byte returns null", SerializationUnits.getUnitType(undefined));
937         assertEquals("djunits type is returned", unitClass, SerializationUnits.getUnitClass(code));
938         assertNull("undefined byte returns null", SerializationUnits.getUnitClass(undefined));
939         assertEquals("speed type can be found by byte code", SerializationUnits.SPEED,
940                 SerializationUnits.getUnitType((byte) 22));
941         assertEquals("speed type can be found by unit type", SerializationUnits.SPEED,
942                 SerializationUnits.getUnitType(SpeedUnit.SI));
943         assertEquals("speed type can be found by non SI unit type", SerializationUnits.SPEED,
944                 SerializationUnits.getUnitType(SpeedUnit.FOOT_PER_SECOND));
945         assertEquals("speed unit code can be found by unit type", 22, SerializationUnits.getUnitCode(SpeedUnit.SI));
946     }
947 
948     /**
949      * Test all constructors for SerializationException.
950      */
951     @Test
952     public final void serializationExceptionTest()
953     {
954         String message = "MessageString";
955         Exception e = new SerializationException(message);
956         assertEquals("message should be our message", message, e.getMessage());
957         assertEquals("cause should be null", null, e.getCause());
958         e = new SerializationException();
959         assertEquals("cause should be null", null, e.getCause());
960         String causeString = "CauseString";
961         Throwable cause = new Throwable(causeString);
962         e = new SerializationException(cause);
963         assertEquals("cause should not be our cause", cause, e.getCause());
964         assertEquals("cause description should be our cause string", causeString, e.getCause().getMessage());
965         e = new SerializationException(message, cause);
966         assertEquals("message should be our message", message, e.getMessage());
967         assertEquals("cause should not be our cause", cause, e.getCause());
968         assertEquals("cause description should be our cause string", causeString, e.getCause().getMessage());
969         for (boolean enableSuppression : new boolean[] {true, false})
970         {
971             for (boolean writableStackTrace : new boolean[] {true, false})
972             {
973                 e = new SerializationException(message, cause, enableSuppression, writableStackTrace);
974                 assertTrue("Exception should not be null", null != e);
975                 assertEquals("message should be our message", message, e.getMessage());
976                 assertEquals("cause should not be our cause", cause, e.getCause());
977                 assertEquals("cause description should be our cause string", causeString, e.getCause().getMessage());
978                 // Don't know how to check if suppression is enabled/disabled
979                 StackTraceElement[] stackTrace = new StackTraceElement[1];
980                 stackTrace[0] = new StackTraceElement("a", "b", "c", 1234);
981                 try
982                 {
983                     e.setStackTrace(stackTrace);
984                 }
985                 catch (Exception e1)
986                 {
987                     assertTrue("Stack trace should be writable", writableStackTrace);
988                     continue;
989                 }
990                 // You wouldn't believe it, but a call to setStackTrace if non-writable is silently ignored
991                 StackTraceElement[] retrievedStackTrace = e.getStackTrace();
992                 if (retrievedStackTrace.length > 0)
993                 {
994                     assertTrue("stack trace should be writable", writableStackTrace);
995                 }
996             }
997         }
998     }
999 
1000     /**
1001      * Test all constructors for SerializationRuntimeException.
1002      */
1003     @Test
1004     public final void serializationRuntimeExceptionTest()
1005     {
1006         String message = "MessageString";
1007         Exception e = new SerializationRuntimeException(message);
1008         assertEquals("message should be our message", message, e.getMessage());
1009         assertEquals("cause should be null", null, e.getCause());
1010         e = new SerializationRuntimeException();
1011         assertEquals("cause should be null", null, e.getCause());
1012         String causeString = "CauseString";
1013         Throwable cause = new Throwable(causeString);
1014         e = new SerializationRuntimeException(cause);
1015         assertEquals("cause should not be our cause", cause, e.getCause());
1016         assertEquals("cause description should be our cause string", causeString, e.getCause().getMessage());
1017         e = new SerializationRuntimeException(message, cause);
1018         assertEquals("message should be our message", message, e.getMessage());
1019         assertEquals("cause should not be our cause", cause, e.getCause());
1020         assertEquals("cause description should be our cause string", causeString, e.getCause().getMessage());
1021         for (boolean enableSuppression : new boolean[] {true, false})
1022         {
1023             for (boolean writableStackTrace : new boolean[] {true, false})
1024             {
1025                 e = new SerializationRuntimeException(message, cause, enableSuppression, writableStackTrace);
1026                 assertTrue("Exception should not be null", null != e);
1027                 assertEquals("message should be our message", message, e.getMessage());
1028                 assertEquals("cause should not be our cause", cause, e.getCause());
1029                 assertEquals("cause description should be our cause string", causeString, e.getCause().getMessage());
1030                 // Don't know how to check if suppression is enabled/disabled
1031                 StackTraceElement[] stackTrace = new StackTraceElement[1];
1032                 stackTrace[0] = new StackTraceElement("a", "b", "c", 1234);
1033                 try
1034                 {
1035                     e.setStackTrace(stackTrace);
1036                 }
1037                 catch (Exception e1)
1038                 {
1039                     assertTrue("Stack trace should be writable", writableStackTrace);
1040                     continue;
1041                 }
1042                 // You wouldn't believe it, but a call to setStackTrace if non-writable is silently ignored
1043                 StackTraceElement[] retrievedStackTrace = e.getStackTrace();
1044                 if (retrievedStackTrace.length > 0)
1045                 {
1046                     assertTrue("stack trace should be writable", writableStackTrace);
1047                 }
1048             }
1049         }
1050     }
1051 
1052     /**
1053      * Test the remainder of the EndianUtil class.
1054      */
1055     @Test
1056     public void testEndianUtil()
1057     {
1058         assertTrue("EndianUtil.BIG_ENDIAN is big endian", EndianUtil.BIG_ENDIAN.isBigEndian());
1059         assertFalse("EndianUtil.LITTLE_ENDIAN is not big endian", EndianUtil.LITTLE_ENDIAN.isBigEndian());
1060         assertEquals("Platform endianness matches what EndianUtil says", ByteOrder.nativeOrder().equals(ByteOrder.BIG_ENDIAN),
1061                 EndianUtil.isPlatformBigEndian());
1062         assertTrue("EndianUtil.BIG_ENDIAN is big endian", EndianUtil.bigEndian().isBigEndian());
1063         assertFalse("EndianUtil.LITTLE_ENDIAN is not big endian", EndianUtil.littleEndian().isBigEndian());
1064         assertTrue("EndianUtil has descriptive toString method", EndianUtil.BIG_ENDIAN.toString().startsWith("EndianUtil"));
1065     }
1066 
1067     /**
1068      * Test the toString and dataClassName methods of the BasicSerializer.
1069      */
1070     @Test
1071     public void testBasicSerializer()
1072     {
1073         byte code = 123;
1074         String dataClassName = "dataClass";
1075         BasicSerializer<Byte> testSerializer = new BasicSerializer<Byte>(code, dataClassName)
1076         {
1077 
1078             @Override
1079             public int size(final Byte object) throws SerializationException
1080             {
1081                 // Auto-generated method stub; never called
1082                 return 0;
1083             }
1084 
1085             @Override
1086             public int sizeWithPrefix(final Byte object) throws SerializationException
1087             {
1088                 // Auto-generated method stub; never called
1089                 return 0;
1090             }
1091 
1092             @Override
1093             public void serialize(final Byte object, final byte[] buffer, final Pointer pointer, final EndianUtil endianUtil)
1094                     throws SerializationException
1095             {
1096                 // Auto-generated method stub; never called
1097             }
1098 
1099             @Override
1100             public void serializeWithPrefix(final Byte object, final byte[] buffer, final Pointer pointer,
1101                     final EndianUtil endianUtil) throws SerializationException
1102             {
1103                 // Auto-generated method stub; never called
1104             }
1105 
1106             @Override
1107             public Byte deSerialize(final byte[] buffer, final Pointer pointer, final EndianUtil endianUtil)
1108                     throws SerializationException
1109             {
1110                 // Auto-generated method stub; never called
1111                 return null;
1112             }
1113 
1114             @Override
1115             public int getNumberOfDimensions()
1116             {
1117                 // Auto-generated method stub
1118                 return 0;
1119             }
1120         };
1121         // We only want to test two methods; so we don't have to provide real implementation for other methods
1122         assertEquals("data class name is returned", dataClassName, testSerializer.dataClassName());
1123         assertTrue("toString returns something descriptive", testSerializer.toString().startsWith("BasicSerializer"));
1124     }
1125 
1126 }