| // Copyright 2019 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 proxydatasource |
| |
| import ( |
| "context" |
| "errors" |
| "fmt" |
| "strings" |
| "testing" |
| "time" |
| |
| "github.com/google/go-cmp/cmp" |
| "github.com/google/go-cmp/cmp/cmpopts" |
| "golang.org/x/pkgsite/internal" |
| "golang.org/x/pkgsite/internal/derrors" |
| "golang.org/x/pkgsite/internal/licenses" |
| "golang.org/x/pkgsite/internal/proxy" |
| "golang.org/x/pkgsite/internal/testing/sample" |
| "golang.org/x/pkgsite/internal/testing/testhelper" |
| ) |
| |
| func setup(t *testing.T) (context.Context, *DataSource, func()) { |
| t.Helper() |
| contents := map[string]string{ |
| "go.mod": "module foo.com/bar", |
| "LICENSE": testhelper.MITLicense, |
| "baz/baz.go": "//Package baz provides a helpful constant.\npackage baz\nimport \"net/http\"\nconst OK = http.StatusOK", |
| } |
| // nrContents is the same as contents, except the license is non-redistributable. |
| nrContents := map[string]string{ |
| "go.mod": "module foo.com/nr", |
| "LICENSE": "unknown", |
| "baz/baz.go": "//Package baz provides a helpful constant.\npackage baz\nimport \"net/http\"\nconst OK = http.StatusOK", |
| } |
| |
| testModules := []*proxy.Module{ |
| { |
| ModulePath: "foo.com/bar", |
| Version: "v1.1.0", |
| Files: contents, |
| }, |
| { |
| ModulePath: "foo.com/bar", |
| Version: "v1.2.0", |
| Files: contents, |
| }, |
| { |
| ModulePath: "foo.com/nr", |
| Version: "v1.1.0", |
| Files: nrContents, |
| }, |
| } |
| client, teardownProxy := proxy.SetupTestClient(t, testModules) |
| ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second) |
| return ctx, New(client), func() { |
| teardownProxy() |
| cancel() |
| } |
| } |
| |
| var ( |
| wantLicenseMD = sample.LicenseMetadata[0] |
| wantPackage = internal.LegacyPackage{ |
| Path: "foo.com/bar/baz", |
| Name: "baz", |
| Imports: []string{"net/http"}, |
| Synopsis: "Package baz provides a helpful constant.", |
| V1Path: "foo.com/bar/baz", |
| Licenses: []*licenses.Metadata{wantLicenseMD}, |
| IsRedistributable: true, |
| GOOS: "linux", |
| GOARCH: "amd64", |
| } |
| wantModuleInfo = internal.ModuleInfo{ |
| ModulePath: "foo.com/bar", |
| Version: "v1.2.0", |
| CommitTime: time.Date(2019, 1, 30, 0, 0, 0, 0, time.UTC), |
| IsRedistributable: true, |
| HasGoMod: true, |
| } |
| cmpOpts = append([]cmp.Option{ |
| cmpopts.IgnoreFields(internal.LegacyPackage{}, "DocumentationHTML"), |
| cmpopts.IgnoreFields(licenses.License{}, "Contents"), |
| }, sample.LicenseCmpOpts...) |
| ) |
| |
| func TestDataSource_GetModuleInfo(t *testing.T) { |
| ctx, ds, teardown := setup(t) |
| defer teardown() |
| got, err := ds.GetModuleInfo(ctx, "foo.com/bar", "v1.2.0") |
| if err != nil { |
| t.Fatal(err) |
| } |
| if diff := cmp.Diff(&wantModuleInfo, got, cmpOpts...); diff != "" { |
| t.Errorf("GetModuleInfo diff (-want +got):\n%s", diff) |
| } |
| } |
| |
| func TestDataSource_GetUnitMeta(t *testing.T) { |
| ctx, ds, teardown := setup(t) |
| defer teardown() |
| |
| for _, test := range []struct { |
| path, modulePath, version string |
| want *internal.UnitMeta |
| }{ |
| { |
| path: "foo.com/bar", |
| modulePath: "foo.com/bar", |
| version: "v1.1.0", |
| want: &internal.UnitMeta{ |
| ModulePath: "foo.com/bar", |
| Version: "v1.1.0", |
| IsRedistributable: true, |
| }, |
| }, |
| { |
| path: "foo.com/bar/baz", |
| modulePath: "foo.com/bar", |
| version: "v1.1.0", |
| want: &internal.UnitMeta{ |
| ModulePath: "foo.com/bar", |
| Name: "baz", |
| Version: "v1.1.0", |
| IsRedistributable: true, |
| }, |
| }, |
| { |
| path: "foo.com/bar/baz", |
| modulePath: internal.UnknownModulePath, |
| version: "v1.1.0", |
| want: &internal.UnitMeta{ |
| ModulePath: "foo.com/bar", |
| Name: "baz", |
| Version: "v1.1.0", |
| IsRedistributable: true, |
| }, |
| }, |
| { |
| path: "foo.com/bar/baz", |
| modulePath: internal.UnknownModulePath, |
| version: internal.LatestVersion, |
| want: &internal.UnitMeta{ |
| ModulePath: "foo.com/bar", |
| Name: "baz", |
| Version: "v1.2.0", |
| IsRedistributable: true, |
| }, |
| }, |
| } { |
| t.Run(test.path, func(t *testing.T) { |
| got, err := ds.GetUnitMeta(ctx, test.path, test.modulePath, test.version) |
| if err != nil { |
| t.Fatal(err) |
| } |
| test.want.Path = test.path |
| if diff := cmp.Diff(got, test.want); diff != "" { |
| t.Errorf("mismatch (-want +got):\n%s", diff) |
| } |
| }) |
| } |
| } |
| |
| func TestDataSource_Bypass(t *testing.T) { |
| for _, bypass := range []bool{false, true} { |
| t.Run(fmt.Sprintf("bypass=%t", bypass), func(t *testing.T) { |
| // re-create the data source to get around caching |
| ctx, ds, teardown := setup(t) |
| defer teardown() |
| ds.bypassLicenseCheck = bypass |
| for _, mpath := range []string{"foo.com/bar", "foo.com/nr"} { |
| wantEmpty := !bypass && strings.HasSuffix(mpath, "/nr") |
| |
| got, err := ds.getModule(ctx, mpath, "v1.1.0") |
| if err != nil { |
| t.Fatal(err) |
| } |
| // Assume internal.Module.RemoveNonRedistributableData is correct; we just |
| // need to check one value to confirm that it was called. |
| if gotEmpty := (got.Licenses[0].Contents == nil); gotEmpty != wantEmpty { |
| t.Errorf("bypass %t for %q: got empty %t, want %t", bypass, mpath, gotEmpty, wantEmpty) |
| } |
| } |
| }) |
| } |
| } |
| |
| func TestDataSource_GetLatestMajorVersion(t *testing.T) { |
| t.Helper() |
| testModules := []*proxy.Module{ |
| { |
| ModulePath: "foo.com/bar", |
| }, |
| { |
| ModulePath: "foo.com/bar/v2", |
| }, |
| { |
| ModulePath: "foo.com/bar/v3", |
| }, |
| { |
| ModulePath: "bar.com/foo", |
| }, |
| } |
| client, teardownProxy := proxy.SetupTestClient(t, testModules) |
| defer teardownProxy() |
| ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) |
| defer cancel() |
| ds := New(client) |
| |
| for _, test := range []struct { |
| seriesPath string |
| wantVersion string |
| wantErr error |
| }{ |
| { |
| seriesPath: "foo.com/bar", |
| wantVersion: "/v3", |
| }, |
| { |
| seriesPath: "bar.com/foo", |
| wantVersion: "", |
| }, |
| { |
| seriesPath: "boo.com/far", |
| wantErr: derrors.NotFound, |
| }, |
| } { |
| gotVersion, err := ds.GetLatestMajorVersion(ctx, test.seriesPath) |
| if err != nil { |
| if test.wantErr == nil { |
| t.Fatalf("got unexpected error %v", err) |
| } |
| if !errors.Is(err, test.wantErr) { |
| t.Errorf("got err = %v, want Is(%v)", err, test.wantErr) |
| } |
| } |
| if gotVersion != test.wantVersion { |
| t.Errorf("GetLatestMajorVersion(%v) = %v, want %v", test.seriesPath, gotVersion, test.wantVersion) |
| } |
| } |
| } |