diff --git a/musttag_test.go b/musttag_test.go index 42f35c6..5b6092a 100644 --- a/musttag_test.go +++ b/musttag_test.go @@ -3,7 +3,8 @@ package musttag import ( "go/token" "io" - "path" + "os" + "path/filepath" "strings" "testing" @@ -12,14 +13,11 @@ import ( ) func TestAnalyzer(t *testing.T) { - // NOTE(junk1tm): analysistest isn't aware of the main package's modules - // (see https://github.com/golang/go/issues/37054), so to run tests with - // external dependencies we have to be creative. Using vendor with symlinks - // would work but the paths would contain the `vendor/` prefix, and that's - // not what we want because we match full paths. The solution is to write - // stubs of the dependencies (we don't need the actual code, only the - // functions signatures to match) and to put them exactly at - // testdata/src/path/to/pkg (GOPATH?), otherwise it won't work. + // NOTE(junk1tm): analysistest does not yet support modules + // (see https://github.com/golang/go/issues/37054 for details). + // So, to be able to run tests with external dependencies, + // we first need to write a GOPATH-like tree of stubs. + prepareTestFiles(t) testPackages = []string{"tests", "examples"} @@ -86,5 +84,74 @@ func shortName(name string) string { name = strings.ReplaceAll(name, "*", "") name = strings.ReplaceAll(name, "(", "") name = strings.ReplaceAll(name, ")", "") - return path.Base(name) + return filepath.Base(name) +} + +func prepareTestFiles(t *testing.T) { + testdata := analysistest.TestData() + + t.Cleanup(func() { + _ = os.RemoveAll(filepath.Join(testdata, "src")) + }) + + hardlink := func(dir, file string) { + target := filepath.Join(testdata, "src", dir, file) + if err := os.MkdirAll(filepath.Dir(target), 0o777); err != nil { + t.Fatal(err) + } + if err := os.Link(filepath.Join(testdata, file), target); err != nil { + t.Fatal(err) + } + } + hardlink("tests", "tests.go") + hardlink("examples", "examples.go") + + for file, data := range stubs { + target := filepath.Join(testdata, "src", file) + if err := os.MkdirAll(filepath.Dir(target), 0o777); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(target, []byte(data), 0o666); err != nil { + t.Fatal(err) + } + } +} + +var stubs = map[string]string{ + "gopkg.in/yaml.v3/yaml.go": `package yaml +import "io" +func Marshal(_ any) ([]byte, error) { return nil, nil } +func Unmarshal(_ []byte, _ any) error { return nil } +type Encoder struct{} +func NewEncoder(_ io.Writer) *Encoder { return nil } +func (*Encoder) Encode(_ any) error { return nil } +type Decoder struct{} +func NewDecoder(_ io.Reader) *Decoder { return nil } +func (*Decoder) Decode(_ any) error { return nil }`, + + "github.com/BurntSushi/toml/toml.go": `package toml +import "io" +import "io/fs" +func Unmarshal(_ []byte, _ any) error { return nil } +type MetaData struct{} +func Decode(_ string, _ any) (MetaData, error) { return MetaData{}, nil } +func DecodeFS(_ fs.FS, _ string, _ any) (MetaData, error) { return MetaData{}, nil } +func DecodeFile(_ string, _ any) (MetaData, error) { return MetaData{}, nil } +type Encoder struct{} +func NewEncoder(_ io.Writer) *Encoder { return nil } +func (*Encoder) Encode(_ any) error { return nil } +type Decoder struct{} +func NewDecoder(_ io.Reader) *Decoder { return nil } +func (*Decoder) Decode(_ any) error { return nil }`, + + "github.com/mitchellh/mapstructure/mapstructure.go": `package mapstructure +type Metadata struct{} +func Decode(_, _ any) error { return nil } +func DecodeMetadata(_, _ any, _ *Metadata) error { return nil } +func WeakDecode(_, _ any) error { return nil } +func WeakDecodeMetadata(_, _ any, _ *Metadata) error { return nil }`, + + "example.com/custom/custom.go": `package custom +func Marshal(_ any) ([]byte, error) { return nil, nil } +func Unmarshal(_ []byte, _ any) error { return nil }`, } diff --git a/testdata/src/examples/examples.go b/testdata/examples.go similarity index 100% rename from testdata/src/examples/examples.go rename to testdata/examples.go diff --git a/testdata/src/example.com/custom/custom.go b/testdata/src/example.com/custom/custom.go deleted file mode 100644 index 492edb9..0000000 --- a/testdata/src/example.com/custom/custom.go +++ /dev/null @@ -1,5 +0,0 @@ -// Package custom is an example of using a custom package. -package custom - -func Marshal(_ any) ([]byte, error) { return nil, nil } -func Unmarshal(_ []byte, _ any) error { return nil } diff --git a/testdata/src/example.com/custom/go.mod b/testdata/src/example.com/custom/go.mod deleted file mode 100644 index bba54ee..0000000 --- a/testdata/src/example.com/custom/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module example.com/custom - -go 1.18 diff --git a/testdata/src/github.com/BurntSushi/toml/go.mod b/testdata/src/github.com/BurntSushi/toml/go.mod deleted file mode 100644 index 57b1d37..0000000 --- a/testdata/src/github.com/BurntSushi/toml/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module github.com/BurntSushi/toml - -go 1.18 diff --git a/testdata/src/github.com/BurntSushi/toml/toml.go b/testdata/src/github.com/BurntSushi/toml/toml.go deleted file mode 100644 index e972579..0000000 --- a/testdata/src/github.com/BurntSushi/toml/toml.go +++ /dev/null @@ -1,25 +0,0 @@ -// Package toml provides stubs for github.com/BurntSushi/toml. -package toml - -import ( - "io" - "io/fs" -) - -func Unmarshal(_ []byte, _ any) error { return nil } - -type MetaData struct{} - -func Decode(_ string, _ any) (MetaData, error) { return MetaData{}, nil } -func DecodeFS(_ fs.FS, _ string, _ any) (MetaData, error) { return MetaData{}, nil } -func DecodeFile(_ string, _ any) (MetaData, error) { return MetaData{}, nil } - -type Encoder struct{} - -func NewEncoder(_ io.Writer) *Encoder { return nil } -func (*Encoder) Encode(_ any) error { return nil } - -type Decoder struct{} - -func NewDecoder(_ io.Reader) *Decoder { return nil } -func (*Decoder) Decode(_ any) error { return nil } diff --git a/testdata/src/github.com/mitchellh/mapstructure/go.mod b/testdata/src/github.com/mitchellh/mapstructure/go.mod deleted file mode 100644 index b36f650..0000000 --- a/testdata/src/github.com/mitchellh/mapstructure/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module github.com/mitchellh/mapstructure - -go 1.18 diff --git a/testdata/src/github.com/mitchellh/mapstructure/mapstructure.go b/testdata/src/github.com/mitchellh/mapstructure/mapstructure.go deleted file mode 100644 index f0777c8..0000000 --- a/testdata/src/github.com/mitchellh/mapstructure/mapstructure.go +++ /dev/null @@ -1,12 +0,0 @@ -// Package mapstructure provides stubs for github.com/mitchellh/mapstructure. -package mapstructure - -// mapstructure.NewDecoder wants the struct pointer to be passed via -// mapstructure.DecoderConfig, that's why we do not support it for now. - -type Metadata struct{} - -func Decode(_, _ any) error { return nil } -func DecodeMetadata(_, _ any, _ *Metadata) error { return nil } -func WeakDecode(_, _ any) error { return nil } -func WeakDecodeMetadata(_, _ any, _ *Metadata) error { return nil } diff --git a/testdata/src/gopkg.in/yaml.v3/go.mod b/testdata/src/gopkg.in/yaml.v3/go.mod deleted file mode 100644 index 315174b..0000000 --- a/testdata/src/gopkg.in/yaml.v3/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module gopkg.in/yaml.v3 - -go 1.18 diff --git a/testdata/src/gopkg.in/yaml.v3/yaml.go b/testdata/src/gopkg.in/yaml.v3/yaml.go deleted file mode 100644 index 88b4aa0..0000000 --- a/testdata/src/gopkg.in/yaml.v3/yaml.go +++ /dev/null @@ -1,17 +0,0 @@ -// Package yaml provides stubs for gopkg.in/yaml.v3. -package yaml - -import "io" - -func Marshal(_ any) ([]byte, error) { return nil, nil } -func Unmarshal(_ []byte, _ any) error { return nil } - -type Encoder struct{} - -func NewEncoder(_ io.Writer) *Encoder { return nil } -func (*Encoder) Encode(_ any) error { return nil } - -type Decoder struct{} - -func NewDecoder(_ io.Reader) *Decoder { return nil } -func (*Decoder) Decode(_ any) error { return nil } diff --git a/testdata/src/tests/tests.go b/testdata/tests.go similarity index 100% rename from testdata/src/tests/tests.go rename to testdata/tests.go