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  }