golang.org/toolchain@v0.0.1-go1.9rc2.windows-amd64/src/cmd/vendor/github.com/google/pprof/internal/binutils/binutils_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 binutils
    16  
    17  import (
    18  	"fmt"
    19  	"testing"
    20  
    21  	"github.com/google/pprof/internal/plugin"
    22  )
    23  
    24  var testAddrMap = map[int]string{
    25  	1000: "_Z3fooid.clone2",
    26  	2000: "_ZNSaIiEC1Ev.clone18",
    27  	3000: "_ZNSt6vectorIS_IS_IiSaIiEESaIS1_EESaIS3_EEixEm",
    28  }
    29  
    30  func functionName(level int) (name string) {
    31  	if name = testAddrMap[level]; name != "" {
    32  		return name
    33  	}
    34  	return fmt.Sprintf("fun%d", level)
    35  }
    36  
    37  func TestAddr2Liner(t *testing.T) {
    38  	const offset = 0x500
    39  
    40  	a := addr2Liner{&mockAddr2liner{}, offset, nil}
    41  	for i := 1; i < 8; i++ {
    42  		addr := i*0x1000 + offset
    43  		s, err := a.addrInfo(uint64(addr))
    44  		if err != nil {
    45  			t.Fatalf("addrInfo(%#x): %v", addr, err)
    46  		}
    47  		if len(s) != i {
    48  			t.Fatalf("addrInfo(%#x): got len==%d, want %d", addr, len(s), i)
    49  		}
    50  		for l, f := range s {
    51  			level := (len(s) - l) * 1000
    52  			want := plugin.Frame{Func: functionName(level), File: fmt.Sprintf("file%d", level), Line: level}
    53  
    54  			if f != want {
    55  				t.Errorf("AddrInfo(%#x)[%d]: = %+v, want %+v", addr, l, f, want)
    56  			}
    57  		}
    58  	}
    59  	s, err := a.addrInfo(0xFFFF)
    60  	if err != nil {
    61  		t.Fatalf("addrInfo(0xFFFF): %v", err)
    62  	}
    63  	if len(s) != 0 {
    64  		t.Fatalf("AddrInfo(0xFFFF): got len==%d, want 0", len(s))
    65  	}
    66  	a.rw.close()
    67  }
    68  
    69  type mockAddr2liner struct {
    70  	output []string
    71  }
    72  
    73  func (a *mockAddr2liner) write(s string) error {
    74  	var lines []string
    75  	switch s {
    76  	case "1000":
    77  		lines = []string{"_Z3fooid.clone2", "file1000:1000"}
    78  	case "2000":
    79  		lines = []string{"_ZNSaIiEC1Ev.clone18", "file2000:2000", "_Z3fooid.clone2", "file1000:1000"}
    80  	case "3000":
    81  		lines = []string{"_ZNSt6vectorIS_IS_IiSaIiEESaIS1_EESaIS3_EEixEm", "file3000:3000", "_ZNSaIiEC1Ev.clone18", "file2000:2000", "_Z3fooid.clone2", "file1000:1000"}
    82  	case "4000":
    83  		lines = []string{"fun4000", "file4000:4000", "_ZNSt6vectorIS_IS_IiSaIiEESaIS1_EESaIS3_EEixEm", "file3000:3000", "_ZNSaIiEC1Ev.clone18", "file2000:2000", "_Z3fooid.clone2", "file1000:1000"}
    84  	case "5000":
    85  		lines = []string{"fun5000", "file5000:5000", "fun4000", "file4000:4000", "_ZNSt6vectorIS_IS_IiSaIiEESaIS1_EESaIS3_EEixEm", "file3000:3000", "_ZNSaIiEC1Ev.clone18", "file2000:2000", "_Z3fooid.clone2", "file1000:1000"}
    86  	case "6000":
    87  		lines = []string{"fun6000", "file6000:6000", "fun5000", "file5000:5000", "fun4000", "file4000:4000", "_ZNSt6vectorIS_IS_IiSaIiEESaIS1_EESaIS3_EEixEm", "file3000:3000", "_ZNSaIiEC1Ev.clone18", "file2000:2000", "_Z3fooid.clone2", "file1000:1000"}
    88  	case "7000":
    89  		lines = []string{"fun7000", "file7000:7000", "fun6000", "file6000:6000", "fun5000", "file5000:5000", "fun4000", "file4000:4000", "_ZNSt6vectorIS_IS_IiSaIiEESaIS1_EESaIS3_EEixEm", "file3000:3000", "_ZNSaIiEC1Ev.clone18", "file2000:2000", "_Z3fooid.clone2", "file1000:1000"}
    90  	case "8000":
    91  		lines = []string{"fun8000", "file8000:8000", "fun7000", "file7000:7000", "fun6000", "file6000:6000", "fun5000", "file5000:5000", "fun4000", "file4000:4000", "_ZNSt6vectorIS_IS_IiSaIiEESaIS1_EESaIS3_EEixEm", "file3000:3000", "_ZNSaIiEC1Ev.clone18", "file2000:2000", "_Z3fooid.clone2", "file1000:1000"}
    92  	case "9000":
    93  		lines = []string{"fun9000", "file9000:9000", "fun8000", "file8000:8000", "fun7000", "file7000:7000", "fun6000", "file6000:6000", "fun5000", "file5000:5000", "fun4000", "file4000:4000", "_ZNSt6vectorIS_IS_IiSaIiEESaIS1_EESaIS3_EEixEm", "file3000:3000", "_ZNSaIiEC1Ev.clone18", "file2000:2000", "_Z3fooid.clone2", "file1000:1000"}
    94  	default:
    95  		lines = []string{"??", "??:0"}
    96  	}
    97  	a.output = append(a.output, "0x"+s)
    98  	a.output = append(a.output, lines...)
    99  	return nil
   100  }
   101  
   102  func (a *mockAddr2liner) readLine() (string, error) {
   103  	if len(a.output) == 0 {
   104  		return "", fmt.Errorf("end of file")
   105  	}
   106  	next := a.output[0]
   107  	a.output = a.output[1:]
   108  	return next, nil
   109  }
   110  
   111  func (a *mockAddr2liner) close() {
   112  }
   113  
   114  func TestAddr2LinerLookup(t *testing.T) {
   115  	oddSizedMap := addr2LinerNM{
   116  		m: []symbolInfo{
   117  			{0x1000, "0x1000"},
   118  			{0x2000, "0x2000"},
   119  			{0x3000, "0x3000"},
   120  		},
   121  	}
   122  	evenSizedMap := addr2LinerNM{
   123  		m: []symbolInfo{
   124  			{0x1000, "0x1000"},
   125  			{0x2000, "0x2000"},
   126  			{0x3000, "0x3000"},
   127  			{0x4000, "0x4000"},
   128  		},
   129  	}
   130  	for _, a := range []*addr2LinerNM{
   131  		&oddSizedMap, &evenSizedMap,
   132  	} {
   133  		for address, want := range map[uint64]string{
   134  			0x1000: "0x1000",
   135  			0x1001: "0x1000",
   136  			0x1FFF: "0x1000",
   137  			0x2000: "0x2000",
   138  			0x2001: "0x2000",
   139  		} {
   140  			if got, _ := a.addrInfo(address); !checkAddress(got, address, want) {
   141  				t.Errorf("%x: got %v, want %s", address, got, want)
   142  			}
   143  		}
   144  	}
   145  }
   146  
   147  func checkAddress(got []plugin.Frame, address uint64, want string) bool {
   148  	if len(got) != 1 {
   149  		return false
   150  	}
   151  	return got[0].Func == want
   152  }