1 package shark 2 3 import org.assertj.core.api.Assertions 4 import org.junit.Test 5 import shark.LongScatterSetAssertion.Companion.assertThat 6 import shark.internal.hppc.HPPC.mixPhi 7 import shark.internal.hppc.LongScatterSet 8 9 class LongScatterSetTest { 10 new set is emptynull11 @Test fun `new set is empty`() { 12 assertThat(LongScatterSet()) 13 .isEmpty() 14 } 15 LongScatterSet#add() adds elementsnull16 @Test fun `LongScatterSet#add() adds elements`() { 17 val set = LongScatterSet() 18 19 TEST_VALUES_LIST.forEach { set.add(it) } 20 21 assertThat(set) 22 .containsExactly(TEST_VALUES_LIST) 23 } 24 += operator works as additionnull25 @Test fun `+= operator works as addition`() { 26 val set = LongScatterSet() 27 28 set += TEST_VALUE 29 30 assertThat(set) 31 .containsExactly(TEST_VALUE) 32 } 33 when adding element twice, it is only added oncenull34 @Test fun `when adding element twice, it is only added once`() { 35 val set = LongScatterSet() 36 37 set.add(TEST_VALUE) 38 set.add(TEST_VALUE) 39 40 assertThat(set) 41 .containsExactly(TEST_VALUE) 42 } 43 44 /** 45 * [LongScatterSet] calculates hash for its values using [mixPhi] function. 46 * Inevitably, there can be collisions when two different values have same hash value; 47 * [LongScatterSet] should handle such collisions properly. 48 * There are two tests that verify adding and removing operations for values with matching hash value; 49 * current test verifies that values we use in those tests actually do have matching hashes. 50 */ 11 and 14_723_950_898 have same hashnull51 @Test fun `11 and 14_723_950_898 have same hash`() { 52 Assertions.assertThat(mixPhi(11)) 53 .isEqualTo(mixPhi(14_723_950_898)) 54 } 55 elements with equal hash can be addednull56 @Test fun `elements with equal hash can be added`() { 57 val set = LongScatterSet() 58 59 set.add(SAME_MIX_PHI_1) 60 set.add(SAME_MIX_PHI_2) 61 62 assertThat(set) 63 .containsExactly(listOf(SAME_MIX_PHI_1, SAME_MIX_PHI_2)) 64 } 65 LongScatterSet#remove() removes elementsnull66 @Test fun `LongScatterSet#remove() removes elements`() { 67 val set = LongScatterSet() 68 TEST_VALUES_LIST.forEach { set.add(it) } 69 70 TEST_VALUES_LIST.forEach { set.remove(it) } 71 72 assertThat(set) 73 .isEmpty() 74 } 75 removing from empty setnull76 @Test fun `removing from empty set`() { 77 val set = LongScatterSet() 78 79 set.remove(TEST_VALUE) 80 81 assertThat(set) 82 .isEmpty() 83 } 84 elements with equal hash can be removednull85 @Test fun `elements with equal hash can be removed`() { 86 val set = LongScatterSet() 87 set.add(SAME_MIX_PHI_1) 88 set.add(SAME_MIX_PHI_2) 89 90 set.remove(SAME_MIX_PHI_2) 91 92 assertThat(set) 93 .containsExactly(SAME_MIX_PHI_1) 94 } 95 LongScatterSet#release() empties setnull96 @Test fun `LongScatterSet#release() empties set`() { 97 val set = LongScatterSet() 98 set.add(TEST_VALUE) 99 100 set.release() 101 102 assertThat(set) 103 .isEmpty() 104 } 105 106 /** 107 * Verifies that calling [LongScatterSet.ensureCapacity] after elements has been added to set 108 * does not damage the data in set 109 */ setting initial capacity after operationsnull110 @Test fun `setting initial capacity after operations`() { 111 val set = LongScatterSet() 112 set.add(TEST_VALUE) 113 114 set.ensureCapacity(TEST_CAPACITY) 115 116 assertThat(set) 117 .containsExactly(TEST_VALUE) 118 } 119 adding a lot of elements causes resizingnull120 @Test fun `adding a lot of elements causes resizing`() { 121 val set = LongScatterSet() 122 (1..100L).forEach { set.add(it) } 123 124 assertThat(set) 125 .containsExactly((1..100L).toList()) 126 } 127 128 companion object { 129 // Values SAME_MIX_PHI_1 and SAME_MIX_PHI_2 have same hash when calculated via HHPC.mixPhi() 130 const val SAME_MIX_PHI_1 = 11L 131 const val SAME_MIX_PHI_2 = 14_723_950_898L 132 val TEST_VALUES_LIST = listOf(42, 0, Long.MIN_VALUE, Long.MAX_VALUE, -1) 133 const val TEST_VALUE = 12L 134 const val TEST_CAPACITY = 10 135 } 136 } 137