blob: ed4e3e59dc8bdc6090ece75a6650d6110880fb61 [file] [log] [blame]
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package benchproc
import (
"fmt"
"strings"
"testing"
)
func checkKeyHeader(t *testing.T, tree *KeyHeader, want string) {
t.Helper()
got := renderKeyHeader(tree)
if got != want {
t.Errorf("want %s\ngot %s", want, got)
}
// Check the structure of the tree.
prevEnd := make([]int, len(tree.Levels))
var walk func(int, *KeyHeaderNode)
walk = func(level int, n *KeyHeaderNode) {
if n.Field != level {
t.Errorf("want level %d, got %d", level, n.Field)
}
if n.Start != prevEnd[level] {
t.Errorf("want start %d, got %d", prevEnd[level], n.Start)
}
prevEnd[level] = n.Start + n.Len
for _, sub := range n.Children {
walk(level+1, sub)
}
}
for _, n := range tree.Top {
walk(0, n)
}
// Check that we walked the full span of keys on each level.
for level, width := range prevEnd {
if width != len(tree.Keys) {
t.Errorf("want width %d, got %d at level %d", len(tree.Keys), width, level)
}
}
}
func renderKeyHeader(t *KeyHeader) string {
buf := new(strings.Builder)
var walk func([]*KeyHeaderNode)
walk = func(ns []*KeyHeaderNode) {
for _, n := range ns {
fmt.Fprintf(buf, "\n%s%s:%s", strings.Repeat("\t", n.Field), t.Levels[n.Field], n.Value)
walk(n.Children)
}
}
walk(t.Top)
return buf.String()
}
func TestKeyHeader(t *testing.T) {
// Test basic merging.
t.Run("basic", func(t *testing.T) {
s, _ := mustParse(t, ".config")
c1 := p(t, s, "", "a", "a1", "b", "b1")
c2 := p(t, s, "", "a", "a1", "b", "b2")
tree := NewKeyHeader([]Key{c1, c2})
checkKeyHeader(t, tree, `
a:a1
b:b1
b:b2`)
})
// Test that higher level differences prevent lower levels
// from being merged, even if the lower levels match.
t.Run("noMerge", func(t *testing.T) {
s, _ := mustParse(t, ".config")
c1 := p(t, s, "", "a", "a1", "b", "b1")
c2 := p(t, s, "", "a", "a2", "b", "b1")
tree := NewKeyHeader([]Key{c1, c2})
checkKeyHeader(t, tree, `
a:a1
b:b1
a:a2
b:b1`)
})
// Test mismatched tuple lengths.
t.Run("missingValues", func(t *testing.T) {
s, _ := mustParse(t, ".config")
c1 := p(t, s, "", "a", "a1")
c2 := p(t, s, "", "a", "a1", "b", "b1")
c3 := p(t, s, "", "a", "a1", "b", "b1", "c", "c1")
tree := NewKeyHeader([]Key{c1, c2, c3})
checkKeyHeader(t, tree, `
a:a1
b:
c:
b:b1
c:
c:c1`)
})
// Test no Keys.
t.Run("none", func(t *testing.T) {
tree := NewKeyHeader([]Key{})
if len(tree.Top) != 0 {
t.Fatalf("wanted empty tree, got %v", tree)
}
})
// Test empty Keys.
t.Run("empty", func(t *testing.T) {
s, _ := mustParse(t, ".config")
c1 := p(t, s, "")
c2 := p(t, s, "")
tree := NewKeyHeader([]Key{c1, c2})
checkKeyHeader(t, tree, "")
})
}