1 /* 2 * Copyright (C) 2009 Google Inc. 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 org.junit.contrib.truth.Truth.ASSERT; 20 21 /** 22 * Tests common methods in {@link ImmutableTable} 23 * 24 * @author gak (at) google.com (Gregory Kick) 25 */ 26 public class ImmutableTableTest extends AbstractTableReadTest { 27 @Override protected Table<String, Integer, Character> create(Object... data) { 28 ImmutableTable.Builder<String, Integer, Character> builder = 29 ImmutableTable.builder(); 30 for (int i = 0; i < data.length; i = i + 3) { 31 builder.put((String) data[i], (Integer) data[i + 1], 32 (Character) data[i + 2]); 33 } 34 return builder.build(); 35 } 36 37 public void testBuilder() { 38 ImmutableTable.Builder<Character, Integer, String> builder = 39 new ImmutableTable.Builder<Character, Integer, String>(); 40 assertEquals(ImmutableTable.of(), builder.build()); 41 assertEquals(ImmutableTable.of('a', 1, "foo"), builder 42 .put('a', 1, "foo") 43 .build()); 44 Table<Character, Integer, String> expectedTable = HashBasedTable.create(); 45 expectedTable.put('a', 1, "foo"); 46 expectedTable.put('b', 1, "bar"); 47 expectedTable.put('a', 2, "baz"); 48 Table<Character, Integer, String> otherTable = HashBasedTable.create(); 49 otherTable.put('b', 1, "bar"); 50 otherTable.put('a', 2, "baz"); 51 assertEquals(expectedTable, builder 52 .putAll(otherTable) 53 .build()); 54 } 55 56 public void testBuilder_withImmutableCell() { 57 ImmutableTable.Builder<Character, Integer, String> builder = 58 new ImmutableTable.Builder<Character, Integer, String>(); 59 assertEquals(ImmutableTable.of('a', 1, "foo"), builder 60 .put(Tables.immutableCell('a', 1, "foo")) 61 .build()); 62 } 63 64 public void testBuilder_withImmutableCellAndNullContents() { 65 ImmutableTable.Builder<Character, Integer, String> builder = 66 new ImmutableTable.Builder<Character, Integer, String>(); 67 try { 68 builder.put(Tables.immutableCell((Character) null, 1, "foo")); 69 fail(); 70 } catch (NullPointerException e) { 71 // success 72 } 73 try { 74 builder.put(Tables.immutableCell('a', (Integer) null, "foo")); 75 fail(); 76 } catch (NullPointerException e) { 77 // success 78 } 79 try { 80 builder.put(Tables.immutableCell('a', 1, (String) null)); 81 fail(); 82 } catch (NullPointerException e) { 83 // success 84 } 85 } 86 87 private static class StringHolder { 88 String string; 89 } 90 91 public void testBuilder_withMutableCell() { 92 ImmutableTable.Builder<Character, Integer, String> builder = 93 new ImmutableTable.Builder<Character, Integer, String>(); 94 95 final StringHolder holder = new StringHolder(); 96 holder.string = "foo"; 97 Table.Cell<Character, Integer, String> mutableCell = 98 new Tables.AbstractCell<Character, Integer, String>() { 99 @Override public Character getRowKey() { 100 return 'K'; 101 } 102 @Override public Integer getColumnKey() { 103 return 42; 104 } 105 @Override public String getValue() { 106 return holder.string; 107 } 108 }; 109 110 // Add the mutable cell to the builder 111 builder.put(mutableCell); 112 113 // Mutate the value 114 holder.string = "bar"; 115 116 // Make sure it uses the original value. 117 assertEquals(ImmutableTable.of('K', 42, "foo"), builder.build()); 118 } 119 120 public void testBuilder_noDuplicates() { 121 ImmutableTable.Builder<Character, Integer, String> builder = 122 new ImmutableTable.Builder<Character, Integer, String>() 123 .put('a', 1, "foo") 124 .put('a', 1, "bar"); 125 try { 126 builder.build(); 127 fail(); 128 } catch (IllegalArgumentException e) { 129 // success 130 } 131 } 132 133 public void testBuilder_noNulls() { 134 ImmutableTable.Builder<Character, Integer, String> builder = 135 new ImmutableTable.Builder<Character, Integer, String>(); 136 try { 137 builder.put(null, 1, "foo"); 138 fail(); 139 } catch (NullPointerException e) { 140 // success 141 } 142 try { 143 builder.put('a', null, "foo"); 144 fail(); 145 } catch (NullPointerException e) { 146 // success 147 } 148 try { 149 builder.put('a', 1, null); 150 fail(); 151 } catch (NullPointerException e) { 152 // success 153 } 154 } 155 156 private static <R, C, V> void validateTableCopies(Table<R, C, V> original) { 157 Table<R, C, V> copy = ImmutableTable.copyOf(original); 158 assertEquals(original, copy); 159 validateViewOrdering(original, copy); 160 161 Table<R, C, V> built 162 = ImmutableTable.<R, C, V>builder().putAll(original).build(); 163 assertEquals(original, built); 164 validateViewOrdering(original, built); 165 } 166 167 private static <R, C, V> void validateViewOrdering( 168 Table<R, C, V> original, Table<R, C, V> copy) { 169 assertTrue(Iterables.elementsEqual(original.cellSet(), copy.cellSet())); 170 assertTrue(Iterables.elementsEqual(original.rowKeySet(), copy.rowKeySet())); 171 assertTrue(Iterables.elementsEqual(original.values(), copy.values())); 172 } 173 174 public void testCopyOf() { 175 Table<Character, Integer, String> table = TreeBasedTable.create(); 176 validateTableCopies(table); 177 table.put('b', 2, "foo"); 178 validateTableCopies(table); 179 table.put('b', 1, "bar"); 180 table.put('a', 2, "baz"); 181 validateTableCopies(table); 182 // Even though rowKeySet, columnKeySet, and cellSet have the same 183 // iteration ordering, row has an inconsistent ordering. 184 ASSERT.that(table.row('b').keySet()).hasContentsInOrder(1, 2); 185 ASSERT.that(ImmutableTable.copyOf(table).row('b').keySet()) 186 .hasContentsInOrder(2, 1); 187 } 188 189 public void testCopyOfSparse() { 190 Table<Character, Integer, String> table = TreeBasedTable.create(); 191 table.put('x', 2, "foo"); 192 table.put('r', 1, "bar"); 193 table.put('c', 3, "baz"); 194 table.put('b', 7, "cat"); 195 table.put('e', 5, "dog"); 196 table.put('c', 0, "axe"); 197 table.put('e', 3, "tub"); 198 table.put('r', 4, "foo"); 199 table.put('x', 5, "bar"); 200 validateTableCopies(table); 201 } 202 203 public void testCopyOfDense() { 204 Table<Character, Integer, String> table = TreeBasedTable.create(); 205 table.put('c', 3, "foo"); 206 table.put('c', 2, "bar"); 207 table.put('c', 1, "baz"); 208 table.put('b', 3, "cat"); 209 table.put('b', 1, "dog"); 210 table.put('a', 3, "foo"); 211 table.put('a', 2, "bar"); 212 table.put('a', 1, "baz"); 213 validateTableCopies(table); 214 } 215 216 public void testBuilder_orderRowsAndColumnsBy_putAll() { 217 Table<Character, Integer, String> table = HashBasedTable.create(); 218 table.put('b', 2, "foo"); 219 table.put('b', 1, "bar"); 220 table.put('a', 2, "baz"); 221 ImmutableTable.Builder<Character, Integer, String> builder 222 = ImmutableTable.builder(); 223 Table<Character, Integer, String> copy 224 = builder.orderRowsBy(Ordering.natural()) 225 .orderColumnsBy(Ordering.natural()) 226 .putAll(table).build(); 227 ASSERT.that(copy.rowKeySet()).hasContentsInOrder('a', 'b'); 228 ASSERT.that(copy.columnKeySet()).hasContentsInOrder(1, 2); 229 ASSERT.that(copy.values()).hasContentsInOrder("baz", "bar", "foo"); 230 ASSERT.that(copy.row('b').keySet()).hasContentsInOrder(1, 2); 231 } 232 233 public void testBuilder_orderRowsAndColumnsBy_sparse() { 234 ImmutableTable.Builder<Character, Integer, String> builder 235 = ImmutableTable.builder(); 236 builder.orderRowsBy(Ordering.natural()); 237 builder.orderColumnsBy(Ordering.natural()); 238 builder.put('x', 2, "foo"); 239 builder.put('r', 1, "bar"); 240 builder.put('c', 3, "baz"); 241 builder.put('b', 7, "cat"); 242 builder.put('e', 5, "dog"); 243 builder.put('c', 0, "axe"); 244 builder.put('e', 3, "tub"); 245 builder.put('r', 4, "foo"); 246 builder.put('x', 5, "bar"); 247 Table<Character, Integer, String> table = builder.build(); 248 ASSERT.that(table.rowKeySet()).hasContentsInOrder('b', 'c', 'e', 'r', 'x'); 249 ASSERT.that(table.columnKeySet()).hasContentsInOrder(0, 1, 2, 3, 4, 5, 7); 250 ASSERT.that(table.values()).hasContentsInOrder("cat", "axe", "baz", "tub", 251 "dog", "bar", "foo", "foo", "bar"); 252 ASSERT.that(table.row('c').keySet()).hasContentsInOrder(0, 3); 253 ASSERT.that(table.column(5).keySet()).hasContentsInOrder('e', 'x'); 254 } 255 256 public void testBuilder_orderRowsAndColumnsBy_dense() { 257 ImmutableTable.Builder<Character, Integer, String> builder 258 = ImmutableTable.builder(); 259 builder.orderRowsBy(Ordering.natural()); 260 builder.orderColumnsBy(Ordering.natural()); 261 builder.put('c', 3, "foo"); 262 builder.put('c', 2, "bar"); 263 builder.put('c', 1, "baz"); 264 builder.put('b', 3, "cat"); 265 builder.put('b', 1, "dog"); 266 builder.put('a', 3, "foo"); 267 builder.put('a', 2, "bar"); 268 builder.put('a', 1, "baz"); 269 Table<Character, Integer, String> table = builder.build(); 270 ASSERT.that(table.rowKeySet()).hasContentsInOrder('a', 'b', 'c'); 271 ASSERT.that(table.columnKeySet()).hasContentsInOrder(1, 2, 3); 272 ASSERT.that(table.values()).hasContentsInOrder("baz", "bar", "foo", "dog", 273 "cat", "baz", "bar", "foo"); 274 ASSERT.that(table.row('c').keySet()).hasContentsInOrder(1, 2, 3); 275 ASSERT.that(table.column(1).keySet()).hasContentsInOrder('a', 'b', 'c'); 276 } 277 278 public void testBuilder_orderRowsBy_sparse() { 279 ImmutableTable.Builder<Character, Integer, String> builder 280 = ImmutableTable.builder(); 281 builder.orderRowsBy(Ordering.natural()); 282 builder.put('x', 2, "foo"); 283 builder.put('r', 1, "bar"); 284 builder.put('c', 3, "baz"); 285 builder.put('b', 7, "cat"); 286 builder.put('e', 5, "dog"); 287 builder.put('c', 0, "axe"); 288 builder.put('e', 3, "tub"); 289 builder.put('r', 4, "foo"); 290 builder.put('x', 5, "bar"); 291 Table<Character, Integer, String> table = builder.build(); 292 ASSERT.that(table.rowKeySet()).hasContentsInOrder('b', 'c', 'e', 'r', 'x'); 293 ASSERT.that(table.column(5).keySet()).hasContentsInOrder('e', 'x'); 294 } 295 296 public void testBuilder_orderRowsBy_dense() { 297 ImmutableTable.Builder<Character, Integer, String> builder 298 = ImmutableTable.builder(); 299 builder.orderRowsBy(Ordering.natural()); 300 builder.put('c', 3, "foo"); 301 builder.put('c', 2, "bar"); 302 builder.put('c', 1, "baz"); 303 builder.put('b', 3, "cat"); 304 builder.put('b', 1, "dog"); 305 builder.put('a', 3, "foo"); 306 builder.put('a', 2, "bar"); 307 builder.put('a', 1, "baz"); 308 Table<Character, Integer, String> table = builder.build(); 309 ASSERT.that(table.rowKeySet()).hasContentsInOrder('a', 'b', 'c'); 310 ASSERT.that(table.column(1).keySet()).hasContentsInOrder('a', 'b', 'c'); 311 } 312 313 public void testBuilder_orderColumnsBy_sparse() { 314 ImmutableTable.Builder<Character, Integer, String> builder 315 = ImmutableTable.builder(); 316 builder.orderColumnsBy(Ordering.natural()); 317 builder.put('x', 2, "foo"); 318 builder.put('r', 1, "bar"); 319 builder.put('c', 3, "baz"); 320 builder.put('b', 7, "cat"); 321 builder.put('e', 5, "dog"); 322 builder.put('c', 0, "axe"); 323 builder.put('e', 3, "tub"); 324 builder.put('r', 4, "foo"); 325 builder.put('x', 5, "bar"); 326 Table<Character, Integer, String> table = builder.build(); 327 ASSERT.that(table.columnKeySet()).hasContentsInOrder(0, 1, 2, 3, 4, 5, 7); 328 ASSERT.that(table.row('c').keySet()).hasContentsInOrder(0, 3); 329 } 330 331 public void testBuilder_orderColumnsBy_dense() { 332 ImmutableTable.Builder<Character, Integer, String> builder 333 = ImmutableTable.builder(); 334 builder.orderColumnsBy(Ordering.natural()); 335 builder.put('c', 3, "foo"); 336 builder.put('c', 2, "bar"); 337 builder.put('c', 1, "baz"); 338 builder.put('b', 3, "cat"); 339 builder.put('b', 1, "dog"); 340 builder.put('a', 3, "foo"); 341 builder.put('a', 2, "bar"); 342 builder.put('a', 1, "baz"); 343 Table<Character, Integer, String> table = builder.build(); 344 ASSERT.that(table.columnKeySet()).hasContentsInOrder(1, 2, 3); 345 ASSERT.that(table.row('c').keySet()).hasContentsInOrder(1, 2, 3); 346 } 347 } 348