11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// Copyright 2011 Google Inc. All Rights Reserved. 21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 31d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpackage com.google.common.hash; 41d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 51d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.collect.Iterables; 61d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.collect.Lists; 71d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.hash.AbstractStreamingHashFunction.AbstractStreamingHasher; 81d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.hash.HashTestUtils.RandomHasherAction; 91d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport junit.framework.TestCase; 111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.io.ByteArrayOutputStream; 131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.nio.ByteBuffer; 141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.nio.ByteOrder; 151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.nio.charset.Charset; 161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Arrays; 171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Collections; 181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.List; 191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Random; 201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/** 221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Tests for AbstractHashSink. 231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author andreou@google.com (Dimitris Andreou) 251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpublic class AbstractStreamingHasherTest extends TestCase { 271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** Test we get the HashCode that is created by the sink. Later we ignore the result */ 281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testSanity() { 291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Sink sink = new Sink(4); 301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(0xDeadBeef, sink.makeHash().asInt()); 311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testBytes() { 341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Sink sink = new Sink(4); // byte order insignificant here 351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert byte[] expected = { 1, 2, 3, 4, 5, 6, 7, 8 }; 361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert sink.putByte((byte) 1); 371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert sink.putBytes(new byte[] { 2, 3, 4, 5, 6 }); 381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert sink.putByte((byte) 7); 391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert sink.putBytes(new byte[] { }); 401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert sink.putBytes(new byte[] { 8 }); 411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert sink.hash(); 421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert sink.assertInvariants(8); 431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert sink.assertBytes(expected); 441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testShort() { 471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Sink sink = new Sink(4); 481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert sink.putShort((short) 0x0201); 491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert sink.hash(); 501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert sink.assertInvariants(2); 511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert sink.assertBytes(new byte[] { 1, 2, 0, 0 }); // padded with zeros 521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testInt() { 551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Sink sink = new Sink(4); 561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert sink.putInt(0x04030201); 571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert sink.hash(); 581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert sink.assertInvariants(4); 591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert sink.assertBytes(new byte[] { 1, 2, 3, 4 }); 601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testLong() { 631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Sink sink = new Sink(8); 641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert sink.putLong(0x0807060504030201L); 651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert sink.hash(); 661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert sink.assertInvariants(8); 671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert sink.assertBytes(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }); 681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testChar() { 711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Sink sink = new Sink(4); 721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert sink.putChar((char) 0x0201); 731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert sink.hash(); 741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert sink.assertInvariants(2); 751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert sink.assertBytes(new byte[] { 1, 2, 0, 0 }); // padded with zeros 761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testFloat() { 791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Sink sink = new Sink(4); 801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert sink.putFloat(Float.intBitsToFloat(0x04030201)); 811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert sink.hash(); 821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert sink.assertInvariants(4); 831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert sink.assertBytes(new byte[] { 1, 2, 3, 4 }); 841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testDouble() { 871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Sink sink = new Sink(8); 881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert sink.putDouble(Double.longBitsToDouble(0x0807060504030201L)); 891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert sink.hash(); 901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert sink.assertInvariants(8); 911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert sink.assertBytes(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }); 921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testCorrectExceptions() { 951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Sink sink = new Sink(4); 961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert try { 971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert sink.putBytes(new byte[8], -1, 4); 981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert fail(); 991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } catch (IndexOutOfBoundsException ok) {} 1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert try { 1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert sink.putBytes(new byte[8], 0, 16); 1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert fail(); 1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } catch (IndexOutOfBoundsException ok) {} 1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert try { 1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert sink.putBytes(new byte[8], 0, -1); 1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert fail(); 1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } catch (IndexOutOfBoundsException ok) {} 1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * This test creates a long random sequence of inputs, then a lot of differently configured 1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * sinks process it; all should produce the same answer, the only difference should be the 1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * number of process()/processRemaining() invocations, due to alignment. 1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void testExhaustive() throws Exception { 1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Random random = new Random(0); // will iteratively make more debuggable, each time it breaks 1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert for (int totalInsertions = 0; totalInsertions < 200; totalInsertions++) { 1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert List<Sink> sinks = Lists.newArrayList(); 1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert for (int chunkSize = 4; chunkSize <= 32; chunkSize++) { 1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert for (int bufferSize = chunkSize; bufferSize <= chunkSize * 4; bufferSize += chunkSize) { 1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // yes, that's a lot of sinks! 1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert sinks.add(new Sink(chunkSize, bufferSize)); 1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // For convenience, testing only with big endianness, to match DataOutputStream. 1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // I regard highly unlikely that both the little endianness tests above and this one 1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // passes, and there is still a little endianness bug lurking around. 1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Control control = new Control(); 1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Hasher controlSink = control.newHasher(1024); 1321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Iterable<Hasher> sinksAndControl = Iterables.concat( 1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert sinks, Collections.singleton(controlSink)); 1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert for (int insertion = 0; insertion < totalInsertions; insertion++) { 1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert RandomHasherAction.pickAtRandom(random).performAction(random, sinksAndControl); 1371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert for (Sink sink : sinks) { 1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert sink.hash(); 1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert byte[] expected = controlSink.hash().asBytes(); 1431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert for (Sink sink : sinks) { 1441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert sink.assertInvariants(expected.length); 1451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert sink.assertBytes(expected); 1461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static class Sink extends AbstractStreamingHasher { 1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final int chunkSize; 1521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final int bufferSize; 1531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final ByteArrayOutputStream out = new ByteArrayOutputStream(); 1541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert int processCalled = 0; 1561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert boolean remainingCalled = false; 1571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Sink(int chunkSize, int bufferSize) { 1591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert super(chunkSize, bufferSize); 1601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.chunkSize = chunkSize; 1611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.bufferSize = bufferSize; 1621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Sink(int chunkSize) { 1651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert super(chunkSize); 1661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.chunkSize = chunkSize; 1671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.bufferSize = chunkSize; 1681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override HashCode makeHash() { 1711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return HashCodes.fromInt(0xDeadBeef); 1721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override protected void process(ByteBuffer bb) { 1751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert processCalled++; 1761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(ByteOrder.LITTLE_ENDIAN, bb.order()); 1771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(bb.remaining() >= chunkSize); 1781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert for (int i = 0; i < chunkSize; i++) { 1791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert out.write(bb.get()); 1801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override protected void processRemaining(ByteBuffer bb) { 1841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertFalse(remainingCalled); 1851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert remainingCalled = true; 1861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(ByteOrder.LITTLE_ENDIAN, bb.order()); 1871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(bb.remaining() > 0); 1881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertTrue(bb.remaining() < bufferSize); 1891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert int before = processCalled; 1901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert super.processRemaining(bb); 1911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert int after = processCalled; 1921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(before + 1, after); // default implementation pads and calls process() 1931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert processCalled--; // don't count the tail invocation (makes tests a bit more understandable) 1941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // ensures that the number of invocations looks sane 1971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert void assertInvariants(int expectedBytes) { 1981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // we should have seen as many bytes as the next multiple of chunk after expectedBytes - 1 1991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(out.toByteArray().length, ceilToMultiple(expectedBytes, chunkSize)); 2001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(expectedBytes / chunkSize, processCalled); 2011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(expectedBytes % chunkSize != 0, remainingCalled); 2021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // returns the minimum x such as x >= a && (x % b) == 0 2051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static int ceilToMultiple(int a, int b) { 2061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert int remainder = a % b; 2071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return remainder == 0 ? a : a + b - remainder; 2081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert void assertBytes(byte[] expected) { 2111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert byte[] got = out.toByteArray(); 2121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert for (int i = 0; i < expected.length; i++) { 2131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(expected[i], got[i]); 2141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static class Control extends AbstractNonStreamingHashFunction { 2191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 2201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public HashCode hashBytes(byte[] input) { 2211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return HashCodes.fromBytes(input); 2221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 2251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public HashCode hashBytes(byte[] input, int off, int len) { 2261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return hashBytes(Arrays.copyOfRange(input, off, off + len)); 2271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 2301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public int bits() { 2311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw new UnsupportedOperationException(); 2321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 2351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public HashCode hashString(CharSequence input) { 2361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw new UnsupportedOperationException(); 2371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 2401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public HashCode hashString(CharSequence input, Charset charset) { 2411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw new UnsupportedOperationException(); 2421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 2451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public HashCode hashLong(long input) { 2461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw new UnsupportedOperationException(); 2471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} 250