| 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 |