github.com/grafana/pyroscope@v1.18.0/pkg/phlaredb/symdb/rewriter_test.go (about)

     1  package symdb
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/stretchr/testify/assert"
     7  )
     8  
     9  func Test_lookupTable(t *testing.T) {
    10  	// Given the source data set.
    11  	// Copy arbitrary subsets of items from src to dst.
    12  	var dst []string
    13  	src := []string{
    14  		"zero",
    15  		"one",
    16  		"two",
    17  		"three",
    18  		"four",
    19  		"five",
    20  		"six",
    21  		"seven",
    22  	}
    23  
    24  	type testCase struct {
    25  		description string
    26  		input       []uint32
    27  		expected    []string
    28  	}
    29  
    30  	testCases := []testCase{
    31  		{
    32  			description: "empty table",
    33  			input:       []uint32{5, 0, 3, 1, 2, 2, 4},
    34  			expected:    []string{"five", "zero", "three", "one", "two", "two", "four"},
    35  		},
    36  		{
    37  			description: "no new values",
    38  			input:       []uint32{2, 1, 2, 3},
    39  			expected:    []string{"two", "one", "two", "three"},
    40  		},
    41  		{
    42  			description: "new value mixed",
    43  			input:       []uint32{2, 1, 6, 2, 3},
    44  			expected:    []string{"two", "one", "six", "two", "three"},
    45  		},
    46  	}
    47  
    48  	// Try to lookup values in src lazily.
    49  	// Table size must be greater or equal
    50  	// to the source data set.
    51  	l := newLookupTable[string](10)
    52  
    53  	populate := func(t *testing.T, x []uint32) {
    54  		for i, v := range x {
    55  			x[i] = l.tryLookup(v)
    56  		}
    57  		// Resolve unknown yet values.
    58  		// Mind the order and deduplication.
    59  		p := -1
    60  		for it := l.iter(); it.Err() == nil && it.Next(); {
    61  			m := int(it.At())
    62  			if m <= p {
    63  				t.Fatal("iterator order invalid")
    64  			}
    65  			p = m
    66  			it.setValue(src[m])
    67  		}
    68  	}
    69  
    70  	resolveAppend := func() {
    71  		// Populate dst with the newly resolved values.
    72  		// Note that order in dst does not have to match src.
    73  		for i, v := range l.values {
    74  			l.storeResolved(i, uint32(len(dst)))
    75  			dst = append(dst, v)
    76  		}
    77  	}
    78  
    79  	resolve := func(x []uint32) []string {
    80  		// Lookup resolved values.
    81  		var resolved []string
    82  		for _, v := range x {
    83  			resolved = append(resolved, dst[l.lookupResolved(v)])
    84  		}
    85  		return resolved
    86  	}
    87  
    88  	for _, tc := range testCases {
    89  		tc := tc
    90  		t.Run(tc.description, func(t *testing.T) {
    91  			l.reset()
    92  			populate(t, tc.input)
    93  			resolveAppend()
    94  			assert.Equal(t, tc.expected, resolve(tc.input))
    95  		})
    96  	}
    97  
    98  	assert.Len(t, dst, 7)
    99  	assert.NotContains(t, dst, "seven")
   100  }