// Copyright 2009 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package dwarf_test

// Stripped-down, simplified version of ../../gosym/pclntab_test.go

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
	"testing"

	. "golang.org/x/debug/dwarf"
	"golang.org/x/debug/elf"
	"golang.org/x/debug/macho"
)

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")
	}
	// This command builds pclinetest from ../../gosym/pclinetest.asm;
	// the resulting binary looks like it was built from pclinetest.s,
	// but we have renamed it to keep it away from the go tool.
	pclinetestBinary = filepath.Join(pclineTempDir, "pclinetest")
	command := fmt.Sprintf("go tool asm -o %s.6 ../gosym/pclinetest.asm && 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 getData(file string) (*Data, error) {
	switch runtime.GOOS {
	case "linux":
		f, err := elf.Open(file)
		if err != nil {
			return nil, err
		}
		dwarf, err := f.DWARF()
		if err != nil {
			return nil, err
		}
		f.Close()
		return dwarf, nil
	case "darwin":
		f, err := macho.Open(file)
		if err != nil {
			return nil, err
		}
		dwarf, err := f.DWARF()
		if err != nil {
			return nil, err
		}
		f.Close()
		return dwarf, nil
	}
	panic("unimplemented DWARF for GOOS=" + runtime.GOOS)
}

func TestPCToLine(t *testing.T) {
	if !dotest(false) {
		return
	}
	defer endtest()

	data, err := getData(pclinetestBinary)
	if err != nil {
		t.Fatal(err)
	}

	// Test PCToLine.
	entry, err := data.LookupFunction("linefrompc")
	if err != nil {
		t.Fatal(err)
	}
	pc, ok := entry.Val(AttrLowpc).(uint64)
	if !ok {
		t.Fatal(`DWARF data for function "linefrompc" has no PC`)
	}
	for _, tt := range []struct {
		offset, want uint64
	}{
		{0, 2},
		{1, 3},
		{2, 4},
		{3, 4},
		{4, 5},
		{6, 5},
		{7, 6},
		{11, 6},
		{12, 7},
		{19, 7},
		{20, 8},
		{32, 8},
		{33, 9},
		{53, 9},
		{54, 10},
	} {
		file, line, err := data.PCToLine(pc + tt.offset)
		if err != nil {
			t.Fatal(err)
		}
		if !strings.HasSuffix(file, "/pclinetest.asm") {
			t.Errorf("got %s; want %s", file, ".../pclinetest.asm")
		}
		if line != tt.want {
			t.Errorf("line for offset %d: got %d; want %d", tt.offset, line, tt.want)
		}
	}
}
