1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // https://developers.google.com/protocol-buffers/ 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 static java.util.Arrays.asList; 34 35 import junit.framework.TestCase; 36 37 import java.util.ArrayList; 38 import java.util.ConcurrentModificationException; 39 import java.util.Iterator; 40 import java.util.List; 41 42 /** 43 * Tests for {@link LazyStringArrayList}. 44 * 45 * @author jonp@google.com (Jon Perlow) 46 */ 47 public class LazyStringArrayListTest extends TestCase { 48 49 private static String STRING_A = "A"; 50 private static String STRING_B = "B"; 51 private static String STRING_C = "C"; 52 53 private static ByteString BYTE_STRING_A = ByteString.copyFromUtf8("A"); 54 private static ByteString BYTE_STRING_B = ByteString.copyFromUtf8("B"); 55 private static ByteString BYTE_STRING_C = ByteString.copyFromUtf8("C"); 56 testJustStrings()57 public void testJustStrings() { 58 LazyStringArrayList list = new LazyStringArrayList(); 59 list.add(STRING_A); 60 list.add(STRING_B); 61 list.add(STRING_C); 62 63 assertEquals(3, list.size()); 64 assertSame(STRING_A, list.get(0)); 65 assertSame(STRING_B, list.get(1)); 66 assertSame(STRING_C, list.get(2)); 67 68 list.set(1, STRING_C); 69 assertSame(STRING_C, list.get(1)); 70 71 list.remove(1); 72 assertSame(STRING_A, list.get(0)); 73 assertSame(STRING_C, list.get(1)); 74 75 List<ByteString> byteStringList = list.asByteStringList(); 76 assertEquals(BYTE_STRING_A, byteStringList.get(0)); 77 assertEquals(BYTE_STRING_C, byteStringList.get(1)); 78 79 // Underlying list should be transformed. 80 assertSame(byteStringList.get(0), list.getByteString(0)); 81 assertSame(byteStringList.get(1), list.getByteString(1)); 82 } 83 testJustByteString()84 public void testJustByteString() { 85 LazyStringArrayList list = new LazyStringArrayList(); 86 list.add(BYTE_STRING_A); 87 list.add(BYTE_STRING_B); 88 list.add(BYTE_STRING_C); 89 90 assertEquals(3, list.size()); 91 assertSame(BYTE_STRING_A, list.getByteString(0)); 92 assertSame(BYTE_STRING_B, list.getByteString(1)); 93 assertSame(BYTE_STRING_C, list.getByteString(2)); 94 95 list.remove(1); 96 assertSame(BYTE_STRING_A, list.getByteString(0)); 97 assertSame(BYTE_STRING_C, list.getByteString(1)); 98 99 List<ByteString> byteStringList = list.asByteStringList(); 100 assertSame(BYTE_STRING_A, byteStringList.get(0)); 101 assertSame(BYTE_STRING_C, byteStringList.get(1)); 102 } 103 testConversionBackAndForth()104 public void testConversionBackAndForth() { 105 LazyStringArrayList list = new LazyStringArrayList(); 106 list.add(STRING_A); 107 list.add(BYTE_STRING_B); 108 list.add(BYTE_STRING_C); 109 110 // String a should be the same because it was originally a string 111 assertSame(STRING_A, list.get(0)); 112 113 // String b and c should be different because the string has to be computed 114 // from the ByteString 115 String bPrime = list.get(1); 116 assertNotSame(STRING_B, bPrime); 117 assertEquals(STRING_B, bPrime); 118 String cPrime = list.get(2); 119 assertNotSame(STRING_C, cPrime); 120 assertEquals(STRING_C, cPrime); 121 122 // String c and c should stay the same once cached. 123 assertSame(bPrime, list.get(1)); 124 assertSame(cPrime, list.get(2)); 125 126 // ByteString needs to be computed from string for both a and b 127 ByteString aPrimeByteString = list.getByteString(0); 128 assertEquals(BYTE_STRING_A, aPrimeByteString); 129 ByteString bPrimeByteString = list.getByteString(1); 130 assertNotSame(BYTE_STRING_B, bPrimeByteString); 131 assertEquals(BYTE_STRING_B, list.getByteString(1)); 132 133 // Once cached, ByteString should stay cached. 134 assertSame(aPrimeByteString, list.getByteString(0)); 135 assertSame(bPrimeByteString, list.getByteString(1)); 136 } 137 testCopyConstructorCopiesByReference()138 public void testCopyConstructorCopiesByReference() { 139 LazyStringArrayList list1 = new LazyStringArrayList(); 140 list1.add(STRING_A); 141 list1.add(BYTE_STRING_B); 142 list1.add(BYTE_STRING_C); 143 144 LazyStringArrayList list2 = new LazyStringArrayList(list1); 145 assertEquals(3, list2.size()); 146 assertSame(STRING_A, list2.get(0)); 147 assertSame(BYTE_STRING_B, list2.getByteString(1)); 148 assertSame(BYTE_STRING_C, list2.getByteString(2)); 149 } 150 testListCopyConstructor()151 public void testListCopyConstructor() { 152 List<String> list1 = new ArrayList<String>(); 153 list1.add(STRING_A); 154 list1.add(STRING_B); 155 list1.add(STRING_C); 156 157 LazyStringArrayList list2 = new LazyStringArrayList(list1); 158 assertEquals(3, list2.size()); 159 assertSame(STRING_A, list2.get(0)); 160 assertSame(STRING_B, list2.get(1)); 161 assertSame(STRING_C, list2.get(2)); 162 } 163 testAddAllCopiesByReferenceIfPossible()164 public void testAddAllCopiesByReferenceIfPossible() { 165 LazyStringArrayList list1 = new LazyStringArrayList(); 166 list1.add(STRING_A); 167 list1.add(BYTE_STRING_B); 168 list1.add(BYTE_STRING_C); 169 170 LazyStringArrayList list2 = new LazyStringArrayList(); 171 list2.addAll(list1); 172 173 assertEquals(3, list2.size()); 174 assertSame(STRING_A, list2.get(0)); 175 assertSame(BYTE_STRING_B, list2.getByteString(1)); 176 assertSame(BYTE_STRING_C, list2.getByteString(2)); 177 } 178 testModificationWithIteration()179 public void testModificationWithIteration() { 180 LazyStringArrayList list = new LazyStringArrayList(); 181 list.addAll(asList(STRING_A, STRING_B, STRING_C)); 182 Iterator<String> iterator = list.iterator(); 183 assertEquals(3, list.size()); 184 assertEquals(STRING_A, list.get(0)); 185 assertEquals(STRING_A, iterator.next()); 186 187 // Does not structurally modify. 188 iterator = list.iterator(); 189 list.set(0, STRING_B); 190 iterator.next(); 191 192 list.remove(0); 193 try { 194 iterator.next(); 195 fail(); 196 } catch (ConcurrentModificationException e) { 197 // expected 198 } 199 200 iterator = list.iterator(); 201 list.add(0, STRING_C); 202 try { 203 iterator.next(); 204 fail(); 205 } catch (ConcurrentModificationException e) { 206 // expected 207 } 208 } 209 testMakeImmutable()210 public void testMakeImmutable() { 211 LazyStringArrayList list = new LazyStringArrayList(); 212 list.add(STRING_A); 213 list.add(STRING_B); 214 list.add(STRING_C); 215 list.makeImmutable(); 216 assertGenericListImmutable(list, STRING_A); 217 218 // LazyStringArrayList has extra methods not covered in the generic 219 // assertion. 220 221 try { 222 list.add(BYTE_STRING_A.toByteArray()); 223 fail(); 224 } catch (UnsupportedOperationException e) { 225 // expected 226 } 227 228 try { 229 list.add(BYTE_STRING_A); 230 fail(); 231 } catch (UnsupportedOperationException e) { 232 // expected 233 } 234 235 try { 236 list.addAllByteArray(asList(BYTE_STRING_A.toByteArray())); 237 fail(); 238 } catch (UnsupportedOperationException e) { 239 // expected 240 } 241 242 try { 243 list.addAllByteString(asList(BYTE_STRING_A)); 244 fail(); 245 } catch (UnsupportedOperationException e) { 246 // expected 247 } 248 249 try { 250 list.mergeFrom(new LazyStringArrayList()); 251 fail(); 252 } catch (UnsupportedOperationException e) { 253 // expected 254 } 255 256 try { 257 list.set(0, BYTE_STRING_A.toByteArray()); 258 fail(); 259 } catch (UnsupportedOperationException e) { 260 // expected 261 } 262 263 try { 264 list.set(0, BYTE_STRING_A); 265 fail(); 266 } catch (UnsupportedOperationException e) { 267 // expected 268 } 269 } 270 testImmutabilityPropagation()271 public void testImmutabilityPropagation() { 272 LazyStringArrayList list = new LazyStringArrayList(); 273 list.add(STRING_A); 274 list.makeImmutable(); 275 276 assertGenericListImmutable(list.asByteStringList(), BYTE_STRING_A); 277 278 // Arrays use reference equality so need to retrieve the underlying value 279 // to properly test deep immutability. 280 List<byte[]> byteArrayList = list.asByteArrayList(); 281 assertGenericListImmutable(byteArrayList, byteArrayList.get(0)); 282 } 283 assertGenericListImmutable(List<T> list, T value)284 private static <T> void assertGenericListImmutable(List<T> list, T value) { 285 try { 286 list.add(value); 287 fail(); 288 } catch (UnsupportedOperationException e) { 289 // expected 290 } 291 292 try { 293 list.add(0, value); 294 fail(); 295 } catch (UnsupportedOperationException e) { 296 // expected 297 } 298 299 try { 300 list.addAll(asList(value)); 301 fail(); 302 } catch (UnsupportedOperationException e) { 303 // expected 304 } 305 306 try { 307 list.addAll(0, asList(value)); 308 fail(); 309 } catch (UnsupportedOperationException e) { 310 // expected 311 } 312 313 try { 314 list.clear(); 315 fail(); 316 } catch (UnsupportedOperationException e) { 317 // expected 318 } 319 320 try { 321 list.remove(0); 322 fail(); 323 } catch (UnsupportedOperationException e) { 324 // expected 325 } 326 327 try { 328 list.remove(value); 329 fail(); 330 } catch (UnsupportedOperationException e) { 331 // expected 332 } 333 334 try { 335 list.removeAll(asList(value)); 336 fail(); 337 } catch (UnsupportedOperationException e) { 338 // expected 339 } 340 341 try { 342 list.retainAll(asList()); 343 fail(); 344 } catch (UnsupportedOperationException e) { 345 // expected 346 } 347 348 try { 349 list.retainAll(asList()); 350 fail(); 351 } catch (UnsupportedOperationException e) { 352 // expected 353 } 354 355 try { 356 list.set(0, value); 357 fail(); 358 } catch (UnsupportedOperationException e) { 359 // expected 360 } 361 } 362 } 363