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  }