diff options
Diffstat (limited to 'guava-tests/test/com/google/common/hash/AbstractStreamingHasherTest.java')
-rw-r--r-- | guava-tests/test/com/google/common/hash/AbstractStreamingHasherTest.java | 115 |
1 files changed, 39 insertions, 76 deletions
diff --git a/guava-tests/test/com/google/common/hash/AbstractStreamingHasherTest.java b/guava-tests/test/com/google/common/hash/AbstractStreamingHasherTest.java index 7324e6f..8f1cbb4 100644 --- a/guava-tests/test/com/google/common/hash/AbstractStreamingHasherTest.java +++ b/guava-tests/test/com/google/common/hash/AbstractStreamingHasherTest.java @@ -1,23 +1,7 @@ -/* - * Copyright (C) 2011 The Guava Authors - * - * 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. - */ +// Copyright 2011 Google Inc. All Rights Reserved. package com.google.common.hash; -import static com.google.common.base.Charsets.UTF_16LE; - import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.hash.AbstractStreamingHashFunction.AbstractStreamingHasher; @@ -35,24 +19,30 @@ import java.util.List; import java.util.Random; /** - * Tests for AbstractStreamingHasher. - * - * @author Dimitris Andreou + * Tests for AbstractHashSink. + * + * @author andreou@google.com (Dimitris Andreou) */ public class AbstractStreamingHasherTest extends TestCase { + /** Test we get the HashCode that is created by the sink. Later we ignore the result */ + public void testSanity() { + Sink sink = new Sink(4); + assertEquals(0xDeadBeef, sink.makeHash().asInt()); + } + public void testBytes() { Sink sink = new Sink(4); // byte order insignificant here byte[] expected = { 1, 2, 3, 4, 5, 6, 7, 8 }; sink.putByte((byte) 1); sink.putBytes(new byte[] { 2, 3, 4, 5, 6 }); sink.putByte((byte) 7); - sink.putBytes(new byte[] {}); + sink.putBytes(new byte[] { }); sink.putBytes(new byte[] { 8 }); sink.hash(); sink.assertInvariants(8); sink.assertBytes(expected); } - + public void testShort() { Sink sink = new Sink(4); sink.putShort((short) 0x0201); @@ -60,7 +50,7 @@ public class AbstractStreamingHasherTest extends TestCase { sink.assertInvariants(2); sink.assertBytes(new byte[] { 1, 2, 0, 0 }); // padded with zeros } - + public void testInt() { Sink sink = new Sink(4); sink.putInt(0x04030201); @@ -68,7 +58,7 @@ public class AbstractStreamingHasherTest extends TestCase { sink.assertInvariants(4); sink.assertBytes(new byte[] { 1, 2, 3, 4 }); } - + public void testLong() { Sink sink = new Sink(8); sink.putLong(0x0807060504030201L); @@ -76,7 +66,7 @@ public class AbstractStreamingHasherTest extends TestCase { sink.assertInvariants(8); sink.assertBytes(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }); } - + public void testChar() { Sink sink = new Sink(4); sink.putChar((char) 0x0201); @@ -84,22 +74,7 @@ public class AbstractStreamingHasherTest extends TestCase { sink.assertInvariants(2); sink.assertBytes(new byte[] { 1, 2, 0, 0 }); // padded with zeros } - - public void testString() { - Random random = new Random(); - for (int i = 0; i < 100; i++) { - byte[] bytes = new byte[64]; - random.nextBytes(bytes); - String s = new String(bytes, UTF_16LE); // so all random strings are valid - assertEquals( - new Sink(4).putString(s).hash(), - new Sink(4).putBytes(s.getBytes(UTF_16LE)).hash()); - assertEquals( - new Sink(4).putString(s).hash(), - new Sink(4).putString(s, UTF_16LE).hash()); - } - } - + public void testFloat() { Sink sink = new Sink(4); sink.putFloat(Float.intBitsToFloat(0x04030201)); @@ -107,7 +82,7 @@ public class AbstractStreamingHasherTest extends TestCase { sink.assertInvariants(4); sink.assertBytes(new byte[] { 1, 2, 3, 4 }); } - + public void testDouble() { Sink sink = new Sink(8); sink.putDouble(Double.longBitsToDouble(0x0807060504030201L)); @@ -115,7 +90,7 @@ public class AbstractStreamingHasherTest extends TestCase { sink.assertInvariants(8); sink.assertBytes(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }); } - + public void testCorrectExceptions() { Sink sink = new Sink(4); try { @@ -131,16 +106,16 @@ public class AbstractStreamingHasherTest extends TestCase { fail(); } catch (IndexOutOfBoundsException ok) {} } - + /** * This test creates a long random sequence of inputs, then a lot of differently configured * sinks process it; all should produce the same answer, the only difference should be the - * number of process()/processRemaining() invocations, due to alignment. + * number of process()/processRemaining() invocations, due to alignment. */ public void testExhaustive() throws Exception { Random random = new Random(0); // will iteratively make more debuggable, each time it breaks for (int totalInsertions = 0; totalInsertions < 200; totalInsertions++) { - + List<Sink> sinks = Lists.newArrayList(); for (int chunkSize = 4; chunkSize <= 32; chunkSize++) { for (int bufferSize = chunkSize; bufferSize <= chunkSize * 4; bufferSize += chunkSize) { @@ -148,28 +123,22 @@ public class AbstractStreamingHasherTest extends TestCase { sinks.add(new Sink(chunkSize, bufferSize)); // For convenience, testing only with big endianness, to match DataOutputStream. // I regard highly unlikely that both the little endianness tests above and this one - // passes, and there is still a little endianness bug lurking around. + // passes, and there is still a little endianness bug lurking around. } } - + Control control = new Control(); Hasher controlSink = control.newHasher(1024); - - Iterable<Hasher> sinksAndControl = - Iterables.concat(sinks, Collections.singleton(controlSink)); + + Iterable<Hasher> sinksAndControl = Iterables.concat( + sinks, Collections.singleton(controlSink)); for (int insertion = 0; insertion < totalInsertions; insertion++) { - RandomHasherAction.pickAtRandom(random).performAction(random, sinksAndControl); - } - // We need to ensure that at least 4 bytes have been put into the hasher or else - // Hasher#hash will throw an ISE. - int intToPut = random.nextInt(); - for (Hasher hasher : sinksAndControl) { - hasher.putInt(intToPut); + RandomHasherAction.pickAtRandom(random).performAction(random, sinksAndControl); } for (Sink sink : sinks) { sink.hash(); } - + byte[] expected = controlSink.hash().asBytes(); for (Sink sink : sinks) { sink.assertInvariants(expected.length); @@ -177,15 +146,15 @@ public class AbstractStreamingHasherTest extends TestCase { } } } - + private static class Sink extends AbstractStreamingHasher { final int chunkSize; final int bufferSize; final ByteArrayOutputStream out = new ByteArrayOutputStream(); - + int processCalled = 0; boolean remainingCalled = false; - + Sink(int chunkSize, int bufferSize) { super(chunkSize, bufferSize); this.chunkSize = chunkSize; @@ -199,7 +168,7 @@ public class AbstractStreamingHasherTest extends TestCase { } @Override HashCode makeHash() { - return HashCodes.fromBytes(out.toByteArray()); + return HashCodes.fromInt(0xDeadBeef); } @Override protected void process(ByteBuffer bb) { @@ -210,7 +179,7 @@ public class AbstractStreamingHasherTest extends TestCase { out.write(bb.get()); } } - + @Override protected void processRemaining(ByteBuffer bb) { assertFalse(remainingCalled); remainingCalled = true; @@ -223,21 +192,21 @@ public class AbstractStreamingHasherTest extends TestCase { assertEquals(before + 1, after); // default implementation pads and calls process() processCalled--; // don't count the tail invocation (makes tests a bit more understandable) } - + // ensures that the number of invocations looks sane void assertInvariants(int expectedBytes) { - // we should have seen as many bytes as the next multiple of chunk after expectedBytes - 1 + // we should have seen as many bytes as the next multiple of chunk after expectedBytes - 1 assertEquals(out.toByteArray().length, ceilToMultiple(expectedBytes, chunkSize)); assertEquals(expectedBytes / chunkSize, processCalled); assertEquals(expectedBytes % chunkSize != 0, remainingCalled); } - + // returns the minimum x such as x >= a && (x % b) == 0 private static int ceilToMultiple(int a, int b) { int remainder = a % b; return remainder == 0 ? a : a + b - remainder; } - + void assertBytes(byte[] expected) { byte[] got = out.toByteArray(); for (int i = 0; i < expected.length; i++) { @@ -245,14 +214,13 @@ public class AbstractStreamingHasherTest extends TestCase { } } } - - // Assumes that AbstractNonStreamingHashFunction works properly (must be tested elsewhere!) + private static class Control extends AbstractNonStreamingHashFunction { @Override public HashCode hashBytes(byte[] input) { return HashCodes.fromBytes(input); } - + @Override public HashCode hashBytes(byte[] input, int off, int len) { return hashBytes(Arrays.copyOfRange(input, off, off + len)); @@ -277,10 +245,5 @@ public class AbstractStreamingHasherTest extends TestCase { public HashCode hashLong(long input) { throw new UnsupportedOperationException(); } - - @Override - public HashCode hashInt(int input) { - throw new UnsupportedOperationException(); - } } } |