/* * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0, * and the EPL 1.0 (http://h2database.com/html/license.html). * Initial Developer: H2 Group */ package org.h2.test.unit; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Random; import org.h2.dev.util.BinaryArithmeticStream; import org.h2.dev.util.BinaryArithmeticStream.Huffman; import org.h2.dev.util.BinaryArithmeticStream.In; import org.h2.dev.util.BinaryArithmeticStream.Out; import org.h2.dev.util.BitStream; import org.h2.test.TestBase; /** * Test the binary arithmetic stream utility. */ public class TestBinaryArithmeticStream extends TestBase { /** * Run just this test. * * @param a ignored */ public static void main(String... a) throws Exception { TestBase.createCaller().init().test(); } @Override public void test() throws Exception { testCompareWithHuffman(); testHuffmanRandomized(); testCompressionRatio(); testRandomized(); testPerformance(); } private void testCompareWithHuffman() throws IOException { Random r = new Random(1); for (int test = 0; test < 10; test++) { int[] freq = new int[4]; for (int i = 0; i < freq.length; i++) { freq[i] = 0 + r.nextInt(1000); } BinaryArithmeticStream.Huffman ah = new BinaryArithmeticStream.Huffman( freq); BitStream.Huffman hh = new BitStream.Huffman(freq); ByteArrayOutputStream hbOut = new ByteArrayOutputStream(); ByteArrayOutputStream abOut = new ByteArrayOutputStream(); BitStream.Out bOut = new BitStream.Out(hbOut); BinaryArithmeticStream.Out aOut = new BinaryArithmeticStream.Out(abOut); for (int i = 0; i < freq.length; i++) { for (int j = 0; j < freq[i]; j++) { int x = i; hh.write(bOut, x); ah.write(aOut, x); } } assertTrue(hbOut.toByteArray().length >= abOut.toByteArray().length); } } private void testHuffmanRandomized() throws IOException { Random r = new Random(1); int[] freq = new int[r.nextInt(200) + 1]; for (int i = 0; i < freq.length; i++) { freq[i] = r.nextInt(1000) + 1; } int seed = r.nextInt(); r.setSeed(seed); Huffman huff = new Huffman(freq); ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); Out out = new Out(byteOut); for (int i = 0; i < 10000; i++) { huff.write(out, r.nextInt(freq.length)); } out.flush(); In in = new In(new ByteArrayInputStream(byteOut.toByteArray())); r.setSeed(seed); for (int i = 0; i < 10000; i++) { int expected = r.nextInt(freq.length); int got = huff.read(in); assertEquals(expected, got); } } private void testPerformance() throws IOException { Random r = new Random(); // long time = System.nanoTime(); // Profiler prof = new Profiler().startCollecting(); for (int seed = 0; seed < 10000; seed++) { r.setSeed(seed); ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); Out out = new Out(byteOut); int len = 100; for (int i = 0; i < len; i++) { boolean v = r.nextBoolean(); int prob = r.nextInt(BinaryArithmeticStream.MAX_PROBABILITY); out.writeBit(v, prob); } out.flush(); r.setSeed(seed); ByteArrayInputStream byteIn = new ByteArrayInputStream( byteOut.toByteArray()); In in = new In(byteIn); for (int i = 0; i < len; i++) { boolean expected = r.nextBoolean(); int prob = r.nextInt(BinaryArithmeticStream.MAX_PROBABILITY); assertEquals(expected, in.readBit(prob)); } } // time = System.nanoTime() - time; // System.out.println("time: " + TimeUnit.NANOSECONDS.toMillis(time)); // System.out.println(prof.getTop(5)); } private void testCompressionRatio() throws IOException { ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); Out out = new Out(byteOut); int prob = 1000; int len = 1024; for (int i = 0; i < len; i++) { out.writeBit(true, prob); } out.flush(); ByteArrayInputStream byteIn = new ByteArrayInputStream( byteOut.toByteArray()); In in = new In(byteIn); for (int i = 0; i < len; i++) { assertTrue(in.readBit(prob)); } // System.out.println(len / 8 + " comp: " + // byteOut.toByteArray().length); } private void testRandomized() throws IOException { for (int i = 0; i < 10000; i = (int) ((i + 10) * 1.1)) { testRandomized(i); } } private void testRandomized(int len) throws IOException { Random r = new Random(); int seed = r.nextInt(); r.setSeed(seed); ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); Out out = new Out(byteOut); for (int i = 0; i < len; i++) { int prob = r.nextInt(BinaryArithmeticStream.MAX_PROBABILITY); out.writeBit(r.nextBoolean(), prob); } out.flush(); byteOut.write(r.nextInt(255)); ByteArrayInputStream byteIn = new ByteArrayInputStream( byteOut.toByteArray()); In in = new In(byteIn); r.setSeed(seed); for (int i = 0; i < len; i++) { int prob = r.nextInt(BinaryArithmeticStream.MAX_PROBABILITY); boolean expected = r.nextBoolean(); boolean got = in.readBit(prob); assertEquals(expected, got); } assertEquals(r.nextInt(255), byteIn.read()); } }