- add sources.
[platform/framework/web/crosswalk.git] / src / third_party / protobuf / java / src / test / java / com / google / protobuf / LiteralByteStringTest.java
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // http://code.google.com/p/protobuf/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 //     * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 //     * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 package com.google.protobuf;
32
33 import junit.framework.TestCase;
34
35 import java.io.ByteArrayOutputStream;
36 import java.io.IOException;
37 import java.io.InputStream;
38 import java.io.OutputStream;
39 import java.io.UnsupportedEncodingException;
40 import java.nio.ByteBuffer;
41 import java.util.Arrays;
42 import java.util.List;
43 import java.util.NoSuchElementException;
44
45 /**
46  * Test {@link LiteralByteString} by setting up a reference string in {@link #setUp()}.
47  * This class is designed to be extended for testing extensions of {@link LiteralByteString}
48  * such as {@link BoundedByteString}, see {@link BoundedByteStringTest}.
49  *
50  * @author carlanton@google.com (Carl Haverl)
51  */
52 public class LiteralByteStringTest extends TestCase {
53   protected static final String UTF_8 = "UTF-8";
54
55   protected String classUnderTest;
56   protected byte[] referenceBytes;
57   protected ByteString stringUnderTest;
58   protected int expectedHashCode;
59
60   @Override
61   protected void setUp() throws Exception {
62     classUnderTest = "LiteralByteString";
63     referenceBytes = ByteStringTest.getTestBytes(1234, 11337766L);
64     stringUnderTest = ByteString.copyFrom(referenceBytes);
65     expectedHashCode = 331161852;
66   }
67
68   public void testExpectedType() {
69     String actualClassName = getActualClassName(stringUnderTest);
70     assertEquals(classUnderTest + " should match type exactly", classUnderTest, actualClassName);
71   }
72
73   protected String getActualClassName(Object object) {
74     String actualClassName = object.getClass().getName();
75     actualClassName = actualClassName.substring(actualClassName.lastIndexOf('.') + 1);
76     return actualClassName;
77   }
78
79   public void testByteAt() {
80     boolean stillEqual = true;
81     for (int i = 0; stillEqual && i < referenceBytes.length; ++i) {
82       stillEqual = (referenceBytes[i] == stringUnderTest.byteAt(i));
83     }
84     assertTrue(classUnderTest + " must capture the right bytes", stillEqual);
85   }
86
87   public void testByteIterator() {
88     boolean stillEqual = true;
89     ByteString.ByteIterator iter = stringUnderTest.iterator();
90     for (int i = 0; stillEqual && i < referenceBytes.length; ++i) {
91       stillEqual = (iter.hasNext() && referenceBytes[i] == iter.nextByte());
92     }
93     assertTrue(classUnderTest + " must capture the right bytes", stillEqual);
94     assertFalse(classUnderTest + " must have exhausted the itertor", iter.hasNext());
95
96     try {
97       iter.nextByte();
98       fail("Should have thrown an exception.");
99     } catch (NoSuchElementException e) {
100       // This is success
101     }
102   }
103
104   public void testByteIterable() {
105     boolean stillEqual = true;
106     int j = 0;
107     for (byte quantum : stringUnderTest) {
108       stillEqual = (referenceBytes[j] == quantum);
109       ++j;
110     }
111     assertTrue(classUnderTest + " must capture the right bytes as Bytes", stillEqual);
112     assertEquals(classUnderTest + " iterable character count", referenceBytes.length, j);
113   }
114
115   public void testSize() {
116     assertEquals(classUnderTest + " must have the expected size", referenceBytes.length,
117         stringUnderTest.size());
118   }
119
120   public void testGetTreeDepth() {
121     assertEquals(classUnderTest + " must have depth 0", 0, stringUnderTest.getTreeDepth());
122   }
123
124   public void testIsBalanced() {
125     assertTrue(classUnderTest + " is technically balanced", stringUnderTest.isBalanced());
126   }
127
128   public void testCopyTo_ByteArrayOffsetLength() {
129     int destinationOffset = 50;
130     int length = 100;
131     byte[] destination = new byte[destinationOffset + length];
132     int sourceOffset = 213;
133     stringUnderTest.copyTo(destination, sourceOffset, destinationOffset, length);
134     boolean stillEqual = true;
135     for (int i = 0; stillEqual && i < length; ++i) {
136       stillEqual = referenceBytes[i + sourceOffset] == destination[i + destinationOffset];
137     }
138     assertTrue(classUnderTest + ".copyTo(4 arg) must give the expected bytes", stillEqual);
139   }
140
141   public void testCopyTo_ByteArrayOffsetLengthErrors() {
142     int destinationOffset = 50;
143     int length = 100;
144     byte[] destination = new byte[destinationOffset + length];
145
146     try {
147       // Copy one too many bytes
148       stringUnderTest.copyTo(destination, stringUnderTest.size() + 1 - length,
149           destinationOffset, length);
150       fail("Should have thrown an exception when copying too many bytes of a "
151           + classUnderTest);
152     } catch (IndexOutOfBoundsException expected) {
153       // This is success
154     }
155
156     try {
157       // Copy with illegal negative sourceOffset
158       stringUnderTest.copyTo(destination, -1, destinationOffset, length);
159       fail("Should have thrown an exception when given a negative sourceOffset in "
160           + classUnderTest);
161     } catch (IndexOutOfBoundsException expected) {
162       // This is success
163     }
164
165     try {
166       // Copy with illegal negative destinationOffset
167       stringUnderTest.copyTo(destination, 0, -1, length);
168       fail("Should have thrown an exception when given a negative destinationOffset in "
169           + classUnderTest);
170     } catch (IndexOutOfBoundsException expected) {
171       // This is success
172     }
173
174     try {
175       // Copy with illegal negative size
176       stringUnderTest.copyTo(destination, 0, 0, -1);
177       fail("Should have thrown an exception when given a negative size in "
178           + classUnderTest);
179     } catch (IndexOutOfBoundsException expected) {
180       // This is success
181     }
182
183     try {
184       // Copy with illegal too-large sourceOffset
185       stringUnderTest.copyTo(destination, 2 * stringUnderTest.size(), 0, length);
186       fail("Should have thrown an exception when the destinationOffset is too large in "
187           + classUnderTest);
188     } catch (IndexOutOfBoundsException expected) {
189       // This is success
190     }
191
192     try {
193       // Copy with illegal too-large destinationOffset
194       stringUnderTest.copyTo(destination, 0, 2 * destination.length, length);
195       fail("Should have thrown an exception when the destinationOffset is too large in "
196           + classUnderTest);
197     } catch (IndexOutOfBoundsException expected) {
198       // This is success
199     }
200   }
201
202   public void testCopyTo_ByteBuffer() {
203     ByteBuffer myBuffer = ByteBuffer.allocate(referenceBytes.length);
204     stringUnderTest.copyTo(myBuffer);
205     assertTrue(classUnderTest + ".copyTo(ByteBuffer) must give back the same bytes",
206         Arrays.equals(referenceBytes, myBuffer.array()));
207   }
208
209   public void testAsReadOnlyByteBuffer() {
210     ByteBuffer byteBuffer = stringUnderTest.asReadOnlyByteBuffer();
211     byte[] roundTripBytes = new byte[referenceBytes.length];
212     assertTrue(byteBuffer.remaining() == referenceBytes.length);
213     assertTrue(byteBuffer.isReadOnly());
214     byteBuffer.get(roundTripBytes);
215     assertTrue(classUnderTest + ".asReadOnlyByteBuffer() must give back the same bytes",
216         Arrays.equals(referenceBytes, roundTripBytes));
217   }
218
219   public void testAsReadOnlyByteBufferList() {
220     List<ByteBuffer> byteBuffers = stringUnderTest.asReadOnlyByteBufferList();
221     int bytesSeen = 0;
222     byte[] roundTripBytes = new byte[referenceBytes.length];
223     for (ByteBuffer byteBuffer : byteBuffers) {
224       int thisLength = byteBuffer.remaining();
225       assertTrue(byteBuffer.isReadOnly());
226       assertTrue(bytesSeen + thisLength <= referenceBytes.length);
227       byteBuffer.get(roundTripBytes, bytesSeen, thisLength);
228       bytesSeen += thisLength;
229     }
230     assertTrue(bytesSeen == referenceBytes.length);
231     assertTrue(classUnderTest + ".asReadOnlyByteBufferTest() must give back the same bytes",
232         Arrays.equals(referenceBytes, roundTripBytes));
233   }
234
235   public void testToByteArray() {
236     byte[] roundTripBytes = stringUnderTest.toByteArray();
237     assertTrue(classUnderTest + ".toByteArray() must give back the same bytes",
238         Arrays.equals(referenceBytes, roundTripBytes));
239   }
240
241   public void testWriteTo() throws IOException {
242     ByteArrayOutputStream bos = new ByteArrayOutputStream();
243     stringUnderTest.writeTo(bos);
244     byte[] roundTripBytes = bos.toByteArray();
245     assertTrue(classUnderTest + ".writeTo() must give back the same bytes",
246         Arrays.equals(referenceBytes, roundTripBytes));
247   }
248   
249   public void testWriteTo_mutating() throws IOException {
250     OutputStream os = new OutputStream() {
251       @Override
252       public void write(byte[] b, int off, int len) {
253         for (int x = 0; x < len; ++x) {
254           b[off + x] = (byte) 0;
255         }
256       }
257
258       @Override
259       public void write(int b) {
260         // Purposefully left blank.
261       }
262     };
263
264     stringUnderTest.writeTo(os);
265     byte[] newBytes = stringUnderTest.toByteArray();
266     assertTrue(classUnderTest + ".writeTo() must not grant access to underlying array",
267         Arrays.equals(referenceBytes, newBytes));
268   }
269
270   public void testNewOutput() throws IOException {
271     ByteArrayOutputStream bos = new ByteArrayOutputStream();
272     ByteString.Output output = ByteString.newOutput();
273     stringUnderTest.writeTo(output);
274     assertEquals("Output Size returns correct result",
275         output.size(), stringUnderTest.size());
276     output.writeTo(bos);
277     assertTrue("Output.writeTo() must give back the same bytes",
278         Arrays.equals(referenceBytes, bos.toByteArray()));
279
280     // write the output stream to itself! This should cause it to double
281     output.writeTo(output);
282     assertEquals("Writing an output stream to itself is successful",
283         stringUnderTest.concat(stringUnderTest), output.toByteString());
284
285     output.reset();
286     assertEquals("Output.reset() resets the output", 0, output.size());
287     assertEquals("Output.reset() resets the output",
288         ByteString.EMPTY, output.toByteString());
289     
290   }
291
292   public void testToString() throws UnsupportedEncodingException {
293     String testString = "I love unicode \u1234\u5678 characters";
294     LiteralByteString unicode = new LiteralByteString(testString.getBytes(UTF_8));
295     String roundTripString = unicode.toString(UTF_8);
296     assertEquals(classUnderTest + " unicode must match", testString, roundTripString);
297   }
298
299   public void testEquals() {
300     assertEquals(classUnderTest + " must not equal null", false, stringUnderTest.equals(null));
301     assertEquals(classUnderTest + " must equal self", stringUnderTest, stringUnderTest);
302     assertFalse(classUnderTest + " must not equal the empty string",
303         stringUnderTest.equals(ByteString.EMPTY));
304     assertEquals(classUnderTest + " empty strings must be equal",
305         new LiteralByteString(new byte[]{}), stringUnderTest.substring(55, 55));
306     assertEquals(classUnderTest + " must equal another string with the same value",
307         stringUnderTest, new LiteralByteString(referenceBytes));
308
309     byte[] mungedBytes = new byte[referenceBytes.length];
310     System.arraycopy(referenceBytes, 0, mungedBytes, 0, referenceBytes.length);
311     mungedBytes[mungedBytes.length - 5] ^= 0xFF;
312     assertFalse(classUnderTest + " must not equal every string with the same length",
313         stringUnderTest.equals(new LiteralByteString(mungedBytes)));
314   }
315
316   public void testHashCode() {
317     int hash = stringUnderTest.hashCode();
318     assertEquals(classUnderTest + " must have expected hashCode", expectedHashCode, hash);
319   }
320
321   public void testPeekCachedHashCode() {
322     assertEquals(classUnderTest + ".peekCachedHashCode() should return zero at first", 0,
323         stringUnderTest.peekCachedHashCode());
324     stringUnderTest.hashCode();
325     assertEquals(classUnderTest + ".peekCachedHashCode should return zero at first",
326         expectedHashCode, stringUnderTest.peekCachedHashCode());
327   }
328
329   public void testPartialHash() {
330     // partialHash() is more strenuously tested elsewhere by testing hashes of substrings.
331     // This test would fail if the expected hash were 1.  It's not.
332     int hash = stringUnderTest.partialHash(stringUnderTest.size(), 0, stringUnderTest.size());
333     assertEquals(classUnderTest + ".partialHash() must yield expected hashCode",
334         expectedHashCode, hash);
335   }
336
337   public void testNewInput() throws IOException {
338     InputStream input = stringUnderTest.newInput();
339     assertEquals("InputStream.available() returns correct value",
340         stringUnderTest.size(), input.available());
341     boolean stillEqual = true;
342     for (byte referenceByte : referenceBytes) {
343       int expectedInt = (referenceByte & 0xFF);
344       stillEqual = (expectedInt == input.read());
345     }
346     assertEquals("InputStream.available() returns correct value",
347         0, input.available());
348     assertTrue(classUnderTest + " must give the same bytes from the InputStream", stillEqual);
349     assertEquals(classUnderTest + " InputStream must now be exhausted", -1, input.read());
350   }
351
352   public void testNewInput_skip() throws IOException {
353     InputStream input = stringUnderTest.newInput();
354     int stringSize = stringUnderTest.size();
355     int nearEndIndex = stringSize * 2 / 3;
356     long skipped1 = input.skip(nearEndIndex);
357     assertEquals("InputStream.skip()", skipped1, nearEndIndex);
358     assertEquals("InputStream.available()",
359         stringSize - skipped1, input.available());
360     assertTrue("InputStream.mark() is available", input.markSupported());
361     input.mark(0);
362     assertEquals("InputStream.skip(), read()",
363         stringUnderTest.byteAt(nearEndIndex) & 0xFF, input.read());
364     assertEquals("InputStream.available()",
365                  stringSize - skipped1 - 1, input.available());
366     long skipped2 = input.skip(stringSize);
367     assertEquals("InputStream.skip() incomplete",
368         skipped2, stringSize - skipped1 - 1);
369     assertEquals("InputStream.skip(), no more input", 0, input.available());
370     assertEquals("InputStream.skip(), no more input", -1, input.read());
371     input.reset();
372     assertEquals("InputStream.reset() succeded",
373                  stringSize - skipped1, input.available());
374     assertEquals("InputStream.reset(), read()",
375         stringUnderTest.byteAt(nearEndIndex) & 0xFF, input.read());
376   }
377
378   public void testNewCodedInput() throws IOException {
379     CodedInputStream cis = stringUnderTest.newCodedInput();
380     byte[] roundTripBytes = cis.readRawBytes(referenceBytes.length);
381     assertTrue(classUnderTest + " must give the same bytes back from the CodedInputStream",
382         Arrays.equals(referenceBytes, roundTripBytes));
383     assertTrue(classUnderTest + " CodedInputStream must now be exhausted", cis.isAtEnd());
384   }
385
386   /**
387    * Make sure we keep things simple when concatenating with empty. See also
388    * {@link ByteStringTest#testConcat_empty()}.
389    */
390   public void testConcat_empty() {
391     assertSame(classUnderTest + " concatenated with empty must give " + classUnderTest,
392         stringUnderTest.concat(ByteString.EMPTY), stringUnderTest);
393     assertSame("empty concatenated with " + classUnderTest + " must give " + classUnderTest,
394         ByteString.EMPTY.concat(stringUnderTest), stringUnderTest);
395   }
396 }