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  })