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