Skip to content

Commit 661c496

Browse files
committed
stack: check go module after GOPATH
This is an hard call. Normally localgomod should never be inside GOPATH. Minor forward looking v2 fixes.
1 parent 1ba5547 commit 661c496

File tree

3 files changed

+65
-37
lines changed

3 files changed

+65
-37
lines changed

stack/context_test.go

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1256,6 +1256,10 @@ func testPanicMismatched(t *testing.T, c *Context, b *bytes.Buffer, ppDir string
12561256
if b.String() != "GOTRACEBACK=all\npanic: 42\n\n" {
12571257
t.Fatalf("output: %q", b.String())
12581258
}
1259+
ver := ""
1260+
if !internaltest.IsUsingModules() {
1261+
ver = ""
1262+
}
12591263
want := []*Goroutine{
12601264
{
12611265
Signature: Signature{
@@ -1268,7 +1272,7 @@ func testPanicMismatched(t *testing.T, c *Context, b *bytes.Buffer, ppDir string
12681272
//
12691273
// Here the package name is "correct". There is no way to deduce
12701274
// this from the stack trace.
1271-
"github.com/maruel/panicparse/cmd/panic/internal/incorrect.Panic",
1275+
"github.com/maruel/panicparse"+ver+"/cmd/panic/internal/incorrect.Panic",
12721276
Args{},
12731277
pathJoin(ppDir, "internal", "incorrect", "correct.go"),
12741278
7),
@@ -1321,6 +1325,10 @@ func testPanicUTF8(t *testing.T, c *Context, b *bytes.Buffer, ppDir string) {
13211325
if b.String() != "GOTRACEBACK=all\npanic: 42\n\n" {
13221326
t.Fatalf("output: %q", b.String())
13231327
}
1328+
ver := ""
1329+
if !internaltest.IsUsingModules() {
1330+
ver = ""
1331+
}
13241332
want := []*Goroutine{
13251333
{
13261334
Signature: Signature{
@@ -1331,7 +1339,7 @@ func testPanicUTF8(t *testing.T, c *Context, b *bytes.Buffer, ppDir string) {
13311339
// This is important to note here the inconsistency in the Go
13321340
// runtime stack generator. The path is escaped, but symbols are
13331341
// not.
1334-
"github.com/maruel/panicparse/cmd/panic/internal/%c3%b9tf8.(*Strùct).Pànic",
1342+
"github.com/maruel/panicparse"+ver+"/cmd/panic/internal/%c3%b9tf8.(*Strùct).Pànic",
13351343
Args{Values: []Arg{{Value: 0xc0000b2e48}}},
13361344
// See TestCallUTF8 in stack_test.go for exercising the methods on
13371345
// Call in this situation.
@@ -1485,7 +1493,17 @@ func pstCount(s []panicwebSignatureType, t panicwebSignatureType) int {
14851493
return i
14861494
}
14871495

1496+
// identifyPanicwebSignature tries to assign one of the predefined signature to
1497+
// the bucket provided.
1498+
//
1499+
// One challenge is that the path will be different depending if this test is
1500+
// run within GOPATH or outside.
14881501
func identifyPanicwebSignature(t *testing.T, b *Bucket, pwebDir string) panicwebSignatureType {
1502+
ver := ""
1503+
if !isInGOPATH {
1504+
ver = ""
1505+
}
1506+
14891507
// The first bucket (the one calling panic()) is deterministic.
14901508
if b.First {
14911509
if len(b.IDs) != 1 {
@@ -1511,7 +1529,7 @@ func identifyPanicwebSignature(t *testing.T, b *Bucket, pwebDir string) panicweb
15111529
t.Fatalf("suspicious: %#v", b)
15121530
return pstUnknown
15131531
}
1514-
if b.Stack.Calls[0].ImportPath() != "github.com/maruel/panicparse/cmd/panicweb/internal" {
1532+
if b.Stack.Calls[0].ImportPath() != "github.com/maruel/panicparse"+ver+"/cmd/panicweb/internal" {
15151533
t.Fatalf("suspicious: %#v", b)
15161534
return pstUnknown
15171535
}

stack/stack.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -363,16 +363,7 @@ func (c *Call) updateLocations(goroot, localgoroot, localgomod, gomodImportPath
363363
goto done
364364
}
365365
}
366-
// Go module path detection only works with stack traces created on the local
367-
// file system.
368-
if localgomod != "" {
369-
if prefix := localgomod + "/"; strings.HasPrefix(c.SrcPath, prefix) {
370-
c.RelSrcPath = gomodImportPath + "/" + c.SrcPath[len(prefix):]
371-
c.LocalSrcPath = c.SrcPath
372-
goto done
373-
}
374-
}
375-
// Finally, check GOPATH.
366+
// Check GOPATH.
376367
// TODO(maruel): Sort for deterministic behavior?
377368
for prefix, dest := range gopaths {
378369
if p := prefix + "/src/"; strings.HasPrefix(c.SrcPath, p) {
@@ -387,6 +378,15 @@ func (c *Call) updateLocations(goroot, localgoroot, localgomod, gomodImportPath
387378
goto done
388379
}
389380
}
381+
// Go module path detection only works with stack traces created on the local
382+
// file system.
383+
if localgomod != "" {
384+
if prefix := localgomod + "/"; strings.HasPrefix(c.SrcPath, prefix) {
385+
c.RelSrcPath = gomodImportPath + "/" + c.SrcPath[len(prefix):]
386+
c.LocalSrcPath = c.SrcPath
387+
goto done
388+
}
389+
}
390390
done:
391391
if !c.IsStdlib {
392392
// Consider _test/_testmain.go as stdlib since it's injected by "go test".

stack/stack_test.go

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import (
1212
"os"
1313
"runtime"
1414
"strings"
15-
"sync"
1615
"testing"
1716

1817
"github.com/google/go-cmp/cmp"
@@ -387,6 +386,40 @@ func TestSignature_Less(t *testing.T) {
387386

388387
//
389388

389+
var (
390+
goroot string
391+
gopaths map[string]string
392+
gomod string
393+
goimport string
394+
isInGOPATH bool
395+
)
396+
397+
func init() {
398+
goroot = runtime.GOROOT()
399+
gopaths = map[string]string{}
400+
for _, p := range getGOPATHs() {
401+
gopaths[p] = p
402+
}
403+
404+
// Assumes pwd == this directory.
405+
pwd, err := os.Getwd()
406+
if err != nil {
407+
panic(err)
408+
}
409+
// Our internal functions work with '/' as path separator.
410+
pwd = strings.Replace(pwd, "\\", "/", -1)
411+
gomod, goimport = isGoModule(splitPath(pwd))
412+
413+
// When inside GOPATH, no version is added. When outside, the version path is
414+
// added from the reading of module statement in go.mod.
415+
for _, p := range getGOPATHs() {
416+
if strings.HasPrefix(pwd, p) {
417+
isInGOPATH = true
418+
break
419+
}
420+
}
421+
}
422+
390423
func newFunc(s string) Func {
391424
return Func{Raw: s}
392425
}
@@ -395,30 +428,7 @@ func newCall(f string, a Args, s string, l int) Call {
395428
return Call{Func: newFunc(f), Args: a, SrcPath: s, Line: l}
396429
}
397430

398-
var (
399-
local sync.Once
400-
goroot string
401-
gopaths map[string]string
402-
gomod string
403-
goimport string
404-
)
405-
406431
func newCallLocal(f string, a Args, s string, l int) Call {
407-
local.Do(func() {
408-
goroot = runtime.GOROOT()
409-
gopaths = map[string]string{}
410-
for _, p := range getGOPATHs() {
411-
gopaths[p] = p
412-
}
413-
// Assumes pwd == this directory.
414-
pwd, err := os.Getwd()
415-
if err != nil {
416-
panic(err)
417-
}
418-
// Our internal functions work with '/' as path separator.
419-
pwd = strings.Replace(pwd, "\\", "/", -1)
420-
gomod, goimport = isGoModule(splitPath(pwd))
421-
})
422432
c := newCall(f, a, s, l)
423433
c.updateLocations(goroot, goroot, gomod, goimport, gopaths)
424434
if c.LocalSrcPath == "" || c.RelSrcPath == "" {

0 commit comments

Comments
 (0)