golang.org/x/build@v0.0.0-20240506185731-218518f32b70/perf/app/compare_test.go (about) 1 // Copyright 2017 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 app 6 7 import ( 8 "context" 9 "fmt" 10 "net/http" 11 "net/http/httptest" 12 "reflect" 13 "strings" 14 "testing" 15 16 "golang.org/x/build/perfdata" 17 "golang.org/x/perf/storage/benchfmt" 18 ) 19 20 func TestResultGroup(t *testing.T) { 21 data := `key: value 22 BenchmarkName 1 ns/op 23 key: value2 24 BenchmarkName 1 ns/op` 25 var results []*benchfmt.Result 26 br := benchfmt.NewReader(strings.NewReader(data)) 27 g := &resultGroup{} 28 for br.Next() { 29 results = append(results, br.Result()) 30 g.add(br.Result()) 31 } 32 if err := br.Err(); err != nil { 33 t.Fatalf("Err() = %v, want nil", err) 34 } 35 if !reflect.DeepEqual(g.results, results) { 36 t.Errorf("g.results = %#v, want %#v", g.results, results) 37 } 38 if want := map[string]valueSet{"key": {"value": 1, "value2": 1}}; !reflect.DeepEqual(g.LabelValues, want) { 39 t.Errorf("g.LabelValues = %#v, want %#v", g.LabelValues, want) 40 } 41 groups := g.splitOn("key") 42 if len(groups) != 2 { 43 t.Fatalf("g.splitOn returned %d groups, want 2", len(groups)) 44 } 45 for i, results := range [][]*benchfmt.Result{ 46 {results[0]}, 47 {results[1]}, 48 } { 49 if !reflect.DeepEqual(groups[i].results, results) { 50 t.Errorf("groups[%d].results = %#v, want %#v", i, groups[i].results, results) 51 } 52 } 53 } 54 55 // static responses for TestCompareQuery 56 var compareQueries = map[string]string{ 57 "one": `upload: 1 58 upload-part: 1 59 label: value 60 BenchmarkOne 1 5 ns/op 61 BenchmarkTwo 1 10 ns/op`, 62 "two": `upload: 1 63 upload-part: 2 64 BenchmarkOne 1 10 ns/op 65 BenchmarkTwo 1 5 ns/op`, 66 "onetwo": `upload: 1 67 upload-part: 1 68 label: value 69 BenchmarkOne 1 5 ns/op 70 BenchmarkTwo 1 10 ns/op 71 label: 72 upload-part: 2 73 BenchmarkOne 1 10 ns/op 74 BenchmarkTwo 1 5 ns/op`, 75 } 76 77 func TestCompareQuery(t *testing.T) { 78 // TODO(quentin): This test seems too heavyweight; we are but shouldn't be also testing the perfdata client -> perfdata server interaction. 79 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 80 if err := r.ParseForm(); err != nil { 81 t.Errorf("ParseForm = %v", err) 82 } 83 q := r.Form.Get("q") 84 w.Header().Set("Content-Type", "text/plain; charset=utf-8") 85 fmt.Fprint(w, compareQueries[q]) 86 })) 87 defer ts.Close() 88 89 a := &App{StorageClient: &perfdata.Client{BaseURL: ts.URL}} 90 91 for _, q := range []string{"one vs two", "onetwo"} { 92 t.Run(q, func(t *testing.T) { 93 data := a.compareQuery(context.Background(), q) 94 if data.Error != "" { 95 t.Fatalf("compareQuery failed: %s", data.Error) 96 } 97 if have := data.Q; have != q { 98 t.Errorf("Q = %q, want %q", have, q) 99 } 100 if len(data.Groups) != 2 { 101 t.Errorf("len(Groups) = %d, want 2", len(data.Groups)) 102 } 103 if len(data.Benchstat.String()) == 0 { 104 t.Error("len(Benchstat) = 0, want >0") 105 } 106 if want := map[string]bool{"upload-part": true, "label": true}; !reflect.DeepEqual(data.Labels, want) { 107 t.Errorf("Labels = %#v, want %#v", data.Labels, want) 108 } 109 if want := (benchfmt.Labels{"upload": "1"}); !reflect.DeepEqual(data.CommonLabels, want) { 110 t.Errorf("CommonLabels = %#v, want %#v", data.CommonLabels, want) 111 } 112 }) 113 } 114 } 115 116 func TestAddToQuery(t *testing.T) { 117 tests := []struct { 118 query, add string 119 want string 120 }{ 121 {"one", "two", "two | one"}, 122 {"pre | one vs two", "three", "three pre | one vs two"}, 123 {"four", "five six", `"five six" | four`}, 124 {"seven", `extra "fun"\problem`, `"extra \"fun\"\\problem" | seven`}, 125 {"eight", `ni\"ne`, `"ni\\\"ne" | eight`}, 126 } 127 for i, test := range tests { 128 t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { 129 if got := addToQuery(test.query, test.add); got != test.want { 130 t.Errorf("addToQuery(%q, %q) = %q, want %q", test.query, test.add, got, test.want) 131 } 132 }) 133 } 134 } 135 136 func TestElideKeyValues(t *testing.T) { 137 type sb map[string]bool 138 tests := []struct { 139 content string 140 keys sb 141 want string 142 }{ 143 {"BenchmarkOne/key=1-1 1 ns/op", sb{"key": true}, "BenchmarkOne/key=*-1 1 ns/op"}, 144 {"BenchmarkOne/key=1-2 1 ns/op", sb{"other": true}, "BenchmarkOne/key=1-2 1 ns/op"}, 145 {"BenchmarkOne/key=1/key2=2-3 1 ns/op", sb{"key": true}, "BenchmarkOne/key=*/key2=2-3 1 ns/op"}, 146 {"BenchmarkOne/foo/bar-4 1 ns/op", sb{"sub1": true}, "BenchmarkOne/*/bar-4 1 ns/op"}, 147 {"BenchmarkOne/foo/bar-5 1 ns/op", sb{"gomaxprocs": true}, "BenchmarkOne/foo/bar-* 1 ns/op"}, 148 {"BenchmarkOne/foo/bar-6 1 ns/op", sb{"name": true}, "Benchmark*/foo/bar-6 1 ns/op"}, 149 } 150 for i, test := range tests { 151 t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { 152 have := elideKeyValues(test.content, test.keys) 153 if have != test.want { 154 t.Errorf("elideKeys(%q, %#v) = %q, want %q", test.content, map[string]bool(test.keys), have, test.want) 155 } 156 }) 157 } 158 }