github.com/jgbaldwinbrown/perf@v0.1.1/benchproc/keyheader_test.go (about) 1 // Copyright 2022 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package benchproc 6 7 import ( 8 "fmt" 9 "strings" 10 "testing" 11 ) 12 13 func checkKeyHeader(t *testing.T, tree *KeyHeader, want string) { 14 t.Helper() 15 got := renderKeyHeader(tree) 16 if got != want { 17 t.Errorf("want %s\ngot %s", want, got) 18 } 19 20 // Check the structure of the tree. 21 prevEnd := make([]int, len(tree.Levels)) 22 var walk func(int, *KeyHeaderNode) 23 walk = func(level int, n *KeyHeaderNode) { 24 if n.Field != level { 25 t.Errorf("want level %d, got %d", level, n.Field) 26 } 27 if n.Start != prevEnd[level] { 28 t.Errorf("want start %d, got %d", prevEnd[level], n.Start) 29 } 30 prevEnd[level] = n.Start + n.Len 31 for _, sub := range n.Children { 32 walk(level+1, sub) 33 } 34 } 35 for _, n := range tree.Top { 36 walk(0, n) 37 } 38 // Check that we walked the full span of keys on each level. 39 for level, width := range prevEnd { 40 if width != len(tree.Keys) { 41 t.Errorf("want width %d, got %d at level %d", len(tree.Keys), width, level) 42 } 43 } 44 } 45 46 func renderKeyHeader(t *KeyHeader) string { 47 buf := new(strings.Builder) 48 var walk func([]*KeyHeaderNode) 49 walk = func(ns []*KeyHeaderNode) { 50 for _, n := range ns { 51 fmt.Fprintf(buf, "\n%s%s:%s", strings.Repeat("\t", n.Field), t.Levels[n.Field], n.Value) 52 walk(n.Children) 53 } 54 } 55 walk(t.Top) 56 return buf.String() 57 } 58 59 func TestKeyHeader(t *testing.T) { 60 // Test basic merging. 61 t.Run("basic", func(t *testing.T) { 62 s, _ := mustParse(t, ".config") 63 c1 := p(t, s, "", "a", "a1", "b", "b1") 64 c2 := p(t, s, "", "a", "a1", "b", "b2") 65 tree := NewKeyHeader([]Key{c1, c2}) 66 checkKeyHeader(t, tree, ` 67 a:a1 68 b:b1 69 b:b2`) 70 }) 71 72 // Test that higher level differences prevent lower levels 73 // from being merged, even if the lower levels match. 74 t.Run("noMerge", func(t *testing.T) { 75 s, _ := mustParse(t, ".config") 76 c1 := p(t, s, "", "a", "a1", "b", "b1") 77 c2 := p(t, s, "", "a", "a2", "b", "b1") 78 tree := NewKeyHeader([]Key{c1, c2}) 79 checkKeyHeader(t, tree, ` 80 a:a1 81 b:b1 82 a:a2 83 b:b1`) 84 }) 85 86 // Test mismatched tuple lengths. 87 t.Run("missingValues", func(t *testing.T) { 88 s, _ := mustParse(t, ".config") 89 c1 := p(t, s, "", "a", "a1") 90 c2 := p(t, s, "", "a", "a1", "b", "b1") 91 c3 := p(t, s, "", "a", "a1", "b", "b1", "c", "c1") 92 tree := NewKeyHeader([]Key{c1, c2, c3}) 93 checkKeyHeader(t, tree, ` 94 a:a1 95 b: 96 c: 97 b:b1 98 c: 99 c:c1`) 100 }) 101 102 // Test no Keys. 103 t.Run("none", func(t *testing.T) { 104 tree := NewKeyHeader([]Key{}) 105 if len(tree.Top) != 0 { 106 t.Fatalf("wanted empty tree, got %v", tree) 107 } 108 }) 109 110 // Test empty Keys. 111 t.Run("empty", func(t *testing.T) { 112 s, _ := mustParse(t, ".config") 113 c1 := p(t, s, "") 114 c2 := p(t, s, "") 115 tree := NewKeyHeader([]Key{c1, c2}) 116 checkKeyHeader(t, tree, "") 117 }) 118 }