blob: 097d92bd22991c5ac28eace306f495996029a4d0 [file] [log] [blame]
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build go1.10
package dwarf_test
// Stripped-down, simplified version of ../../gosym/pclntab_test.go
import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"testing"
. "cloud.google.com/go/cmd/go-cloud-debug-agent/internal/debug/dwarf"
)
var (
pclineTempDir string
pclinetestBinary string
)
func dotest(self bool) bool {
// For now, only works on amd64 platforms.
if runtime.GOARCH != "amd64" {
return false
}
// Self test reads test binary; only works on Linux or Mac.
if self {
if runtime.GOOS != "linux" && runtime.GOOS != "darwin" {
return false
}
}
// Command below expects "sh", so Unix.
if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
return false
}
if pclinetestBinary != "" {
return true
}
var err error
pclineTempDir, err = ioutil.TempDir("", "pclinetest")
if err != nil {
panic(err)
}
if strings.Contains(pclineTempDir, " ") {
panic("unexpected space in tempdir")
}
pclinetestBinary = filepath.Join(pclineTempDir, "pclinetest")
command := fmt.Sprintf("go tool compile -o %s.6 testdata/pclinetest.go && go tool link -H %s -E main -o %s %s.6",
pclinetestBinary, runtime.GOOS, pclinetestBinary, pclinetestBinary)
cmd := exec.Command("sh", "-c", command)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
panic(err)
}
return true
}
func endtest() {
if pclineTempDir != "" {
os.RemoveAll(pclineTempDir)
pclineTempDir = ""
pclinetestBinary = ""
}
}
func TestPCAndLine(t *testing.T) {
t.Skip("This stopped working in Go 1.12")
// TODO(jba): go1.9: use subtests
if !dotest(false) {
return
}
defer endtest()
data, err := getData(pclinetestBinary)
if err != nil {
t.Fatal(err)
}
testLineToBreakpointPCs(t, data)
testPCToLine(t, data)
}
func testPCToLine(t *testing.T, data *Data) {
entry, err := data.LookupFunction("main.main")
if err != nil {
t.Fatal(err)
}
pc, ok := entry.Val(AttrLowpc).(uint64)
if !ok {
t.Fatal(`DWARF data for function "main" has no PC`)
}
for _, tt := range []struct {
offset, want uint64
}{
{0, 19},
{19, 19},
{33, 20},
{97, 22},
{165, 23},
} {
file, line, err := data.PCToLine(pc + tt.offset)
if err != nil {
t.Fatal(err)
}
if !strings.HasSuffix(file, "/pclinetest.go") {
t.Errorf("got %s; want %s", file, "/pclinetest.go")
}
if line != tt.want {
t.Errorf("line for offset %d: got %d; want %d", tt.offset, line, tt.want)
}
}
}
func testLineToBreakpointPCs(t *testing.T, data *Data) {
for _, tt := range []struct {
line uint64
want bool
}{
{18, false},
{19, true},
{20, true},
{21, false},
{22, true},
{23, true},
{24, false},
} {
pcs, err := data.LineToBreakpointPCs("pclinetest.go", uint64(tt.line))
if err != nil {
t.Fatal(err)
}
if got := len(pcs) > 0; got != tt.want {
t.Errorf("line %d: got pcs=%t, want pcs=%t", tt.line, got, tt.want)
}
}
}