OLD | NEW |
| (Empty) |
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.test; | |
32 import com.google.protobuf.*; | |
33 | |
34 import junit.framework.TestCase; | |
35 | |
36 import java.io.ByteArrayOutputStream; | |
37 import java.io.IOException; | |
38 import java.io.InputStream; | |
39 import java.io.OutputStream; | |
40 import java.io.UnsupportedEncodingException; | |
41 import java.nio.ByteBuffer; | |
42 import java.util.Arrays; | |
43 import java.util.List; | |
44 import java.util.NoSuchElementException; | |
45 | |
46 /** | |
47 * Test {@link LiteralByteString} by setting up a reference string in {@link #se
tUp()}. | |
48 * This class is designed to be extended for testing extensions of {@link Litera
lByteString} | |
49 * such as {@link BoundedByteString}, see {@link BoundedByteStringTest}. | |
50 * | |
51 * @author carlanton@google.com (Carl Haverl) | |
52 */ | |
53 public class LiteralByteStringTest extends TestCase { | |
54 protected static final String UTF_8 = "UTF-8"; | |
55 | |
56 protected String classUnderTest; | |
57 protected byte[] referenceBytes; | |
58 protected ByteString stringUnderTest; | |
59 protected int expectedHashCode; | |
60 | |
61 @Override | |
62 protected void setUp() throws Exception { | |
63 classUnderTest = "LiteralByteString"; | |
64 referenceBytes = ByteStringTest.getTestBytes(1234, 11337766L); | |
65 stringUnderTest = ByteString.copyFrom(referenceBytes); | |
66 expectedHashCode = 331161852; | |
67 } | |
68 | |
69 protected String getActualClassName(Object object) { | |
70 String actualClassName = object.getClass().getName(); | |
71 actualClassName = actualClassName.substring(actualClassName.lastIndexOf('.')
+ 1); | |
72 return actualClassName; | |
73 } | |
74 | |
75 public void testByteAt() { | |
76 boolean stillEqual = true; | |
77 for (int i = 0; stillEqual && i < referenceBytes.length; ++i) { | |
78 stillEqual = (referenceBytes[i] == stringUnderTest.byteAt(i)); | |
79 } | |
80 assertTrue(classUnderTest + " must capture the right bytes", stillEqual); | |
81 } | |
82 | |
83 public void testByteIterator() { | |
84 boolean stillEqual = true; | |
85 ByteString.ByteIterator iter = stringUnderTest.iterator(); | |
86 for (int i = 0; stillEqual && i < referenceBytes.length; ++i) { | |
87 stillEqual = (iter.hasNext() && referenceBytes[i] == iter.nextByte()); | |
88 } | |
89 assertTrue(classUnderTest + " must capture the right bytes", stillEqual); | |
90 assertFalse(classUnderTest + " must have exhausted the itertor", iter.hasNex
t()); | |
91 | |
92 try { | |
93 iter.nextByte(); | |
94 fail("Should have thrown an exception."); | |
95 } catch (NoSuchElementException e) { | |
96 // This is success | |
97 } | |
98 } | |
99 | |
100 public void testByteIterable() { | |
101 boolean stillEqual = true; | |
102 int j = 0; | |
103 for (byte quantum : stringUnderTest) { | |
104 stillEqual = (referenceBytes[j] == quantum); | |
105 ++j; | |
106 } | |
107 assertTrue(classUnderTest + " must capture the right bytes as Bytes", stillE
qual); | |
108 assertEquals(classUnderTest + " iterable character count", referenceBytes.le
ngth, j); | |
109 } | |
110 | |
111 public void testSize() { | |
112 assertEquals(classUnderTest + " must have the expected size", referenceBytes
.length, | |
113 stringUnderTest.size()); | |
114 } | |
115 | |
116 public void testCopyTo_ByteArrayOffsetLength() { | |
117 int destinationOffset = 50; | |
118 int length = 100; | |
119 byte[] destination = new byte[destinationOffset + length]; | |
120 int sourceOffset = 213; | |
121 stringUnderTest.copyTo(destination, sourceOffset, destinationOffset, length)
; | |
122 boolean stillEqual = true; | |
123 for (int i = 0; stillEqual && i < length; ++i) { | |
124 stillEqual = referenceBytes[i + sourceOffset] == destination[i + destinati
onOffset]; | |
125 } | |
126 assertTrue(classUnderTest + ".copyTo(4 arg) must give the expected bytes", s
tillEqual); | |
127 } | |
128 | |
129 public void testCopyTo_ByteArrayOffsetLengthErrors() { | |
130 int destinationOffset = 50; | |
131 int length = 100; | |
132 byte[] destination = new byte[destinationOffset + length]; | |
133 | |
134 try { | |
135 // Copy one too many bytes | |
136 stringUnderTest.copyTo(destination, stringUnderTest.size() + 1 - length, | |
137 destinationOffset, length); | |
138 fail("Should have thrown an exception when copying too many bytes of a " | |
139 + classUnderTest); | |
140 } catch (IndexOutOfBoundsException expected) { | |
141 // This is success | |
142 } | |
143 | |
144 try { | |
145 // Copy with illegal negative sourceOffset | |
146 stringUnderTest.copyTo(destination, -1, destinationOffset, length); | |
147 fail("Should have thrown an exception when given a negative sourceOffset i
n " | |
148 + classUnderTest); | |
149 } catch (IndexOutOfBoundsException expected) { | |
150 // This is success | |
151 } | |
152 | |
153 try { | |
154 // Copy with illegal negative destinationOffset | |
155 stringUnderTest.copyTo(destination, 0, -1, length); | |
156 fail("Should have thrown an exception when given a negative destinationOff
set in " | |
157 + classUnderTest); | |
158 } catch (IndexOutOfBoundsException expected) { | |
159 // This is success | |
160 } | |
161 | |
162 try { | |
163 // Copy with illegal negative size | |
164 stringUnderTest.copyTo(destination, 0, 0, -1); | |
165 fail("Should have thrown an exception when given a negative size in " | |
166 + classUnderTest); | |
167 } catch (IndexOutOfBoundsException expected) { | |
168 // This is success | |
169 } | |
170 | |
171 try { | |
172 // Copy with illegal too-large sourceOffset | |
173 stringUnderTest.copyTo(destination, 2 * stringUnderTest.size(), 0, length)
; | |
174 fail("Should have thrown an exception when the destinationOffset is too la
rge in " | |
175 + classUnderTest); | |
176 } catch (IndexOutOfBoundsException expected) { | |
177 // This is success | |
178 } | |
179 | |
180 try { | |
181 // Copy with illegal too-large destinationOffset | |
182 stringUnderTest.copyTo(destination, 0, 2 * destination.length, length); | |
183 fail("Should have thrown an exception when the destinationOffset is too la
rge in " | |
184 + classUnderTest); | |
185 } catch (IndexOutOfBoundsException expected) { | |
186 // This is success | |
187 } | |
188 } | |
189 | |
190 public void testCopyTo_ByteBuffer() { | |
191 ByteBuffer myBuffer = ByteBuffer.allocate(referenceBytes.length); | |
192 stringUnderTest.copyTo(myBuffer); | |
193 assertTrue(classUnderTest + ".copyTo(ByteBuffer) must give back the same byt
es", | |
194 Arrays.equals(referenceBytes, myBuffer.array())); | |
195 } | |
196 | |
197 public void testAsReadOnlyByteBuffer() { | |
198 ByteBuffer byteBuffer = stringUnderTest.asReadOnlyByteBuffer(); | |
199 byte[] roundTripBytes = new byte[referenceBytes.length]; | |
200 assertTrue(byteBuffer.remaining() == referenceBytes.length); | |
201 assertTrue(byteBuffer.isReadOnly()); | |
202 byteBuffer.get(roundTripBytes); | |
203 assertTrue(classUnderTest + ".asReadOnlyByteBuffer() must give back the same
bytes", | |
204 Arrays.equals(referenceBytes, roundTripBytes)); | |
205 } | |
206 | |
207 public void testAsReadOnlyByteBufferList() { | |
208 List<ByteBuffer> byteBuffers = stringUnderTest.asReadOnlyByteBufferList(); | |
209 int bytesSeen = 0; | |
210 byte[] roundTripBytes = new byte[referenceBytes.length]; | |
211 for (ByteBuffer byteBuffer : byteBuffers) { | |
212 int thisLength = byteBuffer.remaining(); | |
213 assertTrue(byteBuffer.isReadOnly()); | |
214 assertTrue(bytesSeen + thisLength <= referenceBytes.length); | |
215 byteBuffer.get(roundTripBytes, bytesSeen, thisLength); | |
216 bytesSeen += thisLength; | |
217 } | |
218 assertTrue(bytesSeen == referenceBytes.length); | |
219 assertTrue(classUnderTest + ".asReadOnlyByteBufferTest() must give back the
same bytes", | |
220 Arrays.equals(referenceBytes, roundTripBytes)); | |
221 } | |
222 | |
223 public void testToByteArray() { | |
224 byte[] roundTripBytes = stringUnderTest.toByteArray(); | |
225 assertTrue(classUnderTest + ".toByteArray() must give back the same bytes", | |
226 Arrays.equals(referenceBytes, roundTripBytes)); | |
227 } | |
228 | |
229 public void testWriteTo() throws IOException { | |
230 ByteArrayOutputStream bos = new ByteArrayOutputStream(); | |
231 stringUnderTest.writeTo(bos); | |
232 byte[] roundTripBytes = bos.toByteArray(); | |
233 assertTrue(classUnderTest + ".writeTo() must give back the same bytes", | |
234 Arrays.equals(referenceBytes, roundTripBytes)); | |
235 } | |
236 | |
237 public void testWriteTo_mutating() throws IOException { | |
238 OutputStream os = new OutputStream() { | |
239 @Override | |
240 public void write(byte[] b, int off, int len) { | |
241 for (int x = 0; x < len; ++x) { | |
242 b[off + x] = (byte) 0; | |
243 } | |
244 } | |
245 | |
246 @Override | |
247 public void write(int b) { | |
248 // Purposefully left blank. | |
249 } | |
250 }; | |
251 | |
252 stringUnderTest.writeTo(os); | |
253 byte[] newBytes = stringUnderTest.toByteArray(); | |
254 assertTrue(classUnderTest + ".writeTo() must not grant access to underlying
array", | |
255 Arrays.equals(referenceBytes, newBytes)); | |
256 } | |
257 | |
258 public void testNewOutput() throws IOException { | |
259 ByteArrayOutputStream bos = new ByteArrayOutputStream(); | |
260 ByteString.Output output = ByteString.newOutput(); | |
261 stringUnderTest.writeTo(output); | |
262 assertEquals("Output Size returns correct result", | |
263 output.size(), stringUnderTest.size()); | |
264 output.writeTo(bos); | |
265 assertTrue("Output.writeTo() must give back the same bytes", | |
266 Arrays.equals(referenceBytes, bos.toByteArray())); | |
267 | |
268 // write the output stream to itself! This should cause it to double | |
269 output.writeTo(output); | |
270 assertEquals("Writing an output stream to itself is successful", | |
271 stringUnderTest.concat(stringUnderTest), output.toByteString()); | |
272 | |
273 output.reset(); | |
274 assertEquals("Output.reset() resets the output", 0, output.size()); | |
275 assertEquals("Output.reset() resets the output", | |
276 ByteString.EMPTY, output.toByteString()); | |
277 | |
278 } | |
279 | |
280 public void testHashCode() { | |
281 int hash = stringUnderTest.hashCode(); | |
282 assertEquals(classUnderTest + " must have expected hashCode", expectedHashCo
de, hash); | |
283 } | |
284 | |
285 public void testNewInput() throws IOException { | |
286 InputStream input = stringUnderTest.newInput(); | |
287 assertEquals("InputStream.available() returns correct value", | |
288 stringUnderTest.size(), input.available()); | |
289 boolean stillEqual = true; | |
290 for (byte referenceByte : referenceBytes) { | |
291 int expectedInt = (referenceByte & 0xFF); | |
292 stillEqual = (expectedInt == input.read()); | |
293 } | |
294 assertEquals("InputStream.available() returns correct value", | |
295 0, input.available()); | |
296 assertTrue(classUnderTest + " must give the same bytes from the InputStream"
, stillEqual); | |
297 assertEquals(classUnderTest + " InputStream must now be exhausted", -1, inpu
t.read()); | |
298 } | |
299 | |
300 public void testNewInput_skip() throws IOException { | |
301 InputStream input = stringUnderTest.newInput(); | |
302 int stringSize = stringUnderTest.size(); | |
303 int nearEndIndex = stringSize * 2 / 3; | |
304 long skipped1 = input.skip(nearEndIndex); | |
305 assertEquals("InputStream.skip()", skipped1, nearEndIndex); | |
306 assertEquals("InputStream.available()", | |
307 stringSize - skipped1, input.available()); | |
308 assertTrue("InputStream.mark() is available", input.markSupported()); | |
309 input.mark(0); | |
310 assertEquals("InputStream.skip(), read()", | |
311 stringUnderTest.byteAt(nearEndIndex) & 0xFF, input.read()); | |
312 assertEquals("InputStream.available()", | |
313 stringSize - skipped1 - 1, input.available()); | |
314 long skipped2 = input.skip(stringSize); | |
315 assertEquals("InputStream.skip() incomplete", | |
316 skipped2, stringSize - skipped1 - 1); | |
317 assertEquals("InputStream.skip(), no more input", 0, input.available()); | |
318 assertEquals("InputStream.skip(), no more input", -1, input.read()); | |
319 input.reset(); | |
320 assertEquals("InputStream.reset() succeded", | |
321 stringSize - skipped1, input.available()); | |
322 assertEquals("InputStream.reset(), read()", | |
323 stringUnderTest.byteAt(nearEndIndex) & 0xFF, input.read()); | |
324 } | |
325 | |
326 public void testNewCodedInput() throws IOException { | |
327 CodedInputStream cis = stringUnderTest.newCodedInput(); | |
328 byte[] roundTripBytes = cis.readRawBytes(referenceBytes.length); | |
329 assertTrue(classUnderTest + " must give the same bytes back from the CodedIn
putStream", | |
330 Arrays.equals(referenceBytes, roundTripBytes)); | |
331 assertTrue(classUnderTest + " CodedInputStream must now be exhausted", cis.i
sAtEnd()); | |
332 } | |
333 | |
334 /** | |
335 * Make sure we keep things simple when concatenating with empty. See also | |
336 * {@link ByteStringTest#testConcat_empty()}. | |
337 */ | |
338 public void testConcat_empty() { | |
339 assertSame(classUnderTest + " concatenated with empty must give " + classUnd
erTest, | |
340 stringUnderTest.concat(ByteString.EMPTY), stringUnderTest); | |
341 assertSame("empty concatenated with " + classUnderTest + " must give " + cla
ssUnderTest, | |
342 ByteString.EMPTY.concat(stringUnderTest), stringUnderTest); | |
343 } | |
344 } | |
OLD | NEW |