content: package net.agkn.hll.serialization;
  
  import net.agkn.hll.HLL;
  import net.agkn.hll.HLLType;
  import org.testng.annotations.Test;
  
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.List;
  import java.util.Random;
  
  import static net.agkn.hll.HLL.MAXIMUM_EXPTHRESH_PARAM;
  import static net.agkn.hll.HLL.MAXIMUM_REGWIDTH_PARAM;
  import static net.agkn.hll.HLL.MINIMUM_EXPTHRESH_PARAM;
  import static net.agkn.hll.HLL.MINIMUM_LOG2M_PARAM;
  import static net.agkn.hll.HLL.MINIMUM_REGWIDTH_PARAM;
  import static org.testng.Assert.assertEquals;
  
  /**
   * Serialization smoke-tests.
   *
   * @author yerenkow
   * @author benl
   */
  public class HLLSerializationTest {
      // A fixed random seed so that this test is reproducible.
      private static final long RANDOM_SEED = 1L;
  
      /**
       * A smoke-test that covers serialization/deserialization of an HLL
       * under all possible parameters.
       */
      @Test
      public void serializationSmokeTest() throws Exception {
          final Random random = new Random(RANDOM_SEED);
          final int randomCount = 250;
          final List<Long> randoms = new ArrayList<Long>(randomCount){{
              for (int i=0; i<randomCount; i++) {
                  add(random.nextLong());
              }
          }};
  
          assertCardinality(HLLType.EMPTY, randoms);
          assertCardinality(HLLType.EXPLICIT, randoms);
          assertCardinality(HLLType.SPARSE, randoms);
          assertCardinality(HLLType.FULL, randoms);
      }
  
      // NOTE: log2m<=16 was chosen as the max log2m parameter so that the test
      //       completes in a reasonable amount of time. Not much is gained by
      //       testing larger values - there are no more known serialization
      //       related edge cases that appear as log2m gets even larger.
      // NOTE: This test completed successfully with log2m<=MAXIMUM_LOG2M_PARAM
      //       on 2014-01-30.
      private static void assertCardinality(final HLLType hllType, final Collection<Long> items)
             throws CloneNotSupportedException {
          for(int log2m=MINIMUM_LOG2M_PARAM; log2m<=16; log2m++) {
              for(int regw=MINIMUM_REGWIDTH_PARAM; regw<=MAXIMUM_REGWIDTH_PARAM; regw++) {
                  for(int expthr=MINIMUM_EXPTHRESH_PARAM; expthr<=MAXIMUM_EXPTHRESH_PARAM; expthr++ ) {
                      for(final boolean sparse: new boolean[]{true, false}) {
                          HLL hll = new HLL(log2m, regw, expthr, sparse, hllType);
                          for(final Long item: items) {
                              hll.addRaw(item);
                          }
                          HLL copy = HLL.fromBytes(hll.toBytes());
                          assertEquals(copy.cardinality(), hll.cardinality());
                          assertEquals(copy.getType(), hll.getType());
                          assertEquals(copy.toBytes(), hll.toBytes());
  
                          HLL clone = hll.clone();
                          assertEquals(clone.cardinality(), hll.cardinality());
                          assertEquals(clone.getType(), hll.getType());
                          assertEquals(clone.toBytes(), hll.toBytes());
                      }
                  }
              }
          }
      }
  }
  