golang.org/toolchain@v0.0.1-go1.9rc2.windows-amd64/src/cmd/vendor/github.com/google/pprof/internal/graph/dotgraph_test.go (about) 1 // Copyright 2014 Google Inc. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package graph 16 17 import ( 18 "bytes" 19 "fmt" 20 "io/ioutil" 21 "reflect" 22 "strconv" 23 "strings" 24 "testing" 25 26 "github.com/google/pprof/internal/proftest" 27 ) 28 29 const path = "testdata/" 30 31 func TestComposeWithStandardGraph(t *testing.T) { 32 g := baseGraph() 33 a, c := baseAttrsAndConfig() 34 35 var buf bytes.Buffer 36 ComposeDot(&buf, g, a, c) 37 38 want, err := ioutil.ReadFile(path + "compose1.dot") 39 if err != nil { 40 t.Fatalf("error reading test file: %v", err) 41 } 42 43 compareGraphs(t, buf.Bytes(), want) 44 } 45 46 func TestComposeWithNodeAttributesAndZeroFlat(t *testing.T) { 47 g := baseGraph() 48 a, c := baseAttrsAndConfig() 49 50 // Set NodeAttributes for Node 1. 51 a.Nodes[g.Nodes[0]] = &DotNodeAttributes{ 52 Shape: "folder", 53 Bold: true, 54 Peripheries: 2, 55 URL: "www.google.com", 56 Formatter: func(ni *NodeInfo) string { 57 return strings.ToUpper(ni.Name) 58 }, 59 } 60 61 // Set Flat value to zero on Node 2. 62 g.Nodes[1].Flat = 0 63 64 var buf bytes.Buffer 65 ComposeDot(&buf, g, a, c) 66 67 want, err := ioutil.ReadFile(path + "compose2.dot") 68 if err != nil { 69 t.Fatalf("error reading test file: %v", err) 70 } 71 72 compareGraphs(t, buf.Bytes(), want) 73 } 74 75 func TestComposeWithTagsAndResidualEdge(t *testing.T) { 76 g := baseGraph() 77 a, c := baseAttrsAndConfig() 78 79 // Add tags to Node 1. 80 g.Nodes[0].LabelTags["a"] = &Tag{ 81 Name: "tag1", 82 Cum: 10, 83 Flat: 10, 84 } 85 g.Nodes[0].NumericTags[""] = TagMap{ 86 "b": &Tag{ 87 Name: "tag2", 88 Cum: 20, 89 Flat: 20, 90 Unit: "ms", 91 }, 92 } 93 94 // Set edge to be Residual. 95 g.Nodes[0].Out[g.Nodes[1]].Residual = true 96 97 var buf bytes.Buffer 98 ComposeDot(&buf, g, a, c) 99 100 want, err := ioutil.ReadFile(path + "compose3.dot") 101 if err != nil { 102 t.Fatalf("error reading test file: %v", err) 103 } 104 105 compareGraphs(t, buf.Bytes(), want) 106 } 107 108 func TestComposeWithNestedTags(t *testing.T) { 109 g := baseGraph() 110 a, c := baseAttrsAndConfig() 111 112 // Add tags to Node 1. 113 g.Nodes[0].LabelTags["tag1"] = &Tag{ 114 Name: "tag1", 115 Cum: 10, 116 Flat: 10, 117 } 118 g.Nodes[0].NumericTags["tag1"] = TagMap{ 119 "tag2": &Tag{ 120 Name: "tag2", 121 Cum: 20, 122 Flat: 20, 123 Unit: "ms", 124 }, 125 } 126 127 var buf bytes.Buffer 128 ComposeDot(&buf, g, a, c) 129 130 want, err := ioutil.ReadFile(path + "compose5.dot") 131 if err != nil { 132 t.Fatalf("error reading test file: %v", err) 133 } 134 135 compareGraphs(t, buf.Bytes(), want) 136 } 137 138 func TestComposeWithEmptyGraph(t *testing.T) { 139 g := &Graph{} 140 a, c := baseAttrsAndConfig() 141 142 var buf bytes.Buffer 143 ComposeDot(&buf, g, a, c) 144 145 want, err := ioutil.ReadFile(path + "compose4.dot") 146 if err != nil { 147 t.Fatalf("error reading test file: %v", err) 148 } 149 150 compareGraphs(t, buf.Bytes(), want) 151 } 152 153 func baseGraph() *Graph { 154 src := &Node{ 155 Info: NodeInfo{Name: "src"}, 156 Flat: 10, 157 Cum: 25, 158 In: make(EdgeMap), 159 Out: make(EdgeMap), 160 LabelTags: make(TagMap), 161 NumericTags: make(map[string]TagMap), 162 } 163 dest := &Node{ 164 Info: NodeInfo{Name: "dest"}, 165 Flat: 15, 166 Cum: 25, 167 In: make(EdgeMap), 168 Out: make(EdgeMap), 169 LabelTags: make(TagMap), 170 NumericTags: make(map[string]TagMap), 171 } 172 edge := &Edge{ 173 Src: src, 174 Dest: dest, 175 Weight: 10, 176 } 177 src.Out[dest] = edge 178 src.In[src] = edge 179 return &Graph{ 180 Nodes: Nodes{ 181 src, 182 dest, 183 }, 184 } 185 } 186 187 func baseAttrsAndConfig() (*DotAttributes, *DotConfig) { 188 a := &DotAttributes{ 189 Nodes: make(map[*Node]*DotNodeAttributes), 190 } 191 c := &DotConfig{ 192 Title: "testtitle", 193 Labels: []string{"label1", "label2"}, 194 Total: 100, 195 FormatValue: func(v int64) string { 196 return strconv.FormatInt(v, 10) 197 }, 198 } 199 return a, c 200 } 201 202 func compareGraphs(t *testing.T, got, want []byte) { 203 if string(got) != string(want) { 204 d, err := proftest.Diff(got, want) 205 if err != nil { 206 t.Fatalf("error finding diff: %v", err) 207 } 208 t.Errorf("Compose incorrectly wrote %s", string(d)) 209 } 210 } 211 212 func TestMultilinePrintableName(t *testing.T) { 213 ni := &NodeInfo{ 214 Name: "test1.test2::test3", 215 File: "src/file.cc", 216 Address: 123, 217 Lineno: 999, 218 } 219 220 want := fmt.Sprintf(`%016x\ntest1\ntest2\ntest3\nfile.cc:999\n`, 123) 221 if got := multilinePrintableName(ni); got != want { 222 t.Errorf("multilinePrintableName(%#v) == %q, want %q", ni, got, want) 223 } 224 } 225 226 func TestTagCollapse(t *testing.T) { 227 228 makeTag := func(name, unit string, value, flat, cum int64) *Tag { 229 return &Tag{name, unit, value, flat, 0, cum, 0} 230 } 231 232 tagSource := []*Tag{ 233 makeTag("12mb", "mb", 12, 100, 100), 234 makeTag("1kb", "kb", 1, 1, 1), 235 makeTag("1mb", "mb", 1, 1000, 1000), 236 makeTag("2048mb", "mb", 2048, 1000, 1000), 237 makeTag("1b", "b", 1, 100, 100), 238 makeTag("2b", "b", 2, 100, 100), 239 makeTag("7b", "b", 7, 100, 100), 240 } 241 242 tagWant := [][]*Tag{ 243 []*Tag{ 244 makeTag("1B..2GB", "", 0, 2401, 2401), 245 }, 246 []*Tag{ 247 makeTag("2GB", "", 0, 1000, 1000), 248 makeTag("1B..12MB", "", 0, 1401, 1401), 249 }, 250 []*Tag{ 251 makeTag("2GB", "", 0, 1000, 1000), 252 makeTag("12MB", "", 0, 100, 100), 253 makeTag("1B..1MB", "", 0, 1301, 1301), 254 }, 255 []*Tag{ 256 makeTag("2GB", "", 0, 1000, 1000), 257 makeTag("1MB", "", 0, 1000, 1000), 258 makeTag("2B..1kB", "", 0, 201, 201), 259 makeTag("1B", "", 0, 100, 100), 260 makeTag("12MB", "", 0, 100, 100), 261 }, 262 } 263 264 for _, tc := range tagWant { 265 var got, want []*Tag 266 b := builder{nil, &DotAttributes{}, &DotConfig{}} 267 got = b.collapsedTags(tagSource, len(tc), true) 268 want = SortTags(tc, true) 269 270 if !reflect.DeepEqual(got, want) { 271 t.Errorf("collapse to %d, got:\n%v\nwant:\n%v", len(tc), tagString(got), tagString(want)) 272 } 273 } 274 } 275 276 func tagString(t []*Tag) string { 277 var ret []string 278 for _, s := range t { 279 ret = append(ret, fmt.Sprintln(s)) 280 } 281 return strings.Join(ret, ":") 282 }