1/*
2 * Copyright (C) 2011 The Guava Authors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.google.common.hash;
18
19import static org.mockito.Mockito.inOrder;
20import static org.mockito.Mockito.mock;
21import static org.mockito.Mockito.verify;
22
23import com.google.common.base.Charsets;
24import com.google.common.hash.AbstractStreamingHashFunction.AbstractStreamingHasher;
25import com.google.common.testing.EqualsTester;
26import com.google.common.testing.SerializableTester;
27
28import junit.framework.TestCase;
29
30import org.mockito.InOrder;
31
32import java.io.OutputStream;
33import java.nio.ByteBuffer;
34import java.nio.charset.Charset;
35import java.util.Arrays;
36
37/**
38 * Tests for HashExtractors.
39 *
40 * @author Dimitris Andreou
41 */
42public class FunnelsTest extends TestCase {
43  public void testForBytes() {
44    PrimitiveSink primitiveSink = mock(PrimitiveSink.class);
45    Funnels.byteArrayFunnel().funnel(new byte[] { 4, 3, 2, 1 }, primitiveSink);
46    verify(primitiveSink).putBytes(new byte[] { 4, 3, 2, 1 });
47  }
48
49  public void testForBytes_null() {
50    assertNullsThrowException(Funnels.byteArrayFunnel());
51  }
52
53  public void testForStrings() {
54    PrimitiveSink primitiveSink = mock(PrimitiveSink.class);
55    Funnels.unencodedCharsFunnel().funnel("test", primitiveSink);
56    verify(primitiveSink).putUnencodedChars("test");
57  }
58
59  public void testForStrings_null() {
60    assertNullsThrowException(Funnels.unencodedCharsFunnel());
61  }
62
63  public void testForStringsCharset() {
64    for (Charset charset : Charset.availableCharsets().values()) {
65      PrimitiveSink primitiveSink = mock(PrimitiveSink.class);
66      Funnels.stringFunnel(charset).funnel("test", primitiveSink);
67      verify(primitiveSink).putString("test", charset);
68    }
69  }
70
71  public void testForStringsCharset_null() {
72    for (Charset charset : Charset.availableCharsets().values()) {
73      assertNullsThrowException(Funnels.stringFunnel(charset));
74    }
75  }
76
77  public void testForInts() {
78    Integer value = 1234;
79    PrimitiveSink primitiveSink = mock(PrimitiveSink.class);
80    Funnels.integerFunnel().funnel(value, primitiveSink);
81    verify(primitiveSink).putInt(1234);
82  }
83
84  public void testForInts_null() {
85    assertNullsThrowException(Funnels.integerFunnel());
86  }
87
88  public void testForLongs() {
89    Long value = 1234L;
90    PrimitiveSink primitiveSink = mock(PrimitiveSink.class);
91    Funnels.longFunnel().funnel(value, primitiveSink);
92    verify(primitiveSink).putLong(1234);
93  }
94
95  public void testForLongs_null() {
96    assertNullsThrowException(Funnels.longFunnel());
97  }
98
99  public void testSequential() {
100    @SuppressWarnings("unchecked")
101    Funnel<Object> elementFunnel = mock(Funnel.class);
102    PrimitiveSink primitiveSink = mock(PrimitiveSink.class);
103    Funnel<Iterable<? extends Object>> sequential = Funnels.sequentialFunnel(elementFunnel);
104    sequential.funnel(Arrays.asList("foo", "bar", "baz", "quux"), primitiveSink);
105    InOrder inOrder = inOrder(elementFunnel);
106    inOrder.verify(elementFunnel).funnel("foo", primitiveSink);
107    inOrder.verify(elementFunnel).funnel("bar", primitiveSink);
108    inOrder.verify(elementFunnel).funnel("baz", primitiveSink);
109    inOrder.verify(elementFunnel).funnel("quux", primitiveSink);
110  }
111
112  private static void assertNullsThrowException(Funnel<?> funnel) {
113    PrimitiveSink primitiveSink = new AbstractStreamingHasher(4, 4) {
114      @Override HashCode makeHash() { throw new UnsupportedOperationException(); }
115
116      @Override protected void process(ByteBuffer bb) {
117        while (bb.hasRemaining()) {
118          bb.get();
119        }
120      }
121    };
122    try {
123      funnel.funnel(null, primitiveSink);
124      fail();
125    } catch (NullPointerException ok) {}
126  }
127
128  public void testAsOutputStream() throws Exception {
129    PrimitiveSink sink = mock(PrimitiveSink.class);
130    OutputStream out = Funnels.asOutputStream(sink);
131    byte[] bytes = { 1, 2, 3, 4 };
132    out.write(255);
133    out.write(bytes);
134    out.write(bytes, 1, 2);
135    verify(sink).putByte((byte) 255);
136    verify(sink).putBytes(bytes);
137    verify(sink).putBytes(bytes, 1, 2);
138  }
139
140  public void testSerialization() {
141    assertSame(
142        Funnels.byteArrayFunnel(),
143        SerializableTester.reserialize(Funnels.byteArrayFunnel()));
144    assertSame(
145        Funnels.integerFunnel(),
146        SerializableTester.reserialize(Funnels.integerFunnel()));
147    assertSame(
148        Funnels.longFunnel(),
149        SerializableTester.reserialize(Funnels.longFunnel()));
150    assertSame(
151        Funnels.unencodedCharsFunnel(),
152        SerializableTester.reserialize(Funnels.unencodedCharsFunnel()));
153    assertEquals(
154        Funnels.sequentialFunnel(Funnels.integerFunnel()),
155        SerializableTester.reserialize(Funnels.sequentialFunnel(Funnels.integerFunnel())));
156    assertEquals(
157        Funnels.stringFunnel(Charsets.US_ASCII),
158        SerializableTester.reserialize(Funnels.stringFunnel(Charsets.US_ASCII)));
159  }
160
161  public void testEquals() {
162     new EqualsTester()
163       .addEqualityGroup(Funnels.byteArrayFunnel())
164       .addEqualityGroup(Funnels.integerFunnel())
165       .addEqualityGroup(Funnels.longFunnel())
166       .addEqualityGroup(Funnels.unencodedCharsFunnel())
167       .addEqualityGroup(Funnels.stringFunnel(Charsets.UTF_8))
168       .addEqualityGroup(Funnels.stringFunnel(Charsets.US_ASCII))
169       .addEqualityGroup(Funnels.sequentialFunnel(Funnels.integerFunnel()),
170           SerializableTester.reserialize(Funnels.sequentialFunnel(
171               Funnels.integerFunnel())))
172       .addEqualityGroup(Funnels.sequentialFunnel(Funnels.longFunnel()))
173       .testEquals();
174  }
175}
176