github.com/philpearl/symboltab@v1.1.4/symboltab_test.go (about) 1 package symboltab 2 3 import ( 4 "fmt" 5 "runtime" 6 "strconv" 7 "testing" 8 "time" 9 10 "github.com/stretchr/testify/assert" 11 ) 12 13 func TestBasic(t *testing.T) { 14 st := New(16) 15 16 assertStringToSequence := func(seq int32, existing bool, val string) { 17 t.Helper() 18 seqa, existinga := st.StringToSequence(val, true) 19 assert.Equal(t, existing, existinga) 20 if existinga { 21 assert.Equal(t, seq, seqa) 22 } 23 } 24 25 assert.Zero(t, st.SymbolSize()) 26 27 assertStringToSequence(1, false, "a1") 28 assertStringToSequence(2, false, "a2") 29 assertStringToSequence(3, false, "a3") 30 assertStringToSequence(2, true, "a2") 31 assertStringToSequence(3, true, "a3") 32 33 assert.Equal(t, 1<<18, st.SymbolSize()) 34 35 assert.Equal(t, "a1", st.SequenceToString(1)) 36 assert.Equal(t, "a2", st.SequenceToString(2)) 37 assert.Equal(t, "a3", st.SequenceToString(3)) 38 } 39 40 func TestGrowth(t *testing.T) { 41 st := New(16) 42 43 for i := 0; i < 10000; i++ { 44 seq, found := st.StringToSequence(strconv.Itoa(i), true) 45 assert.False(t, found) 46 assert.Equal(t, int32(i+1), seq) 47 } 48 49 for i := 0; i < 10000; i++ { 50 seq, found := st.StringToSequence(strconv.Itoa(i), true) 51 assert.True(t, found) 52 assert.Equal(t, int32(i+1), seq) 53 } 54 55 for i := 0; i < 10000; i++ { 56 str := st.SequenceToString(int32(i + 1)) 57 assert.Equal(t, strconv.Itoa(i), str) 58 } 59 } 60 61 func TestGrowth2(t *testing.T) { 62 st := New(16) 63 64 for i := 0; i < 10000; i++ { 65 seq, found := st.StringToSequence(strconv.Itoa(i), true) 66 assert.False(t, found) 67 assert.Equal(t, int32(i+1), seq) 68 69 seq, found = st.StringToSequence(strconv.Itoa(i), true) 70 assert.True(t, found) 71 assert.Equal(t, int32(i+1), seq) 72 } 73 } 74 75 func TestAddNew(t *testing.T) { 76 st := New(16) 77 // Won't add entry if asked not to 78 seq, existing := st.StringToSequence("hat", false) 79 assert.False(t, existing) 80 assert.Equal(t, int32(0), seq) 81 82 seq, existing = st.StringToSequence("hat", true) 83 assert.False(t, existing) 84 assert.Equal(t, int32(1), seq) 85 86 // Can find existing entry if not asked to add new 87 seq, existing = st.StringToSequence("hat", false) 88 assert.True(t, existing) 89 assert.Equal(t, int32(1), seq) 90 } 91 92 func TestLowGC(t *testing.T) { 93 st := New(16) 94 for i := 0; i < 1E7; i++ { 95 st.StringToSequence(strconv.Itoa(i), true) 96 } 97 runtime.GC() 98 start := time.Now() 99 runtime.GC() 100 assert.True(t, time.Since(start) < time.Millisecond*5) 101 102 runtime.KeepAlive(st) 103 } 104 105 func BenchmarkSymbolTab(b *testing.B) { 106 symbols := make([]string, b.N) 107 for i := range symbols { 108 symbols[i] = strconv.Itoa(i) 109 } 110 111 b.ReportAllocs() 112 b.ResetTimer() 113 st := New(b.N) 114 for _, sym := range symbols { 115 st.StringToSequence(sym, true) 116 } 117 118 if symbols[0] != st.SequenceToString(1) { 119 b.Errorf("first symbol doesn't match - get %s", st.SequenceToString(1)) 120 } 121 } 122 123 func BenchmarkSequenceToString(b *testing.B) { 124 st := New(b.N) 125 for i := 0; i < b.N; i++ { 126 st.StringToSequence(strconv.Itoa(i), true) 127 } 128 129 b.ReportAllocs() 130 b.ResetTimer() 131 132 var str string 133 for i := 1; i <= b.N; i++ { 134 str = st.SequenceToString(int32(i)) 135 } 136 137 if str != strconv.Itoa(b.N-1) { 138 b.Errorf("last symbol doesn't match - get %s", str) 139 } 140 } 141 142 func BenchmarkExisting(b *testing.B) { 143 st := New(b.N) 144 values := make([]string, b.N) 145 for i := range values { 146 values[i] = strconv.Itoa(i) 147 } 148 149 for _, val := range values { 150 st.StringToSequence(val, true) 151 } 152 153 b.ReportAllocs() 154 b.ResetTimer() 155 156 var seq int32 157 for _, val := range values { 158 seq, _ = st.StringToSequence(val, false) 159 } 160 161 if st.SequenceToString(seq) != strconv.Itoa(b.N-1) { 162 b.Errorf("last symbol doesn't match - get %s", st.SequenceToString(seq)) 163 } 164 } 165 166 func BenchmarkMiss(b *testing.B) { 167 st := New(b.N) 168 values := make([]string, b.N) 169 for i := range values { 170 values[i] = strconv.Itoa(i) 171 } 172 173 b.ReportAllocs() 174 b.ResetTimer() 175 176 for _, val := range values { 177 _, found := st.StringToSequence(val, false) 178 if found { 179 b.Errorf("found value %s", val) 180 } 181 } 182 } 183 184 func ExampleSymbolTab() { 185 st := SymbolTab{} 186 seq, found := st.StringToSequence("10293-ahdb-28383-555", true) 187 fmt.Println(found) 188 fmt.Println(st.SequenceToString(seq)) 189 // Output: false 190 // 10293-ahdb-28383-555 191 } 192 193 func BenchmarkMakeBigSlice(b *testing.B) { 194 for i := 0; i < b.N; i++ { 195 sl := make([]int32, 1e8) 196 runtime.KeepAlive(sl) 197 } 198 }