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  }