// Copyright 2024 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 runtime_test

// This test of GOTRACEBACK=system has its own file,
// to minimize line-number perturbation.

import (
	"bytes"
	"fmt"
	"internal/testenv"
	"io"
	"os"
	"path/filepath"
	"reflect"
	"runtime"
	"runtime/debug"
	"strconv"
	"strings"
	"testing"
)

// This is the entrypoint of the child process used by
// TestTracebackSystem. It prints a crash report to stdout.
func crash() {
	// Ensure that we get pc=0x%x values in the traceback.
	debug.SetTraceback("system")
	writeSentinel(os.Stdout)
	debug.SetCrashOutput(os.Stdout)

	go func() {
		// This call is typically inlined.
		child()
	}()
	select {}
}

func child() {
	grandchild()
}

func grandchild() {
	// Write runtime.Caller's view of the stack to stderr, for debugging.
	var pcs [16]uintptr
	n := runtime.Callers(1, pcs[:])
	io.WriteString(os.Stderr, formatStack(pcs[:n]))

	// Cause the crash report to be written to stdout.
	panic("oops")
}

// TestTracebackSystem tests that the syntax of crash reports produced
// by GOTRACEBACK=system (see traceback2) contains a complete,
// parseable list of program counters for the running goroutine that
// can be parsed and fed to runtime.CallersFrames to obtain accurate
// information about the logical call stack, even in the presence of
// inlining.
//
// The test is a distillation of the crash monitor in
// golang.org/x/telemetry/crashmonitor.
func TestTracebackSystem(t *testing.T) {
	testenv.MustHaveExec(t)
	if runtime.GOOS == "android" {
		t.Skip("Can't read source code for this file on Android")
	}

	// Fork+exec the crashing process.
	exe, err := os.Executable()
	if err != nil {
		t.Fatal(err)
	}
	cmd := testenv.Command(t, exe)
	cmd.Env = append(cmd.Environ(), entrypointVar+"=crash")
	cmd.Stdout = new(strings.Builder)
	// cmd.Stderr = os.Stderr // uncomment to debug, e.g. to see runtime.Caller's view
	cmd.Run() // expected to crash
	crash := cmd.Stdout.(*strings.Builder).String()

	// If the only line is the sentinel, it wasn't a crash.
	if strings.Count(crash, "\n") < 2 {
		t.Fatalf("child process did not produce a crash report")
	}

	// Parse the PCs out of the child's crash report.
	pcs, err := parseStackPCs(crash)
	if err != nil {
		t.Fatal(err)
	}

	// Unwind the stack using this executable's symbol table.
	got := formatStack(pcs)
	want := `redacted.go:0: runtime.gopanic
traceback_system_test.go:51: runtime_test.grandchild: 	panic("oops")
traceback_system_test.go:41: runtime_test.child: 	grandchild()
traceback_system_test.go:35: runtime_test.crash.func1: 		child()
redacted.go:0: runtime.goexit`
	if strings.TrimSpace(got) != strings.TrimSpace(want) {
		t.Errorf("got:\n%swant:\n%s", got, want)
	}
}

// parseStackPCs parses the parent process's program counters for the
// first running goroutine out of a GOTRACEBACK=system traceback,
// adjusting them so that they are valid for the child process's text
// segment.
//
// This function returns only program counter values, ensuring that
// there is no possibility of strings from the crash report (which may
// contain PII) leaking into the telemetry system.
//
// (Copied from golang.org/x/telemetry/crashmonitor.parseStackPCs.)
func parseStackPCs(crash string) ([]uintptr, error) {
	// getPC parses the PC out of a line of the form:
	//     \tFILE:LINE +0xRELPC sp=... fp=... pc=...
	getPC := func(line string) (uint64, error) {
		_, pcstr, ok := strings.Cut(line, " pc=") // e.g. pc=0x%x
		if !ok {
			return 0, fmt.Errorf("no pc= for stack frame: %s", line)
		}
		return strconv.ParseUint(pcstr, 0, 64) // 0 => allow 0x prefix
	}

	var (
		pcs            []uintptr
		parentSentinel uint64
		childSentinel  = sentinel()
		on             = false // are we in the first running goroutine?
		lines          = strings.Split(crash, "\n")
	)
	for i := 0; i < len(lines); i++ {
		line := lines[i]

		// Read sentinel value.
		if parentSentinel == 0 && strings.HasPrefix(line, "sentinel ") {
			_, err := fmt.Sscanf(line, "sentinel %x", &parentSentinel)
			if err != nil {
				return nil, fmt.Errorf("can't read sentinel line")
			}
			continue
		}

		// Search for "goroutine GID [STATUS]"
		if !on {
			if strings.HasPrefix(line, "goroutine ") &&
				strings.Contains(line, " [running]:") {
				on = true

				if parentSentinel == 0 {
					return nil, fmt.Errorf("no sentinel value in crash report")
				}
			}
			continue
		}

		// A blank line marks end of a goroutine stack.
		if line == "" {
			break
		}

		// Skip the final "created by SYMBOL in goroutine GID" part.
		if strings.HasPrefix(line, "created by ") {
			break
		}

		// Expect a pair of lines:
		//   SYMBOL(ARGS)
		//   \tFILE:LINE +0xRELPC sp=0x%x fp=0x%x pc=0x%x
		// Note: SYMBOL may contain parens "pkg.(*T).method"
		// The RELPC is sometimes missing.

		// Skip the symbol(args) line.
		i++
		if i == len(lines) {
			break
		}
		line = lines[i]

		// Parse the PC, and correct for the parent and child's
		// different mappings of the text section.
		pc, err := getPC(line)
		if err != nil {
			// Inlined frame, perhaps; skip it.
			continue
		}
		pcs = append(pcs, uintptr(pc-parentSentinel+childSentinel))
	}
	return pcs, nil
}

// The sentinel function returns its address. The difference between
// this value as observed by calls in two different processes of the
// same executable tells us the relative offset of their text segments.
//
// It would be nice if SetCrashOutput took care of this as it's fiddly
// and likely to confuse every user at first.
func sentinel() uint64 {
	return uint64(reflect.ValueOf(sentinel).Pointer())
}

func writeSentinel(out io.Writer) {
	fmt.Fprintf(out, "sentinel %x\n", sentinel())
}

// formatStack formats a stack of PC values using the symbol table,
// redacting information that cannot be relied upon in the test.
func formatStack(pcs []uintptr) string {
	// When debugging, show file/line/content of files other than this one.
	const debug = false

	var buf strings.Builder
	i := 0
	frames := runtime.CallersFrames(pcs)
	for {
		fr, more := frames.Next()
		if debug {
			fmt.Fprintf(&buf, "pc=%x ", pcs[i])
			i++
		}
		if base := filepath.Base(fr.File); base == "traceback_system_test.go" || debug {
			content, err := os.ReadFile(fr.File)
			if err != nil {
				panic(err)
			}
			lines := bytes.Split(content, []byte("\n"))
			fmt.Fprintf(&buf, "%s:%d: %s: %s\n", base, fr.Line, fr.Function, lines[fr.Line-1])
		} else {
			// For robustness, don't show file/line for functions from other files.
			fmt.Fprintf(&buf, "redacted.go:0: %s\n", fr.Function)
		}

		if !more {
			break
		}
	}
	return buf.String()
}
