Skip to content

garble test fails to resolve test-scoped dependency packages listed as "pkg [pkg.test]" #1018

@zamai

Description

@zamai

Output of garble version:

mvdan.cc/garble v0.15.0

Build settings:
-buildmode exe
-compiler gc
DefaultGODEBUG cryptocustomrand=1,tlssecpmlkem=0,urlstrictcolons=0
CGO_ENABLED 1
GOARCH arm64
GOOS darwin
GOARM64 v8.0

Output of go env in your module/workspace:

-> % go env
AR='ar'
CC='cc'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='c++'
GCCGO='gccgo'
GO111MODULE=''
GOARCH='arm64'
GOARM64='v8.0'
GOAUTH='netrc'
GOBIN=''
GOCACHE='/Users/alex/Library/Caches/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/Users/alex/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/xx/_y62swfx7wngnmzb40174vb80000gn/T/go-build4051403362=/tmp/go-build -gno-record-gcc-switches -fno-common'
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMOD='/Users/alex/Code/garble/go.mod'
GOMODCACHE='/Users/alex/go/pkg/mod'
GONOPROXY='github.com/castai/*'
GONOSUMDB='github.com/castai/*,gitlab.com/castai/*'
GOOS='darwin'
GOPATH='/Users/alex/go'
GOPRIVATE='github.com/castai/*'
GOPROXY='https://us-central1-go.pkg.dev/cicd-master-oxk5/go-modules,https://proxy.golang.org,direct'
GOROOT='/opt/homebrew/Cellar/go/1.26.1/libexec'
GOSUMDB='sum.golang.org'
GOTELEMETRY='local'
GOTELEMETRYDIR='/Users/alex/Library/Application Support/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN=''
GOTOOLDIR='/opt/homebrew/Cellar/go/1.26.1/libexec/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='go1.26.1'
GOWORK=''
PKG_CONFIG='pkg-config'

What did you do?

I am garble test over the repo that had mock.
I reproduced this with a integration test: test_scoped_module.txtar

# A package used only via export_test.go can be listed under a test-scoped
# import path like "pkg/path [pkg.test]". Garble must resolve that form too.

env GOGARBLE=test/bar

exec go test ./internal/foo
stdout 'ok\s+test/bar/internal/foo'

exec go list -deps -test ./internal/foo
stdout 'test/bar/mocks/foo \[test/bar/internal/foo.test\]'

exec garble test ./internal/foo
stdout 'ok\s+test/bar/internal/foo'
-- go.mod --
module test/bar

go 1.23
-- internal/foo/foo.go --
package foo

func LocalFoo(v interface{ Foo() string }) string {
	return v.Foo()
}
-- internal/foo/export_test.go --
package foo

type ExportedFoo interface {
	Foo() string
}

-- internal/foo/foo_test.go --
package foo_test

import (
	"testing"

	"test/bar/internal/foo"
	mockfoo "test/bar/mocks/foo"
)

func TestFoo(t *testing.T) {
	if got := foo.LocalFoo(mockfoo.MockFoo{}); got != "Foo" {
		t.Fatalf("LocalFoo() = %q", got)
	}
}

-- mocks/foo/foo.go --
package foo

import under_test "test/bar/internal/foo"

var _ under_test.ExportedFoo = MockFoo{}

type MockFoo struct{}

func (MockFoo) Foo() string { return "Foo" }

(pity that I can't attach file here, but it's also in my draft RP: #1017

What did you see happen?

go test passes:

$ go test ./internal/foo
ok test/bar/internal/foo
go list -deps -test shows the important package shape:

$ go list -deps -test ./internal/foo
...
test/bar/internal/foo [test/bar/internal/foo.test]
test/bar/mocks/foo [test/bar/internal/foo.test]
test/bar/internal/foo_test [test/bar/internal/foo.test]
test/bar/internal/foo.test

But garble test fails:

$ GOGARBLE=test/bar garble test ./internal/foo
# test/bar/internal/foo.test
list test/bar/mocks/foo: not found
FAIL	test/bar/internal/foo [build failed]
FAIL

So the failure seems to be that garble only looks up test/bar/mocks/foo, while go list -deps -test only recorded it under the test-scoped form test/bar/mocks/foo [test/bar/internal/foo.test].

What did you expect to see?

garble test ./internal/foo should behave like go test ./internal/foo and pass.

go list -deps -test is allowed to report the mock package under a test-scoped import path like:

test/bar/mocks/foo [test/bar/internal/foo.test]

Garble should resolve that dependency correctly instead of only looking up the plain import path.

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs infoRequires extra information to be solved

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions