github.com/grafana/pyroscope@v1.18.0/pkg/og/structs/transporttrie/trie_test.go (about) 1 package transporttrie 2 3 import ( 4 "bytes" 5 "fmt" 6 "hash" 7 "hash/fnv" 8 "math/rand" 9 10 . "github.com/onsi/ginkgo/v2" 11 . "github.com/onsi/gomega" 12 "github.com/sirupsen/logrus" 13 14 "github.com/grafana/pyroscope/pkg/og/util/varint" 15 ) 16 17 func randStr(l int) []byte { 18 buf := make([]byte, l) 19 for i := 0; i < l; i++ { 20 buf[i] = byte(97) + byte(rand.Uint32()%10) 21 } 22 // rand.Read(buf) 23 24 return buf 25 } 26 27 type trieHash struct { 28 w varint.Writer 29 h hash.Hash64 30 } 31 32 func newTrieHash() trieHash { 33 return trieHash{ 34 w: varint.NewWriter(), 35 h: fnv.New64a(), 36 } 37 } 38 39 func (t *trieHash) addUint64(k []byte, v uint64) { 40 _, _ = t.h.Write(k) 41 _, _ = t.w.Write(t.h, v) 42 } 43 44 func (t *trieHash) addInt(k []byte, v int) { 45 t.addUint64(k, uint64(v)) 46 } 47 48 func (t trieHash) sum() uint64 { 49 return t.h.Sum64() 50 } 51 52 var _ = Describe("trie package", func() { 53 serializationExample := []byte("\x00\x00\x01\x02ab\x00\x02\x01c\x01\x00\x01d\x02\x00") 54 Context("trie.Serialize()", func() { 55 trie := New() 56 trie.Insert([]byte("abc"), 1) 57 trie.Insert([]byte("abd"), 2) 58 logrus.Debug("trie abc abd", trie) 59 60 It("returns correct results", func() { 61 var buf bytes.Buffer 62 trie.Serialize(&buf) 63 Expect(buf.Bytes()).To(Equal(serializationExample)) 64 }) 65 66 Context("Ran 1000000 times", func() { 67 var buf1 bytes.Buffer 68 trie.Serialize(&buf1) 69 It("returns the same result", func() { 70 var buf2 bytes.Buffer 71 trie.Serialize(&buf2) 72 Expect(buf2).To(Equal(buf1)) 73 }) 74 }) 75 }) 76 77 Context("Ser/Deserialize()", func() { 78 It("returns correct results", func() { 79 for j := 0; j < 10; j++ { 80 // logrus.Debug("---") 81 trie := New() 82 // trie.Insert([]byte("acc"), []byte{1}) 83 // trie.Insert([]byte("abc"), []byte{2}) 84 // trie.Insert([]byte("abd"), []byte{3}) 85 // trie.Insert([]byte("ab"), []byte{4}) 86 for i := 0; i < 10; i++ { 87 trie.Insert(randStr(10), uint64(i)) 88 } 89 // trie.Insert([]byte("abc"), []byte{1}, true) 90 // trie.Insert([]byte("abc"), []byte{3}, true) 91 // trie.Insert([]byte("bar"), []byte{5}) 92 // trie.Insert([]byte("abd"), []byte{2}) 93 // trie.Insert([]byte("abce"), []byte{3}) 94 // trie.Insert([]byte("ab"), []byte{4}) 95 // trie.Insert([]byte("abc"), []byte{2}) 96 97 // trie.Insert([]byte("baze"), []byte{1}) 98 // trie.Insert([]byte("baz"), []byte{2}) 99 // trie.Insert([]byte("bat"), []byte{3}) 100 // trie.Insert([]byte("bata"), []byte{4}) 101 // trie.Insert([]byte("batb"), []byte{5}) 102 // trie.Insert([]byte("bad"), []byte{6}) 103 // trie.Insert([]byte("bae"), []byte{7}) 104 // trie.Insert([]byte("zyx"), []byte{1}) 105 // trie.Insert([]byte("zy"), []byte{2}) 106 // trie.Insert([]byte(""), []byte{1}) 107 // trie.Insert([]byte("a"), []byte{2}) 108 // trie.Insert([]byte("b"), []byte{3}) 109 110 // trie.Insert([]byte("1234567"), []byte{1}) 111 // trie.Insert([]byte("1234667"), []byte{2}) 112 // trie.Insert([]byte("1234767"), []byte{3}) 113 logrus.Debug("a", trie.String()) 114 strA := "" 115 trie.Iterate(func(k []byte, v uint64) { 116 strA += fmt.Sprintf("%q %d\n", k, v) 117 }) 118 logrus.Debug("strA", strA) 119 120 var buf bytes.Buffer 121 trie.Serialize(&buf) 122 123 r := bytes.NewReader(buf.Bytes()) 124 t, e := Deserialize(r) 125 strB := "" 126 t.Iterate(func(k []byte, v uint64) { 127 strB += fmt.Sprintf("%q %d\n", k, v) 128 }) 129 logrus.Debug("b", t.String()) 130 logrus.Debug("strB", strB) 131 Expect(e).To(BeNil()) 132 Expect(trie.String()).To(Equal(t.String())) 133 Expect(strA).To(Equal(strB)) 134 logrus.Debug("---/") 135 } 136 }) 137 }) 138 139 Context("IterateRaw()", func() { 140 compareWithRawIterator := func(t *Trie) { 141 h1 := newTrieHash() 142 t.Iterate(h1.addUint64) 143 var buf bytes.Buffer 144 Expect(t.Serialize(&buf)).ToNot(HaveOccurred()) 145 146 r := bytes.NewReader(buf.Bytes()) 147 h2 := newTrieHash() 148 tmpBuf := make([]byte, 0, 256) 149 Expect(IterateRaw(r, tmpBuf, h2.addInt)).ToNot(HaveOccurred()) 150 151 Expect(h2.sum()).To(Equal(h1.sum())) 152 } 153 154 It("returns correct results", func() { 155 type value struct { 156 k string 157 v uint64 158 } 159 160 values := []value{ 161 {"foo;bar;baz", 1}, 162 {"foo;bar;baz;a", 1}, 163 {"foo;bar;baz;b", 1}, 164 {"foo;bar;baz;c", 1}, 165 {"foo;bar;bar", 1}, 166 {"foo;bar;qux", 1}, 167 {"foo;bax;bar", 1}, 168 {"zoo;boo", 1}, 169 {"zoo;bao", 1}, 170 } 171 172 trie := New() 173 for _, v := range values { 174 trie.Insert([]byte(v.k), v.v) 175 } 176 177 compareWithRawIterator(trie) 178 }) 179 180 It("handles random tries properly", func() { 181 for j := 0; j < 10; j++ { 182 trie := New() 183 for i := 0; i < 10; i++ { 184 trie.Insert(randStr(10), uint64(i)) 185 } 186 187 h1 := newTrieHash() 188 trie.Iterate(h1.addUint64) 189 190 var buf bytes.Buffer 191 err := trie.Serialize(&buf) 192 Expect(err).To(BeNil()) 193 194 r := bytes.NewReader(buf.Bytes()) 195 h2 := newTrieHash() 196 err = IterateRaw(r, nil, h2.addInt) 197 Expect(err).To(BeNil()) 198 199 Expect(h2.sum()).To(Equal(h1.sum())) 200 } 201 }) 202 }) 203 204 Context("Deserialize()", func() { 205 trie := New() 206 trie.Insert([]byte("abc"), 1) 207 trie.Insert([]byte("ab"), 2) 208 logrus.Debug(trie.String()) 209 210 It("returns correct results", func() { 211 r := bytes.NewReader(serializationExample) 212 t, e := Deserialize(r) 213 logrus.Debug(t.String()) 214 Expect(e).To(BeNil()) 215 var buf bytes.Buffer 216 t.Serialize(&buf) 217 Expect(buf.Bytes()).To(Equal(serializationExample)) 218 }) 219 220 Context("Ran 1000000 times", func() { 221 var buf1 bytes.Buffer 222 trie.Serialize(&buf1) 223 It("returns the same result", func() { 224 var buf2 bytes.Buffer 225 trie.Serialize(&buf2) 226 Expect(buf2).To(Equal(buf1)) 227 }) 228 }) 229 }) 230 })