1 /* 2 * Copyright (C) 2008 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 17 package com.google.common.collect; 18 19 import static com.google.common.base.Preconditions.checkNotNull; 20 21 import com.google.common.annotations.GwtCompatible; 22 import com.google.common.annotations.GwtIncompatible; 23 import com.google.common.base.Function; 24 import com.google.common.base.Functions; 25 import com.google.common.collect.Table.Cell; 26 import com.google.common.collect.testing.CollectionTestSuiteBuilder; 27 import com.google.common.collect.testing.MapInterfaceTest; 28 import com.google.common.collect.testing.SampleElements; 29 import com.google.common.collect.testing.SetTestSuiteBuilder; 30 import com.google.common.collect.testing.SortedSetTestSuiteBuilder; 31 import com.google.common.collect.testing.TestSetGenerator; 32 import com.google.common.collect.testing.TestStringCollectionGenerator; 33 import com.google.common.collect.testing.TestStringSetGenerator; 34 import com.google.common.collect.testing.TestStringSortedSetGenerator; 35 import com.google.common.collect.testing.features.CollectionFeature; 36 import com.google.common.collect.testing.features.CollectionSize; 37 import com.google.common.collect.testing.features.Feature; 38 import java.util.Arrays; 39 import java.util.Collection; 40 import java.util.Collections; 41 import java.util.List; 42 import java.util.Map; 43 import java.util.Set; 44 import java.util.SortedMap; 45 import java.util.SortedSet; 46 import junit.framework.Test; 47 import junit.framework.TestCase; 48 import junit.framework.TestSuite; 49 50 /** 51 * Collection tests for {@link Table} implementations. 52 * 53 * @author Jared Levy 54 * @author Louis Wasserman 55 */ 56 @GwtCompatible(emulated = true) 57 public class TableCollectionTest extends TestCase { 58 59 private static final Feature<?>[] COLLECTION_FEATURES = { 60 CollectionSize.ANY, CollectionFeature.ALLOWS_NULL_QUERIES 61 }; 62 63 private static final Feature<?>[] COLLECTION_FEATURES_ORDER = { 64 CollectionSize.ANY, CollectionFeature.KNOWN_ORDER, CollectionFeature.ALLOWS_NULL_QUERIES 65 }; 66 67 private static final Feature<?>[] COLLECTION_FEATURES_REMOVE = { 68 CollectionSize.ANY, CollectionFeature.SUPPORTS_REMOVE, CollectionFeature.ALLOWS_NULL_QUERIES 69 }; 70 71 private static final Feature<?>[] COLLECTION_FEATURES_REMOVE_ORDER = { 72 CollectionSize.ANY, 73 CollectionFeature.KNOWN_ORDER, 74 CollectionFeature.SUPPORTS_REMOVE, 75 CollectionFeature.ALLOWS_NULL_QUERIES 76 }; 77 78 @GwtIncompatible // suite suite()79 public static Test suite() { 80 TestSuite suite = new TestSuite(); 81 suite.addTestSuite(ArrayRowTests.class); 82 suite.addTestSuite(HashRowTests.class); 83 suite.addTestSuite(TreeRowTests.class); 84 suite.addTestSuite(TransposeRowTests.class); 85 suite.addTestSuite(TransformValueRowTests.class); 86 suite.addTestSuite(UnmodifiableHashRowTests.class); 87 suite.addTestSuite(UnmodifiableTreeRowTests.class); 88 suite.addTestSuite(ArrayColumnTests.class); 89 suite.addTestSuite(HashColumnTests.class); 90 suite.addTestSuite(TreeColumnTests.class); 91 suite.addTestSuite(TransposeColumnTests.class); 92 suite.addTestSuite(TransformValueColumnTests.class); 93 suite.addTestSuite(UnmodifiableHashColumnTests.class); 94 suite.addTestSuite(UnmodifiableTreeColumnTests.class); 95 suite.addTestSuite(ArrayRowMapTests.class); 96 suite.addTestSuite(HashRowMapTests.class); 97 suite.addTestSuite(TreeRowMapTests.class); 98 suite.addTestSuite(TreeRowMapHeadMapTests.class); 99 suite.addTestSuite(TreeRowMapTailMapTests.class); 100 suite.addTestSuite(TreeRowMapSubMapTests.class); 101 suite.addTestSuite(TransformValueRowMapTests.class); 102 suite.addTestSuite(UnmodifiableHashRowMapTests.class); 103 suite.addTestSuite(UnmodifiableTreeRowMapTests.class); 104 suite.addTestSuite(ArrayColumnMapTests.class); 105 suite.addTestSuite(HashColumnMapTests.class); 106 suite.addTestSuite(TreeColumnMapTests.class); 107 suite.addTestSuite(TransformValueColumnMapTests.class); 108 suite.addTestSuite(UnmodifiableHashColumnMapTests.class); 109 suite.addTestSuite(UnmodifiableTreeColumnMapTests.class); 110 111 // Not testing rowKeySet() or columnKeySet() of Table.transformValues() 112 // since the transformation doesn't affect the row and column key sets. 113 114 suite.addTest( 115 SetTestSuiteBuilder.using( 116 new TestStringSetGenerator() { 117 @Override 118 protected Set<String> create(String[] elements) { 119 Table<String, Integer, Character> table = 120 ArrayTable.create(ImmutableList.copyOf(elements), ImmutableList.of(1, 2)); 121 populateForRowKeySet(table, elements); 122 return table.rowKeySet(); 123 } 124 }) 125 .named("ArrayTable.rowKeySet") 126 .withFeatures( 127 CollectionSize.ONE, 128 CollectionSize.SEVERAL, 129 CollectionFeature.KNOWN_ORDER, 130 CollectionFeature.REJECTS_DUPLICATES_AT_CREATION, 131 CollectionFeature.ALLOWS_NULL_QUERIES) 132 .createTestSuite()); 133 134 suite.addTest( 135 SetTestSuiteBuilder.using( 136 new TestStringSetGenerator() { 137 @Override 138 protected Set<String> create(String[] elements) { 139 Table<String, Integer, Character> table = HashBasedTable.create(); 140 populateForRowKeySet(table, elements); 141 return table.rowKeySet(); 142 } 143 }) 144 .named("HashBasedTable.rowKeySet") 145 .withFeatures(COLLECTION_FEATURES_REMOVE) 146 .withFeatures(CollectionFeature.SUPPORTS_ITERATOR_REMOVE) 147 .createTestSuite()); 148 149 suite.addTest( 150 SortedSetTestSuiteBuilder.using( 151 new TestStringSortedSetGenerator() { 152 @Override 153 protected SortedSet<String> create(String[] elements) { 154 TreeBasedTable<String, Integer, Character> table = TreeBasedTable.create(); 155 populateForRowKeySet(table, elements); 156 return table.rowKeySet(); 157 } 158 159 @Override 160 public List<String> order(List<String> insertionOrder) { 161 Collections.sort(insertionOrder); 162 return insertionOrder; 163 } 164 }) 165 .named("TreeBasedTable.rowKeySet") 166 .withFeatures(COLLECTION_FEATURES_REMOVE_ORDER) 167 .withFeatures(CollectionFeature.SUPPORTS_ITERATOR_REMOVE) 168 .createTestSuite()); 169 170 suite.addTest( 171 SetTestSuiteBuilder.using( 172 new TestStringSetGenerator() { 173 @Override 174 protected Set<String> create(String[] elements) { 175 Table<String, Integer, Character> table = HashBasedTable.create(); 176 populateForRowKeySet(table, elements); 177 return Tables.unmodifiableTable(table).rowKeySet(); 178 } 179 }) 180 .named("unmodifiableTable[HashBasedTable].rowKeySet") 181 .withFeatures(COLLECTION_FEATURES) 182 .createTestSuite()); 183 184 suite.addTest( 185 SetTestSuiteBuilder.using( 186 new TestStringSetGenerator() { 187 @Override 188 protected Set<String> create(String[] elements) { 189 RowSortedTable<String, Integer, Character> table = TreeBasedTable.create(); 190 populateForRowKeySet(table, elements); 191 return Tables.unmodifiableRowSortedTable(table).rowKeySet(); 192 } 193 194 @Override 195 public List<String> order(List<String> insertionOrder) { 196 Collections.sort(insertionOrder); 197 return insertionOrder; 198 } 199 }) 200 .named("unmodifiableRowSortedTable[TreeBasedTable].rowKeySet") 201 .withFeatures(COLLECTION_FEATURES_ORDER) 202 .createTestSuite()); 203 204 suite.addTest( 205 SetTestSuiteBuilder.using( 206 new TestStringSetGenerator() { 207 @Override 208 protected Set<String> create(String[] elements) { 209 Table<Integer, String, Character> table = 210 ArrayTable.create(ImmutableList.of(1, 2), ImmutableList.copyOf(elements)); 211 populateForColumnKeySet(table, elements); 212 return table.columnKeySet(); 213 } 214 }) 215 .named("ArrayTable.columnKeySet") 216 .withFeatures( 217 CollectionSize.ONE, 218 CollectionSize.SEVERAL, 219 CollectionFeature.KNOWN_ORDER, 220 CollectionFeature.REJECTS_DUPLICATES_AT_CREATION, 221 CollectionFeature.ALLOWS_NULL_QUERIES) 222 .createTestSuite()); 223 224 suite.addTest( 225 SetTestSuiteBuilder.using( 226 new TestStringSetGenerator() { 227 @Override 228 protected Set<String> create(String[] elements) { 229 Table<Integer, String, Character> table = HashBasedTable.create(); 230 populateForColumnKeySet(table, elements); 231 return table.columnKeySet(); 232 } 233 }) 234 .named("HashBasedTable.columnKeySet") 235 .withFeatures(COLLECTION_FEATURES_REMOVE) 236 .createTestSuite()); 237 238 suite.addTest( 239 SetTestSuiteBuilder.using( 240 new TestStringSetGenerator() { 241 @Override 242 protected Set<String> create(String[] elements) { 243 Table<Integer, String, Character> table = TreeBasedTable.create(); 244 populateForColumnKeySet(table, elements); 245 return table.columnKeySet(); 246 } 247 248 @Override 249 public List<String> order(List<String> insertionOrder) { 250 Collections.sort(insertionOrder); 251 return insertionOrder; 252 } 253 }) 254 .named("TreeBasedTable.columnKeySet") 255 .withFeatures(COLLECTION_FEATURES_REMOVE_ORDER) 256 .createTestSuite()); 257 258 suite.addTest( 259 SetTestSuiteBuilder.using( 260 new TestStringSetGenerator() { 261 @Override 262 protected Set<String> create(String[] elements) { 263 Table<Integer, String, Character> table = HashBasedTable.create(); 264 populateForColumnKeySet(table, elements); 265 return Tables.unmodifiableTable(table).columnKeySet(); 266 } 267 }) 268 .named("unmodifiableTable[HashBasedTable].columnKeySet") 269 .withFeatures(COLLECTION_FEATURES) 270 .createTestSuite()); 271 272 suite.addTest( 273 SetTestSuiteBuilder.using( 274 new TestStringSetGenerator() { 275 @Override 276 protected Set<String> create(String[] elements) { 277 RowSortedTable<Integer, String, Character> table = TreeBasedTable.create(); 278 populateForColumnKeySet(table, elements); 279 return Tables.unmodifiableRowSortedTable(table).columnKeySet(); 280 } 281 282 @Override 283 public List<String> order(List<String> insertionOrder) { 284 Collections.sort(insertionOrder); 285 return insertionOrder; 286 } 287 }) 288 .named("unmodifiableRowSortedTable[TreeBasedTable].columnKeySet") 289 .withFeatures(COLLECTION_FEATURES_ORDER) 290 .createTestSuite()); 291 292 suite.addTest( 293 CollectionTestSuiteBuilder.using( 294 new TestStringCollectionGenerator() { 295 @Override 296 protected Collection<String> create(String[] elements) { 297 List<Integer> rowKeys = Lists.newArrayList(); 298 for (int i = 0; i < elements.length; i++) { 299 rowKeys.add(i); 300 } 301 Table<Integer, Character, String> table = 302 ArrayTable.create(rowKeys, ImmutableList.of('a')); 303 populateForValues(table, elements); 304 return table.values(); 305 } 306 }) 307 .named("ArrayTable.values") 308 .withFeatures( 309 CollectionSize.ONE, 310 CollectionSize.SEVERAL, 311 CollectionFeature.ALLOWS_NULL_VALUES, 312 CollectionFeature.KNOWN_ORDER) 313 .createTestSuite()); 314 315 suite.addTest( 316 CollectionTestSuiteBuilder.using( 317 new TestStringCollectionGenerator() { 318 @Override 319 protected Collection<String> create(String[] elements) { 320 Table<Integer, Character, String> table = HashBasedTable.create(); 321 table.put(1, 'a', "foo"); 322 table.clear(); 323 populateForValues(table, elements); 324 return table.values(); 325 } 326 }) 327 .named("HashBasedTable.values") 328 .withFeatures(COLLECTION_FEATURES_REMOVE) 329 .withFeatures(CollectionFeature.SUPPORTS_ITERATOR_REMOVE) 330 .createTestSuite()); 331 332 suite.addTest( 333 CollectionTestSuiteBuilder.using( 334 new TestStringCollectionGenerator() { 335 @Override 336 protected Collection<String> create(String[] elements) { 337 Table<Integer, Character, String> table = TreeBasedTable.create(); 338 table.put(1, 'a', "foo"); 339 table.clear(); 340 populateForValues(table, elements); 341 return table.values(); 342 } 343 }) 344 .named("TreeBasedTable.values") 345 .withFeatures(COLLECTION_FEATURES_REMOVE_ORDER) 346 .withFeatures(CollectionFeature.SUPPORTS_ITERATOR_REMOVE) 347 .createTestSuite()); 348 349 final Function<String, String> removeFirstCharacter = 350 new Function<String, String>() { 351 @Override 352 public String apply(String input) { 353 return input.substring(1); 354 } 355 }; 356 357 suite.addTest( 358 CollectionTestSuiteBuilder.using( 359 new TestStringCollectionGenerator() { 360 @Override 361 protected Collection<String> create(String[] elements) { 362 Table<Integer, Character, String> table = HashBasedTable.create(); 363 for (int i = 0; i < elements.length; i++) { 364 table.put(i, 'a', "x" + checkNotNull(elements[i])); 365 } 366 return Tables.transformValues(table, removeFirstCharacter).values(); 367 } 368 }) 369 .named("TransformValues.values") 370 .withFeatures(COLLECTION_FEATURES_REMOVE) 371 .withFeatures(CollectionFeature.SUPPORTS_ITERATOR_REMOVE) 372 .createTestSuite()); 373 374 suite.addTest( 375 CollectionTestSuiteBuilder.using( 376 new TestStringCollectionGenerator() { 377 @Override 378 protected Collection<String> create(String[] elements) { 379 Table<Integer, Character, String> table = HashBasedTable.create(); 380 table.put(1, 'a', "foo"); 381 table.clear(); 382 populateForValues(table, elements); 383 return Tables.unmodifiableTable(table).values(); 384 } 385 }) 386 .named("unmodifiableTable[HashBasedTable].values") 387 .withFeatures(COLLECTION_FEATURES) 388 .createTestSuite()); 389 390 suite.addTest( 391 CollectionTestSuiteBuilder.using( 392 new TestStringCollectionGenerator() { 393 @Override 394 protected Collection<String> create(String[] elements) { 395 RowSortedTable<Integer, Character, String> table = TreeBasedTable.create(); 396 table.put(1, 'a', "foo"); 397 table.clear(); 398 populateForValues(table, elements); 399 return Tables.unmodifiableRowSortedTable(table).values(); 400 } 401 }) 402 .named("unmodifiableTable[TreeBasedTable].values") 403 .withFeatures(COLLECTION_FEATURES_ORDER) 404 .createTestSuite()); 405 406 suite.addTest( 407 SetTestSuiteBuilder.using( 408 new TestCellSetGenerator() { 409 @Override 410 public SampleElements<Cell<String, Integer, Character>> samples() { 411 return new SampleElements<>( 412 Tables.immutableCell("bar", 1, 'a'), 413 Tables.immutableCell("bar", 2, 'b'), 414 Tables.immutableCell("bar", 3, (Character) null), 415 Tables.immutableCell("bar", 4, 'b'), 416 Tables.immutableCell("bar", 5, 'b')); 417 } 418 419 @Override 420 public Set<Cell<String, Integer, Character>> create(Object... elements) { 421 List<Integer> columnKeys = Lists.newArrayList(); 422 for (Object element : elements) { 423 @SuppressWarnings("unchecked") 424 Cell<String, Integer, Character> cell = 425 (Cell<String, Integer, Character>) element; 426 columnKeys.add(cell.getColumnKey()); 427 } 428 Table<String, Integer, Character> table = 429 ArrayTable.create(ImmutableList.of("bar"), columnKeys); 430 for (Object element : elements) { 431 @SuppressWarnings("unchecked") 432 Cell<String, Integer, Character> cell = 433 (Cell<String, Integer, Character>) element; 434 table.put(cell.getRowKey(), cell.getColumnKey(), cell.getValue()); 435 } 436 return table.cellSet(); 437 } 438 439 @Override 440 Table<String, Integer, Character> createTable() { 441 throw new UnsupportedOperationException(); 442 } 443 }) 444 .named("ArrayTable.cellSet") 445 .withFeatures( 446 CollectionSize.ONE, 447 CollectionSize.SEVERAL, 448 CollectionFeature.KNOWN_ORDER, 449 CollectionFeature.REJECTS_DUPLICATES_AT_CREATION, 450 CollectionFeature.ALLOWS_NULL_QUERIES) 451 .createTestSuite()); 452 453 suite.addTest( 454 SetTestSuiteBuilder.using( 455 new TestCellSetGenerator() { 456 @Override 457 Table<String, Integer, Character> createTable() { 458 return HashBasedTable.create(); 459 } 460 }) 461 .named("HashBasedTable.cellSet") 462 .withFeatures( 463 CollectionSize.ANY, 464 CollectionFeature.REMOVE_OPERATIONS, 465 CollectionFeature.ALLOWS_NULL_QUERIES) 466 .createTestSuite()); 467 468 suite.addTest( 469 SetTestSuiteBuilder.using( 470 new TestCellSetGenerator() { 471 @Override 472 Table<String, Integer, Character> createTable() { 473 return TreeBasedTable.create(); 474 } 475 }) 476 .named("TreeBasedTable.cellSet") 477 .withFeatures( 478 CollectionSize.ANY, 479 CollectionFeature.REMOVE_OPERATIONS, 480 CollectionFeature.ALLOWS_NULL_QUERIES) 481 .createTestSuite()); 482 483 suite.addTest( 484 SetTestSuiteBuilder.using( 485 new TestCellSetGenerator() { 486 @Override 487 Table<String, Integer, Character> createTable() { 488 Table<Integer, String, Character> original = TreeBasedTable.create(); 489 return Tables.transpose(original); 490 } 491 }) 492 .named("TransposedTable.cellSet") 493 .withFeatures( 494 CollectionSize.ANY, 495 CollectionFeature.REMOVE_OPERATIONS, 496 CollectionFeature.ALLOWS_NULL_QUERIES) 497 .createTestSuite()); 498 499 suite.addTest( 500 SetTestSuiteBuilder.using( 501 new TestCellSetGenerator() { 502 @Override 503 Table<String, Integer, Character> createTable() { 504 return HashBasedTable.create(); 505 } 506 507 @Override 508 public Set<Cell<String, Integer, Character>> create(Object... elements) { 509 Table<String, Integer, Character> table = createTable(); 510 for (Object element : elements) { 511 @SuppressWarnings("unchecked") 512 Cell<String, Integer, Character> cell = 513 (Cell<String, Integer, Character>) element; 514 table.put(cell.getRowKey(), cell.getColumnKey(), cell.getValue()); 515 } 516 return Tables.transformValues(table, Functions.<Character>identity()).cellSet(); 517 } 518 }) 519 .named("TransformValues.cellSet") 520 .withFeatures( 521 CollectionSize.ANY, 522 CollectionFeature.ALLOWS_NULL_QUERIES, 523 CollectionFeature.REMOVE_OPERATIONS) 524 .createTestSuite()); 525 526 suite.addTest( 527 SetTestSuiteBuilder.using( 528 new TestCellSetGenerator() { 529 @Override 530 Table<String, Integer, Character> createTable() { 531 return Tables.unmodifiableTable( 532 HashBasedTable.<String, Integer, Character>create()); 533 } 534 535 @Override 536 public Set<Cell<String, Integer, Character>> create(Object... elements) { 537 Table<String, Integer, Character> table = HashBasedTable.create(); 538 for (Object element : elements) { 539 @SuppressWarnings("unchecked") 540 Cell<String, Integer, Character> cell = 541 (Cell<String, Integer, Character>) element; 542 table.put(cell.getRowKey(), cell.getColumnKey(), cell.getValue()); 543 } 544 return Tables.unmodifiableTable(table).cellSet(); 545 } 546 }) 547 .named("unmodifiableTable[HashBasedTable].cellSet") 548 .withFeatures(CollectionSize.ANY, CollectionFeature.ALLOWS_NULL_QUERIES) 549 .createTestSuite()); 550 551 suite.addTest( 552 SetTestSuiteBuilder.using( 553 new TestCellSetGenerator() { 554 @Override 555 RowSortedTable<String, Integer, Character> createTable() { 556 return Tables.unmodifiableRowSortedTable( 557 TreeBasedTable.<String, Integer, Character>create()); 558 } 559 560 @Override 561 public Set<Cell<String, Integer, Character>> create(Object... elements) { 562 RowSortedTable<String, Integer, Character> table = TreeBasedTable.create(); 563 for (Object element : elements) { 564 @SuppressWarnings("unchecked") 565 Cell<String, Integer, Character> cell = 566 (Cell<String, Integer, Character>) element; 567 table.put(cell.getRowKey(), cell.getColumnKey(), cell.getValue()); 568 } 569 return Tables.unmodifiableRowSortedTable(table).cellSet(); 570 } 571 }) 572 .named("unmodifiableRowSortedTable[TreeBasedTable].cellSet") 573 .withFeatures(CollectionSize.ANY, CollectionFeature.ALLOWS_NULL_QUERIES) 574 .createTestSuite()); 575 576 suite.addTest( 577 SetTestSuiteBuilder.using( 578 new TestStringSetGenerator() { 579 @Override 580 protected Set<String> create(String[] elements) { 581 Iterable<String> rowKeys = ImmutableSet.copyOf(elements); 582 Iterable<Integer> columnKeys = ImmutableList.of(1, 2, 3); 583 Table<String, Integer, Character> table = 584 ArrayTable.create(rowKeys, columnKeys); 585 populateForRowKeySet(table, elements); 586 return table.column(1).keySet(); 587 } 588 }) 589 .named("ArrayTable.column.keySet") 590 .withFeatures( 591 CollectionSize.ONE, 592 CollectionSize.SEVERAL, 593 CollectionFeature.KNOWN_ORDER, 594 CollectionFeature.ALLOWS_NULL_QUERIES) 595 .createTestSuite()); 596 597 suite.addTest( 598 SetTestSuiteBuilder.using( 599 new TestStringSetGenerator() { 600 @Override 601 protected Set<String> create(String[] elements) { 602 Table<String, Integer, Character> table = HashBasedTable.create(); 603 populateForRowKeySet(table, elements); 604 return table.column(1).keySet(); 605 } 606 }) 607 .named("HashBasedTable.column.keySet") 608 .withFeatures(COLLECTION_FEATURES_REMOVE) 609 .createTestSuite()); 610 611 suite.addTest( 612 SetTestSuiteBuilder.using( 613 new TestStringSetGenerator() { 614 @Override 615 protected Set<String> create(String[] elements) { 616 Table<String, Integer, Character> table = TreeBasedTable.create(); 617 populateForRowKeySet(table, elements); 618 return table.column(1).keySet(); 619 } 620 621 @Override 622 public List<String> order(List<String> insertionOrder) { 623 Collections.sort(insertionOrder); 624 return insertionOrder; 625 } 626 }) 627 .named("TreeBasedTable.column.keySet") 628 .withFeatures(COLLECTION_FEATURES_REMOVE_ORDER) 629 .createTestSuite()); 630 631 suite.addTest( 632 SetTestSuiteBuilder.using( 633 new TestStringSetGenerator() { 634 @Override 635 protected Set<String> create(String[] elements) { 636 Table<String, Integer, Character> table = HashBasedTable.create(); 637 populateForRowKeySet(table, elements); 638 return Tables.transformValues(table, Functions.toStringFunction()) 639 .column(1) 640 .keySet(); 641 } 642 }) 643 .named("TransformValues.column.keySet") 644 .withFeatures(COLLECTION_FEATURES_REMOVE) 645 .createTestSuite()); 646 647 suite.addTest( 648 SetTestSuiteBuilder.using( 649 new TestStringSetGenerator() { 650 @Override 651 protected Set<String> create(String[] elements) { 652 Table<String, Integer, Character> table = HashBasedTable.create(); 653 populateForRowKeySet(table, elements); 654 return Tables.unmodifiableTable(table).column(1).keySet(); 655 } 656 }) 657 .named("unmodifiableTable[HashBasedTable].column.keySet") 658 .withFeatures(COLLECTION_FEATURES) 659 .createTestSuite()); 660 661 suite.addTest( 662 SetTestSuiteBuilder.using( 663 new TestStringSetGenerator() { 664 @Override 665 protected Set<String> create(String[] elements) { 666 RowSortedTable<String, Integer, Character> table = TreeBasedTable.create(); 667 populateForRowKeySet(table, elements); 668 return Tables.unmodifiableRowSortedTable(table).column(1).keySet(); 669 } 670 671 @Override 672 public List<String> order(List<String> insertionOrder) { 673 Collections.sort(insertionOrder); 674 return insertionOrder; 675 } 676 }) 677 .named("unmodifiableRowSortedTable[TreeBasedTable].column.keySet") 678 .withFeatures(COLLECTION_FEATURES_ORDER) 679 .createTestSuite()); 680 681 return suite; 682 } 683 populateForRowKeySet( Table<String, Integer, Character> table, String[] elements)684 private static void populateForRowKeySet( 685 Table<String, Integer, Character> table, String[] elements) { 686 for (String row : elements) { 687 table.put(row, 1, 'a'); 688 table.put(row, 2, 'b'); 689 } 690 } 691 populateForColumnKeySet( Table<Integer, String, Character> table, String[] elements)692 private static void populateForColumnKeySet( 693 Table<Integer, String, Character> table, String[] elements) { 694 for (String column : elements) { 695 table.put(1, column, 'a'); 696 table.put(2, column, 'b'); 697 } 698 } 699 populateForValues( Table<Integer, Character, String> table, String[] elements)700 private static void populateForValues( 701 Table<Integer, Character, String> table, String[] elements) { 702 for (int i = 0; i < elements.length; i++) { 703 table.put(i, 'a', elements[i]); 704 } 705 } 706 707 private abstract static class TestCellSetGenerator 708 implements TestSetGenerator<Cell<String, Integer, Character>> { 709 @Override samples()710 public SampleElements<Cell<String, Integer, Character>> samples() { 711 return new SampleElements<>( 712 Tables.immutableCell("bar", 1, 'a'), 713 Tables.immutableCell("bar", 2, 'b'), 714 Tables.immutableCell("foo", 3, 'c'), 715 Tables.immutableCell("bar", 1, 'b'), 716 Tables.immutableCell("cat", 2, 'b')); 717 } 718 719 @Override create(Object... elements)720 public Set<Cell<String, Integer, Character>> create(Object... elements) { 721 Table<String, Integer, Character> table = createTable(); 722 for (Object element : elements) { 723 @SuppressWarnings("unchecked") 724 Cell<String, Integer, Character> cell = (Cell<String, Integer, Character>) element; 725 table.put(cell.getRowKey(), cell.getColumnKey(), cell.getValue()); 726 } 727 return table.cellSet(); 728 } 729 createTable()730 abstract Table<String, Integer, Character> createTable(); 731 732 @Override 733 @SuppressWarnings("unchecked") createArray(int length)734 public Cell<String, Integer, Character>[] createArray(int length) { 735 return (Cell<String, Integer, Character>[]) new Cell<?, ?, ?>[length]; 736 } 737 738 @Override order( List<Cell<String, Integer, Character>> insertionOrder)739 public List<Cell<String, Integer, Character>> order( 740 List<Cell<String, Integer, Character>> insertionOrder) { 741 return insertionOrder; 742 } 743 } 744 745 private abstract static class MapTests extends MapInterfaceTest<String, Integer> { 746 MapTests( boolean allowsNullValues, boolean supportsPut, boolean supportsRemove, boolean supportsClear, boolean supportsIteratorRemove)747 MapTests( 748 boolean allowsNullValues, 749 boolean supportsPut, 750 boolean supportsRemove, 751 boolean supportsClear, 752 boolean supportsIteratorRemove) { 753 super( 754 false, 755 allowsNullValues, 756 supportsPut, 757 supportsRemove, 758 supportsClear, 759 supportsIteratorRemove); 760 } 761 762 @Override getKeyNotInPopulatedMap()763 protected String getKeyNotInPopulatedMap() { 764 return "four"; 765 } 766 767 @Override getValueNotInPopulatedMap()768 protected Integer getValueNotInPopulatedMap() { 769 return 4; 770 } 771 } 772 773 private abstract static class RowTests extends MapTests { RowTests( boolean allowsNullValues, boolean supportsPut, boolean supportsRemove, boolean supportsClear, boolean supportsIteratorRemove)774 RowTests( 775 boolean allowsNullValues, 776 boolean supportsPut, 777 boolean supportsRemove, 778 boolean supportsClear, 779 boolean supportsIteratorRemove) { 780 super(allowsNullValues, supportsPut, supportsRemove, supportsClear, supportsIteratorRemove); 781 } 782 makeTable()783 abstract Table<Character, String, Integer> makeTable(); 784 785 @Override makeEmptyMap()786 protected Map<String, Integer> makeEmptyMap() { 787 return makeTable().row('a'); 788 } 789 790 @Override makePopulatedMap()791 protected Map<String, Integer> makePopulatedMap() { 792 Table<Character, String, Integer> table = makeTable(); 793 table.put('a', "one", 1); 794 table.put('a', "two", 2); 795 table.put('a', "three", 3); 796 table.put('b', "four", 4); 797 return table.row('a'); 798 } 799 } 800 801 @GwtIncompatible // TODO(hhchan): ArrayTable 802 public static class ArrayRowTests extends RowTests { ArrayRowTests()803 public ArrayRowTests() { 804 super(true, true, false, false, false); 805 } 806 807 @Override getKeyNotInPopulatedMap()808 protected String getKeyNotInPopulatedMap() { 809 throw new UnsupportedOperationException(); 810 } 811 812 @Override makeEmptyMap()813 protected Map<String, Integer> makeEmptyMap() { 814 throw new UnsupportedOperationException(); 815 } 816 817 @Override makeTable()818 protected Table<Character, String, Integer> makeTable() { 819 return ArrayTable.create( 820 Arrays.asList('a', 'b', 'c'), Arrays.asList("one", "two", "three", "four")); 821 } 822 } 823 824 public static class HashRowTests extends RowTests { HashRowTests()825 public HashRowTests() { 826 super(false, true, true, true, true); 827 } 828 829 @Override makeTable()830 Table<Character, String, Integer> makeTable() { 831 return HashBasedTable.create(); 832 } 833 } 834 835 public static class TreeRowTests extends RowTests { TreeRowTests()836 public TreeRowTests() { 837 super(false, true, true, true, true); 838 } 839 840 @Override makeTable()841 Table<Character, String, Integer> makeTable() { 842 return TreeBasedTable.create(); 843 } 844 } 845 846 public static class TransposeRowTests extends RowTests { TransposeRowTests()847 public TransposeRowTests() { 848 super(false, true, true, true, false); 849 } 850 851 @Override makeTable()852 Table<Character, String, Integer> makeTable() { 853 Table<String, Character, Integer> original = TreeBasedTable.create(); 854 return Tables.transpose(original); 855 } 856 } 857 858 private static final Function<Integer, Integer> DIVIDE_BY_2 = 859 new Function<Integer, Integer>() { 860 @Override 861 public Integer apply(Integer input) { 862 return (input == null) ? null : input / 2; 863 } 864 }; 865 866 public static class TransformValueRowTests extends RowTests { TransformValueRowTests()867 public TransformValueRowTests() { 868 super(false, false, true, true, true); 869 } 870 871 @Override makeTable()872 Table<Character, String, Integer> makeTable() { 873 Table<Character, String, Integer> table = HashBasedTable.create(); 874 return Tables.transformValues(table, DIVIDE_BY_2); 875 } 876 877 @Override makePopulatedMap()878 protected Map<String, Integer> makePopulatedMap() { 879 Table<Character, String, Integer> table = HashBasedTable.create(); 880 table.put('a', "one", 2); 881 table.put('a', "two", 4); 882 table.put('a', "three", 6); 883 table.put('b', "four", 8); 884 return Tables.transformValues(table, DIVIDE_BY_2).row('a'); 885 } 886 } 887 888 public static class UnmodifiableHashRowTests extends RowTests { UnmodifiableHashRowTests()889 public UnmodifiableHashRowTests() { 890 super(false, false, false, false, false); 891 } 892 893 @Override makeTable()894 Table<Character, String, Integer> makeTable() { 895 Table<Character, String, Integer> table = HashBasedTable.create(); 896 return Tables.unmodifiableTable(table); 897 } 898 899 @Override makePopulatedMap()900 protected Map<String, Integer> makePopulatedMap() { 901 Table<Character, String, Integer> table = HashBasedTable.create(); 902 table.put('a', "one", 1); 903 table.put('a', "two", 2); 904 table.put('a', "three", 3); 905 table.put('b', "four", 4); 906 return Tables.unmodifiableTable(table).row('a'); 907 } 908 } 909 910 public static class UnmodifiableTreeRowTests extends RowTests { UnmodifiableTreeRowTests()911 public UnmodifiableTreeRowTests() { 912 super(false, false, false, false, false); 913 } 914 915 @Override makeTable()916 Table<Character, String, Integer> makeTable() { 917 RowSortedTable<Character, String, Integer> table = TreeBasedTable.create(); 918 return Tables.unmodifiableRowSortedTable(table); 919 } 920 921 @Override makePopulatedMap()922 protected Map<String, Integer> makePopulatedMap() { 923 RowSortedTable<Character, String, Integer> table = TreeBasedTable.create(); 924 table.put('a', "one", 1); 925 table.put('a', "two", 2); 926 table.put('a', "three", 3); 927 table.put('b', "four", 4); 928 return Tables.unmodifiableRowSortedTable(table).row('a'); 929 } 930 } 931 932 private abstract static class ColumnTests extends MapTests { ColumnTests( boolean allowsNullValues, boolean supportsPut, boolean supportsRemove, boolean supportsClear, boolean supportsIteratorRemove)933 ColumnTests( 934 boolean allowsNullValues, 935 boolean supportsPut, 936 boolean supportsRemove, 937 boolean supportsClear, 938 boolean supportsIteratorRemove) { 939 super(allowsNullValues, supportsPut, supportsRemove, supportsClear, supportsIteratorRemove); 940 } 941 makeTable()942 abstract Table<String, Character, Integer> makeTable(); 943 944 @Override makeEmptyMap()945 protected Map<String, Integer> makeEmptyMap() { 946 return makeTable().column('a'); 947 } 948 949 @Override makePopulatedMap()950 protected Map<String, Integer> makePopulatedMap() { 951 Table<String, Character, Integer> table = makeTable(); 952 table.put("one", 'a', 1); 953 table.put("two", 'a', 2); 954 table.put("three", 'a', 3); 955 table.put("four", 'b', 4); 956 return table.column('a'); 957 } 958 } 959 960 @GwtIncompatible // TODO(hhchan): ArrayTable 961 public static class ArrayColumnTests extends ColumnTests { ArrayColumnTests()962 public ArrayColumnTests() { 963 super(true, true, false, false, false); 964 } 965 966 @Override getKeyNotInPopulatedMap()967 protected String getKeyNotInPopulatedMap() { 968 throw new UnsupportedOperationException(); 969 } 970 971 @Override makeEmptyMap()972 protected Map<String, Integer> makeEmptyMap() { 973 throw new UnsupportedOperationException(); 974 } 975 976 @Override makeTable()977 Table<String, Character, Integer> makeTable() { 978 return ArrayTable.create( 979 Arrays.asList("one", "two", "three", "four"), Arrays.asList('a', 'b', 'c')); 980 } 981 } 982 983 public static class HashColumnTests extends ColumnTests { HashColumnTests()984 public HashColumnTests() { 985 super(false, true, true, true, false); 986 } 987 988 @Override makeTable()989 Table<String, Character, Integer> makeTable() { 990 return HashBasedTable.create(); 991 } 992 } 993 994 public static class TreeColumnTests extends ColumnTests { TreeColumnTests()995 public TreeColumnTests() { 996 super(false, true, true, true, false); 997 } 998 999 @Override makeTable()1000 Table<String, Character, Integer> makeTable() { 1001 return TreeBasedTable.create(); 1002 } 1003 } 1004 1005 public static class TransposeColumnTests extends ColumnTests { TransposeColumnTests()1006 public TransposeColumnTests() { 1007 super(false, true, true, true, true); 1008 } 1009 1010 @Override makeTable()1011 Table<String, Character, Integer> makeTable() { 1012 Table<Character, String, Integer> original = TreeBasedTable.create(); 1013 return Tables.transpose(original); 1014 } 1015 } 1016 1017 public static class TransformValueColumnTests extends ColumnTests { TransformValueColumnTests()1018 public TransformValueColumnTests() { 1019 super(false, false, true, true, false); 1020 } 1021 1022 @Override makeTable()1023 Table<String, Character, Integer> makeTable() { 1024 Table<String, Character, Integer> table = HashBasedTable.create(); 1025 return Tables.transformValues(table, DIVIDE_BY_2); 1026 } 1027 1028 @Override makePopulatedMap()1029 protected Map<String, Integer> makePopulatedMap() { 1030 Table<String, Character, Integer> table = HashBasedTable.create(); 1031 table.put("one", 'a', 1); 1032 table.put("two", 'a', 2); 1033 table.put("three", 'a', 3); 1034 table.put("four", 'b', 4); 1035 return Tables.transformValues(table, DIVIDE_BY_2).column('a'); 1036 } 1037 } 1038 1039 public static class UnmodifiableHashColumnTests extends ColumnTests { UnmodifiableHashColumnTests()1040 public UnmodifiableHashColumnTests() { 1041 super(false, false, false, false, false); 1042 } 1043 1044 @Override makeTable()1045 Table<String, Character, Integer> makeTable() { 1046 Table<String, Character, Integer> table = HashBasedTable.create(); 1047 return Tables.unmodifiableTable(table); 1048 } 1049 1050 @Override makePopulatedMap()1051 protected Map<String, Integer> makePopulatedMap() { 1052 Table<String, Character, Integer> table = HashBasedTable.create(); 1053 table.put("one", 'a', 1); 1054 table.put("two", 'a', 2); 1055 table.put("three", 'a', 3); 1056 table.put("four", 'b', 4); 1057 return Tables.unmodifiableTable(table).column('a'); 1058 } 1059 } 1060 1061 public static class UnmodifiableTreeColumnTests extends ColumnTests { UnmodifiableTreeColumnTests()1062 public UnmodifiableTreeColumnTests() { 1063 super(false, false, false, false, false); 1064 } 1065 1066 @Override makeTable()1067 Table<String, Character, Integer> makeTable() { 1068 RowSortedTable<String, Character, Integer> table = TreeBasedTable.create(); 1069 return Tables.unmodifiableRowSortedTable(table); 1070 } 1071 1072 @Override makePopulatedMap()1073 protected Map<String, Integer> makePopulatedMap() { 1074 RowSortedTable<String, Character, Integer> table = TreeBasedTable.create(); 1075 table.put("one", 'a', 1); 1076 table.put("two", 'a', 2); 1077 table.put("three", 'a', 3); 1078 table.put("four", 'b', 4); 1079 return Tables.unmodifiableRowSortedTable(table).column('a'); 1080 } 1081 } 1082 1083 private abstract static class MapMapTests 1084 extends MapInterfaceTest<String, Map<Integer, Character>> { 1085 MapMapTests( boolean allowsNullValues, boolean supportsRemove, boolean supportsClear, boolean supportsIteratorRemove)1086 MapMapTests( 1087 boolean allowsNullValues, 1088 boolean supportsRemove, 1089 boolean supportsClear, 1090 boolean supportsIteratorRemove) { 1091 super(false, allowsNullValues, false, supportsRemove, supportsClear, supportsIteratorRemove); 1092 } 1093 1094 @Override getKeyNotInPopulatedMap()1095 protected String getKeyNotInPopulatedMap() { 1096 return "cat"; 1097 } 1098 1099 @Override getValueNotInPopulatedMap()1100 protected Map<Integer, Character> getValueNotInPopulatedMap() { 1101 return ImmutableMap.of(); 1102 } 1103 1104 /** 1105 * The version of this test supplied by {@link MapInterfaceTest} fails for this particular map 1106 * implementation, because {@code map.get()} returns a view collection that changes in the 1107 * course of a call to {@code remove()}. Thus, the expectation doesn't hold that {@code 1108 * map.remove(x)} returns the same value which {@code map.get(x)} did immediately beforehand. 1109 */ 1110 @Override testRemove()1111 public void testRemove() { 1112 final Map<String, Map<Integer, Character>> map; 1113 final String keyToRemove; 1114 try { 1115 map = makePopulatedMap(); 1116 } catch (UnsupportedOperationException e) { 1117 return; 1118 } 1119 keyToRemove = map.keySet().iterator().next(); 1120 if (supportsRemove) { 1121 int initialSize = map.size(); 1122 map.get(keyToRemove); 1123 map.remove(keyToRemove); 1124 // This line doesn't hold - see the Javadoc comments above. 1125 // assertEquals(expectedValue, oldValue); 1126 assertFalse(map.containsKey(keyToRemove)); 1127 assertEquals(initialSize - 1, map.size()); 1128 } else { 1129 try { 1130 map.remove(keyToRemove); 1131 fail("Expected UnsupportedOperationException."); 1132 } catch (UnsupportedOperationException expected) { 1133 } 1134 } 1135 assertInvariants(map); 1136 } 1137 } 1138 1139 private abstract static class RowMapTests extends MapMapTests { RowMapTests( boolean allowsNullValues, boolean supportsRemove, boolean supportsClear, boolean supportsIteratorRemove)1140 RowMapTests( 1141 boolean allowsNullValues, 1142 boolean supportsRemove, 1143 boolean supportsClear, 1144 boolean supportsIteratorRemove) { 1145 super(allowsNullValues, supportsRemove, supportsClear, supportsIteratorRemove); 1146 } 1147 makeTable()1148 abstract Table<String, Integer, Character> makeTable(); 1149 1150 @Override makePopulatedMap()1151 protected Map<String, Map<Integer, Character>> makePopulatedMap() { 1152 Table<String, Integer, Character> table = makeTable(); 1153 populateTable(table); 1154 return table.rowMap(); 1155 } 1156 populateTable(Table<String, Integer, Character> table)1157 void populateTable(Table<String, Integer, Character> table) { 1158 table.put("foo", 1, 'a'); 1159 table.put("bar", 1, 'b'); 1160 table.put("foo", 3, 'c'); 1161 } 1162 1163 @Override makeEmptyMap()1164 protected Map<String, Map<Integer, Character>> makeEmptyMap() { 1165 return makeTable().rowMap(); 1166 } 1167 } 1168 1169 @GwtIncompatible // TODO(hhchan): ArrayTable 1170 public static class ArrayRowMapTests extends RowMapTests { ArrayRowMapTests()1171 public ArrayRowMapTests() { 1172 super(true, false, false, false); 1173 } 1174 1175 @Override makeTable()1176 Table<String, Integer, Character> makeTable() { 1177 return ArrayTable.create(Arrays.asList("foo", "bar", "dog"), Arrays.asList(1, 2, 3)); 1178 } 1179 1180 @Override makeEmptyMap()1181 protected Map<String, Map<Integer, Character>> makeEmptyMap() { 1182 throw new UnsupportedOperationException(); 1183 } 1184 } 1185 1186 public static class HashRowMapTests extends RowMapTests { HashRowMapTests()1187 public HashRowMapTests() { 1188 super(false, true, true, true); 1189 } 1190 1191 @Override makeTable()1192 Table<String, Integer, Character> makeTable() { 1193 return HashBasedTable.create(); 1194 } 1195 } 1196 1197 public static class TreeRowMapTests extends RowMapTests { TreeRowMapTests()1198 public TreeRowMapTests() { 1199 super(false, true, true, true); 1200 } 1201 1202 @Override makeTable()1203 Table<String, Integer, Character> makeTable() { 1204 return TreeBasedTable.create(); 1205 } 1206 } 1207 1208 public static class TreeRowMapHeadMapTests extends RowMapTests { TreeRowMapHeadMapTests()1209 public TreeRowMapHeadMapTests() { 1210 super(false, true, true, true); 1211 } 1212 1213 @Override makeTable()1214 TreeBasedTable<String, Integer, Character> makeTable() { 1215 TreeBasedTable<String, Integer, Character> table = TreeBasedTable.create(); 1216 table.put("z", 1, 'a'); 1217 return table; 1218 } 1219 1220 @Override makePopulatedMap()1221 protected Map<String, Map<Integer, Character>> makePopulatedMap() { 1222 TreeBasedTable<String, Integer, Character> table = makeTable(); 1223 populateTable(table); 1224 return table.rowMap().headMap("x"); 1225 } 1226 1227 @Override makeEmptyMap()1228 protected Map<String, Map<Integer, Character>> makeEmptyMap() { 1229 return makeTable().rowMap().headMap("x"); 1230 } 1231 1232 @Override getKeyNotInPopulatedMap()1233 protected String getKeyNotInPopulatedMap() { 1234 return "z"; 1235 } 1236 } 1237 1238 public static class TreeRowMapTailMapTests extends RowMapTests { TreeRowMapTailMapTests()1239 public TreeRowMapTailMapTests() { 1240 super(false, true, true, true); 1241 } 1242 1243 @Override makeTable()1244 TreeBasedTable<String, Integer, Character> makeTable() { 1245 TreeBasedTable<String, Integer, Character> table = TreeBasedTable.create(); 1246 table.put("a", 1, 'a'); 1247 return table; 1248 } 1249 1250 @Override makePopulatedMap()1251 protected Map<String, Map<Integer, Character>> makePopulatedMap() { 1252 TreeBasedTable<String, Integer, Character> table = makeTable(); 1253 populateTable(table); 1254 return table.rowMap().tailMap("b"); 1255 } 1256 1257 @Override makeEmptyMap()1258 protected Map<String, Map<Integer, Character>> makeEmptyMap() { 1259 return makeTable().rowMap().tailMap("b"); 1260 } 1261 1262 @Override getKeyNotInPopulatedMap()1263 protected String getKeyNotInPopulatedMap() { 1264 return "a"; 1265 } 1266 } 1267 1268 public static class TreeRowMapSubMapTests extends RowMapTests { TreeRowMapSubMapTests()1269 public TreeRowMapSubMapTests() { 1270 super(false, true, true, true); 1271 } 1272 1273 @Override makeTable()1274 TreeBasedTable<String, Integer, Character> makeTable() { 1275 TreeBasedTable<String, Integer, Character> table = TreeBasedTable.create(); 1276 table.put("a", 1, 'a'); 1277 table.put("z", 1, 'a'); 1278 return table; 1279 } 1280 1281 @Override makePopulatedMap()1282 protected Map<String, Map<Integer, Character>> makePopulatedMap() { 1283 TreeBasedTable<String, Integer, Character> table = makeTable(); 1284 populateTable(table); 1285 return table.rowMap().subMap("b", "x"); 1286 } 1287 1288 @Override makeEmptyMap()1289 protected Map<String, Map<Integer, Character>> makeEmptyMap() { 1290 return makeTable().rowMap().subMap("b", "x"); 1291 } 1292 1293 @Override getKeyNotInPopulatedMap()1294 protected String getKeyNotInPopulatedMap() { 1295 return "z"; 1296 } 1297 } 1298 1299 private static final Function<String, Character> FIRST_CHARACTER = 1300 new Function<String, Character>() { 1301 @Override 1302 public Character apply(String input) { 1303 return input == null ? null : input.charAt(0); 1304 } 1305 }; 1306 1307 public static class TransformValueRowMapTests extends RowMapTests { TransformValueRowMapTests()1308 public TransformValueRowMapTests() { 1309 super(false, true, true, true); 1310 } 1311 1312 @Override makeTable()1313 Table<String, Integer, Character> makeTable() { 1314 Table<String, Integer, String> original = HashBasedTable.create(); 1315 return Tables.transformValues(original, FIRST_CHARACTER); 1316 } 1317 1318 @Override makePopulatedMap()1319 protected Map<String, Map<Integer, Character>> makePopulatedMap() { 1320 Table<String, Integer, String> table = HashBasedTable.create(); 1321 table.put("foo", 1, "apple"); 1322 table.put("bar", 1, "banana"); 1323 table.put("foo", 3, "cat"); 1324 return Tables.transformValues(table, FIRST_CHARACTER).rowMap(); 1325 } 1326 } 1327 1328 public static class UnmodifiableHashRowMapTests extends RowMapTests { UnmodifiableHashRowMapTests()1329 public UnmodifiableHashRowMapTests() { 1330 super(false, false, false, false); 1331 } 1332 1333 @Override makeTable()1334 Table<String, Integer, Character> makeTable() { 1335 Table<String, Integer, Character> original = HashBasedTable.create(); 1336 return Tables.unmodifiableTable(original); 1337 } 1338 1339 @Override makePopulatedMap()1340 protected Map<String, Map<Integer, Character>> makePopulatedMap() { 1341 Table<String, Integer, Character> table = HashBasedTable.create(); 1342 table.put("foo", 1, 'a'); 1343 table.put("bar", 1, 'b'); 1344 table.put("foo", 3, 'c'); 1345 return Tables.unmodifiableTable(table).rowMap(); 1346 } 1347 } 1348 1349 public static class UnmodifiableTreeRowMapTests extends RowMapTests { UnmodifiableTreeRowMapTests()1350 public UnmodifiableTreeRowMapTests() { 1351 super(false, false, false, false); 1352 } 1353 1354 @Override makeTable()1355 RowSortedTable<String, Integer, Character> makeTable() { 1356 RowSortedTable<String, Integer, Character> original = TreeBasedTable.create(); 1357 return Tables.unmodifiableRowSortedTable(original); 1358 } 1359 1360 @Override makePopulatedMap()1361 protected SortedMap<String, Map<Integer, Character>> makePopulatedMap() { 1362 RowSortedTable<String, Integer, Character> table = TreeBasedTable.create(); 1363 table.put("foo", 1, 'a'); 1364 table.put("bar", 1, 'b'); 1365 table.put("foo", 3, 'c'); 1366 return Tables.unmodifiableRowSortedTable(table).rowMap(); 1367 } 1368 } 1369 1370 private abstract static class ColumnMapTests extends MapMapTests { ColumnMapTests( boolean allowsNullValues, boolean supportsRemove, boolean supportsClear, boolean supportsIteratorRemove)1371 ColumnMapTests( 1372 boolean allowsNullValues, 1373 boolean supportsRemove, 1374 boolean supportsClear, 1375 boolean supportsIteratorRemove) { 1376 super(allowsNullValues, supportsRemove, supportsClear, supportsIteratorRemove); 1377 } 1378 makeTable()1379 abstract Table<Integer, String, Character> makeTable(); 1380 1381 @Override makePopulatedMap()1382 protected Map<String, Map<Integer, Character>> makePopulatedMap() { 1383 Table<Integer, String, Character> table = makeTable(); 1384 table.put(1, "foo", 'a'); 1385 table.put(1, "bar", 'b'); 1386 table.put(3, "foo", 'c'); 1387 return table.columnMap(); 1388 } 1389 1390 @Override makeEmptyMap()1391 protected Map<String, Map<Integer, Character>> makeEmptyMap() { 1392 return makeTable().columnMap(); 1393 } 1394 } 1395 1396 @GwtIncompatible // TODO(hhchan): ArrayTable 1397 public static class ArrayColumnMapTests extends ColumnMapTests { ArrayColumnMapTests()1398 public ArrayColumnMapTests() { 1399 super(true, false, false, false); 1400 } 1401 1402 @Override makeTable()1403 Table<Integer, String, Character> makeTable() { 1404 return ArrayTable.create(Arrays.asList(1, 2, 3), Arrays.asList("foo", "bar", "dog")); 1405 } 1406 1407 @Override makeEmptyMap()1408 protected Map<String, Map<Integer, Character>> makeEmptyMap() { 1409 throw new UnsupportedOperationException(); 1410 } 1411 } 1412 1413 public static class HashColumnMapTests extends ColumnMapTests { HashColumnMapTests()1414 public HashColumnMapTests() { 1415 super(false, true, true, false); 1416 } 1417 1418 @Override makeTable()1419 Table<Integer, String, Character> makeTable() { 1420 return HashBasedTable.create(); 1421 } 1422 } 1423 1424 public static class TreeColumnMapTests extends ColumnMapTests { TreeColumnMapTests()1425 public TreeColumnMapTests() { 1426 super(false, true, true, false); 1427 } 1428 1429 @Override makeTable()1430 Table<Integer, String, Character> makeTable() { 1431 return TreeBasedTable.create(); 1432 } 1433 } 1434 1435 public static class TransformValueColumnMapTests extends ColumnMapTests { TransformValueColumnMapTests()1436 public TransformValueColumnMapTests() { 1437 super(false, true, true, false); 1438 } 1439 1440 @Override makeTable()1441 Table<Integer, String, Character> makeTable() { 1442 Table<Integer, String, String> original = HashBasedTable.create(); 1443 return Tables.transformValues(original, FIRST_CHARACTER); 1444 } 1445 1446 @Override makePopulatedMap()1447 protected Map<String, Map<Integer, Character>> makePopulatedMap() { 1448 Table<Integer, String, String> table = HashBasedTable.create(); 1449 table.put(1, "foo", "apple"); 1450 table.put(1, "bar", "banana"); 1451 table.put(3, "foo", "cat"); 1452 return Tables.transformValues(table, FIRST_CHARACTER).columnMap(); 1453 } 1454 } 1455 1456 public static class UnmodifiableHashColumnMapTests extends ColumnMapTests { UnmodifiableHashColumnMapTests()1457 public UnmodifiableHashColumnMapTests() { 1458 super(false, false, false, false); 1459 } 1460 1461 @Override makeTable()1462 Table<Integer, String, Character> makeTable() { 1463 Table<Integer, String, Character> original = HashBasedTable.create(); 1464 return Tables.unmodifiableTable(original); 1465 } 1466 1467 @Override makePopulatedMap()1468 protected Map<String, Map<Integer, Character>> makePopulatedMap() { 1469 Table<Integer, String, Character> table = HashBasedTable.create(); 1470 table.put(1, "foo", 'a'); 1471 table.put(1, "bar", 'b'); 1472 table.put(3, "foo", 'c'); 1473 return Tables.unmodifiableTable(table).columnMap(); 1474 } 1475 } 1476 1477 public static class UnmodifiableTreeColumnMapTests extends ColumnMapTests { UnmodifiableTreeColumnMapTests()1478 public UnmodifiableTreeColumnMapTests() { 1479 super(false, false, false, false); 1480 } 1481 1482 @Override makeTable()1483 Table<Integer, String, Character> makeTable() { 1484 RowSortedTable<Integer, String, Character> original = TreeBasedTable.create(); 1485 return Tables.unmodifiableRowSortedTable(original); 1486 } 1487 1488 @Override makePopulatedMap()1489 protected Map<String, Map<Integer, Character>> makePopulatedMap() { 1490 RowSortedTable<Integer, String, Character> table = TreeBasedTable.create(); 1491 table.put(1, "foo", 'a'); 1492 table.put(1, "bar", 'b'); 1493 table.put(3, "foo", 'c'); 1494 return Tables.unmodifiableRowSortedTable(table).columnMap(); 1495 } 1496 } 1497 } 1498