Files
metrics/app/vmselect/promql/parse_cache_test.go

130 lines
3.3 KiB
Go

package promql
import (
"fmt"
"testing"
"github.com/VictoriaMetrics/metricsql"
)
func testGetParseCacheValue(q string) *parseCacheValue {
e, err := metricsql.Parse(q)
return &parseCacheValue{
e: e,
err: err,
}
}
func testGenerateQueries(items int) []string {
queries := make([]string, items)
for i := range items {
queries[i] = fmt.Sprintf(`node_time_seconds{instance="node%d", job="job%d"}`, i, i)
}
return queries
}
func TestParseCache(t *testing.T) {
pc := newParseCache()
if pc.len() != 0 || pc.misses() != 0 || pc.requests() != 0 {
t.Errorf("unexpected pc.Len()=%d, pc.Misses()=%d, pc.Requests()=%d; expected all to be zero.", pc.len(), pc.misses(), pc.requests())
}
q1 := `foo{bar="baz"}`
v1 := testGetParseCacheValue(q1)
q2 := `foo1{bar1="baz1"}`
v2 := testGetParseCacheValue(q2)
pc.put(q1, v1)
if pc.len() != 1 {
t.Errorf("unexpected value obtained; got %d; want %d", pc.len(), 1)
}
if res := pc.get(q2); res != nil {
t.Errorf("unexpected non-empty value obtained from cache: %d ", res)
}
if pc.len() != 1 {
t.Errorf("unexpected value obtained; got %d; want %d", pc.len(), 1)
}
if miss := pc.misses(); miss != 1 {
t.Errorf("unexpected value obtained; got %d; want %d", miss, 1)
}
if req := pc.requests(); req != 1 {
t.Errorf("unexpected value obtained; got %d; want %d", req, 1)
}
pc.put(q2, v2)
if pc.len() != 2 {
t.Errorf("unexpected value obtained; got %d; want %d", pc.len(), 2)
}
if res := pc.get(q1); res != v1 {
t.Errorf("unexpected value obtained; got %v; want %v", res, v1)
}
if res := pc.get(q2); res != v2 {
t.Errorf("unexpected value obtained; got %v; want %v", res, v2)
}
pc.put(q2, v2)
if pc.len() != 2 {
t.Errorf("unexpected value obtained; got %d; want %d", pc.len(), 2)
}
if miss := pc.misses(); miss != 1 {
t.Errorf("unexpected value obtained; got %d; want %d", miss, 1)
}
if req := pc.requests(); req != 3 {
t.Errorf("unexpected value obtained; got %d; want %d", req, 3)
}
if res := pc.get(q2); res != v2 {
t.Errorf("unexpected value obtained; got %v; want %v", res, v2)
}
if pc.len() != 2 {
t.Errorf("unexpected value obtained; got %d; want %d", pc.len(), 2)
}
if miss := pc.misses(); miss != 1 {
t.Errorf("unexpected value obtained; got %d; want %d", miss, 1)
}
if req := pc.requests(); req != 4 {
t.Errorf("unexpected value obtained; got %d; want %d", req, 4)
}
}
func TestParseCacheBucketOverflow(t *testing.T) {
b := newParseBucket()
var expectedLen uint64
// +2 for overflow and clean up
queries := testGenerateQueries(parseBucketMaxLen + 2)
// Same value for all keys
v := testGetParseCacheValue(queries[0])
// Fill bucket
for i := range parseBucketMaxLen {
b.put(queries[i], v)
}
expectedLen = uint64(parseBucketMaxLen)
if b.len() != expectedLen {
t.Errorf("unexpected value obtained; got %v; want %v", b.len(), expectedLen)
}
// Overflow bucket
expectedLen = uint64(parseBucketMaxLen + 1)
b.put(queries[parseBucketMaxLen], v)
if b.len() != uint64(expectedLen) {
t.Errorf("unexpected value obtained; got %v; want %v", b.len(), expectedLen)
}
// Clean up;
oldLen := b.len()
overflow := int(float64(oldLen) * parseBucketFreePercent)
expectedLen = oldLen - uint64(overflow) + 1 // +1 for new entry
b.put(queries[parseBucketMaxLen+1], v)
if b.len() != expectedLen {
t.Errorf("unexpected value obtained; got %v; want %v", b.len(), expectedLen)
}
}