content: package net.agkn.hll.serialization;
  
  /*
   * Copyright 2013 Aggregate Knowledge, Inc.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  
  import org.testng.annotations.Test;
  import java.util.Random;
  
  import static org.testng.Assert.assertEquals;
  import static org.testng.Assert.assertTrue;
  import static org.testng.Assert.fail;
  
  /**
   * Unit and smoke tests for {@link BigEndianAscendingWordDeserializer}.
   *
   * @author timon
   */
  public class BigEndianAscendingWordDeserializerTest {
      /**
       * Error checking tests for constructor.
       */
      @SuppressWarnings("unused")
      @Test
      public void constructorErrorTest() {
          // word length too small
          try {
              new BigEndianAscendingWordDeserializer(0/*wordLength, below minimum of 1*/, 0/*bytePadding, arbitrary*/, new byte[1]/*bytes, arbitrary, not used here*/);
              fail("Should complain about too-short words.");
          } catch(final IllegalArgumentException e) {
              assertTrue(e.getMessage().contains("Word length must be"));
          }
  
          // word length too large
          try {
              new BigEndianAscendingWordDeserializer(65/*wordLength, above maximum of 64*/, 0/*bytePadding, arbitrary*/, new byte[1]/*bytes, arbitrary, not used here*/);
              fail("Should complain about too-long words.");
          } catch(final IllegalArgumentException e) {
              assertTrue(e.getMessage().contains("Word length must be"));
          }
  
          // byte padding negative
          try {
              new BigEndianAscendingWordDeserializer(5/*wordLength, arbitrary*/, -1/*bytePadding, too small*/, new byte[1]/*bytes, arbitrary, not used here*/);
              fail("Should complain about negative byte padding.");
          } catch(final IllegalArgumentException e) {
              assertTrue(e.getMessage().contains("Byte padding must be"));
          }
      }
  
      /**
       * Smoke test using 64-bit short words and special word values.
       */
      @Test
      public void smokeTest64BitWord() {
          final BigEndianAscendingWordSerializer serializer =
              new BigEndianAscendingWordSerializer(64/*wordLength*/,
                                                   5/*wordCount*/,
                                                   0/*bytePadding, arbitrary*/);
  
          // Check that the sign bit is being preserved.
          serializer.writeWord(-1L);
          serializer.writeWord(-112894714L);
  
          // Check "special" values
          serializer.writeWord(0L);
          serializer.writeWord(Long.MAX_VALUE);
          serializer.writeWord(Long.MIN_VALUE);
  
          final byte[] bytes = serializer.getBytes();
  
          final BigEndianAscendingWordDeserializer deserializer =
              new BigEndianAscendingWordDeserializer(64/*wordLength*/, 0/*bytePadding*/, bytes);
  
          assertEquals(deserializer.totalWordCount(), 5/*wordCount*/);
  
          assertEquals(deserializer.readWord(), -1L);
          assertEquals(deserializer.readWord(), -112894714L);
          assertEquals(deserializer.readWord(), 0L);
          assertEquals(deserializer.readWord(), Long.MAX_VALUE);
          assertEquals(deserializer.readWord(), Long.MIN_VALUE);
      }
  
      /**
       * A smoke/fuzz test for ascending (from zero) word values.
       */
      @Test
      public void ascendingSmokeTest() {
          for(int wordLength=5; wordLength<65; wordLength++) {
              runAscendingTest(wordLength, 3/*bytePadding, arbitrary*/, 100000/*wordCount, arbitrary*/);
          }
      }
  
      /**
       * A smoke/fuzz test for random word values.
       */
      @Test
      public void randomSmokeTest() {
          for(int wordLength=5; wordLength<65; wordLength++) {
              runRandomTest(wordLength, 3/*bytePadding, arbitrary*/, 100000/*wordCount, arbitrary*/, (long)wordLength/*seed, arbitrary*/);
          }
      }
  
      // ------------------------------------------------------------------------
      /**
       * Runs a test which serializes and deserializes random word values.
       *
       * @param wordLength the length of words to test
       * @param bytePadding the number of bytes padding the byte array
       * @param wordCount the number of word values to test
       * @param seed the seed to the random value generator
       */
      private static void runRandomTest(final int wordLength, final int bytePadding, final int wordCount, final long seed) {
          final Random random = new Random(seed);
          final Random verificationRandom = new Random(seed);
  
          final long wordMask;
          if(wordLength == 64) {
              wordMask = ~0L;
          } else {
              wordMask = (1L << wordLength) - 1L;
          }
  
          final BigEndianAscendingWordSerializer serializer =
              new BigEndianAscendingWordSerializer(wordLength/*wordLength, arbitrary*/,
                                                   wordCount,
                                                   bytePadding/*bytePadding, arbitrary*/);
  
          for(int i=0; i<wordCount; i++) {
              final long value = random.nextLong() & wordMask;
              serializer.writeWord(value);
          }
  
          final byte[] bytes = serializer.getBytes();
  
          final BigEndianAscendingWordDeserializer deserializer =
              new BigEndianAscendingWordDeserializer(wordLength, bytePadding, bytes);
  
          assertEquals(deserializer.totalWordCount(), wordCount);
          for(int i=0; i<wordCount; i++) {
              assertEquals(deserializer.readWord(), (verificationRandom.nextLong() & wordMask));
          }
      }
  
      /**
       * Runs a test which serializes and deserializes ascending (from zero) word values.
       *
       * @param wordLength the length of words to test
       * @param bytePadding the number of bytes padding the byte array
       * @param wordCount the number of word values to test
       */
      private static void runAscendingTest(final int wordLength, final int bytePadding, final int wordCount) {
          final long wordMask;
          if(wordLength == 64) {
              wordMask = ~0L;
          } else {
              wordMask = (1L << wordLength) - 1L;
          }
  
          final BigEndianAscendingWordSerializer serializer =
              new BigEndianAscendingWordSerializer(wordLength/*wordLength, arbitrary*/,
                                                   wordCount,
                                                   bytePadding/*bytePadding, arbitrary*/);
  
          for(long i=0; i<wordCount; i++) {
              serializer.writeWord(i & wordMask);
          }
  
          final byte[] bytes = serializer.getBytes();
  
          final BigEndianAscendingWordDeserializer deserializer =
              new BigEndianAscendingWordDeserializer(wordLength, bytePadding, bytes);
  
          assertEquals(deserializer.totalWordCount(), wordCount);
          for(long i=0; i<wordCount; i++) {
              assertEquals(deserializer.readWord(), i & wordMask);
          }
      }
  }
  