internal: add DataSource.GetLatestInfo
Add a single method to DataSource for getting all information
about latest versions.
Remove the old method.
Use the new method throughout.
Change-Id: Ie1c4894261021e91c9b889d00d98a2c7754017fd
Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/279792
Trust: Jonathan Amsterdam <jba@google.com>
Run-TryBot: Jonathan Amsterdam <jba@google.com>
Reviewed-by: Julie Qiu <julie@golang.org>
diff --git a/internal/datasource.go b/internal/datasource.go
index bd16f0a..0bdf1f3 100644
--- a/internal/datasource.go
+++ b/internal/datasource.go
@@ -11,14 +11,6 @@
// See the internal/postgres package for further documentation of these
// methods, particularly as they pertain to the main postgres implementation.
- // GetLatestMajorVersion returns the latest module path and the full package path
- // of the latest version found, given the fullPath and the modulePath.
- // For example, in the module path "github.com/casbin/casbin", there
- // is another module path with a greater major version "github.com/casbin/casbin/v3".
- // This function will return "github.com/casbin/casbin/v3" or the input module path
- // if no later module path was found. It also returns the full package path at the
- // latest module version if it exists. If not, it returns the module path.
- GetLatestMajorVersion(ctx context.Context, fullPath, modulePath string) (_ string, _ string, err error)
// GetNestedModules returns the latest major version of all nested modules
// given a modulePath path prefix.
GetNestedModules(ctx context.Context, modulePath string) ([]*ModuleInfo, error)
@@ -29,4 +21,37 @@
GetUnitMeta(ctx context.Context, path, requestedModulePath, requestedVersion string) (_ *UnitMeta, err error)
// GetModuleReadme gets the readme for the module.
GetModuleReadme(ctx context.Context, modulePath, resolvedVersion string) (*Readme, error)
+
+ // GetLatestInfo gets information about the latest versions of a unit and module.
+ // See LatestInfo for documentation.
+ GetLatestInfo(ctx context.Context, unitPath, modulePath string) (LatestInfo, error)
+}
+
+// LatestInfo holds information about the latest versions and paths.
+// The information is relative to a unit in a module.
+type LatestInfo struct {
+ // MinorVersion is the latest minor version for the unit, regardless of
+ // module.
+ MinorVersion string
+
+ // MinorModulePath is the module path for MinorVersion.
+ MinorModulePath string
+
+ // UnitExistsAtMinor is whether the unit exists at the latest minor version
+ // of the module
+ UnitExistsAtMinor bool
+
+ // MajorModulePath is the path of the latest module path in the series.
+ // For example, in the module path "github.com/casbin/casbin", there
+ // is another module path with a greater major version
+ // "github.com/casbin/casbin/v3". This field will be
+ // "github.com/casbin/casbin/v3" or the input module path if no later module
+ // path was found.
+ MajorModulePath string
+
+ // MajorUnitPath is the path of the unit in the latest major version of the
+ // module, if it exists. For example, if the module is M, the unit is M/U,
+ // and the latest major version is 3, then is field is "M/v3/U". If the module version
+ // at MajorModulePath does not contain this unit, then it is the module path."
+ MajorUnitPath string
}
diff --git a/internal/frontend/latest_version.go b/internal/frontend/latest_version.go
index 5dff358..b7ac118 100644
--- a/internal/frontend/latest_version.go
+++ b/internal/frontend/latest_version.go
@@ -6,13 +6,9 @@
import (
"context"
- "errors"
- "sync"
"golang.org/x/pkgsite/internal"
- "golang.org/x/pkgsite/internal/derrors"
"golang.org/x/pkgsite/internal/log"
- "golang.org/x/pkgsite/internal/middleware"
)
// GetLatestInfo returns various pieces of information about the latest
@@ -22,44 +18,16 @@
// fullPath and the modulePath.
// It returns empty strings on error.
// It is intended to be used as an argument to middleware.LatestVersions.
-func (s *Server) GetLatestInfo(ctx context.Context, unitPath, modulePath string) (latest middleware.LatestInfo) {
+func (s *Server) GetLatestInfo(ctx context.Context, unitPath, modulePath string) internal.LatestInfo {
// It is okay to use a different DataSource (DB connection) than the rest of the
// request, because this makes self-contained calls on the DB.
ds := s.getDataSource(ctx)
- var wg sync.WaitGroup
-
- wg.Add(1)
- go func() {
- defer wg.Done()
- var err error
- latest.MinorVersion, err = latestMinorVersion(ctx, ds, unitPath, internal.UnknownModulePath)
- if err != nil {
- log.Errorf(ctx, "latestMinorVersion: %v", err)
- }
- }()
-
- wg.Add(1)
- go func() {
- defer wg.Done()
- var err error
- latest.MajorModulePath, latest.MajorUnitPath, err = ds.GetLatestMajorVersion(ctx, unitPath, modulePath)
- if err != nil && !errors.Is(err, derrors.NotFound) {
- log.Errorf(ctx, "GetLatestMajorVersion: %v", err)
- }
- }()
-
- wg.Wait()
- return latest
-}
-
-// TODO(https://github.com/golang/go/issues/40107): this is currently tested in server_test.go, but
-// we should add tests for this function.
-func latestMinorVersion(ctx context.Context, ds internal.DataSource, unitPath, modulePath string) (_ string, err error) {
- defer derrors.Wrap(&err, "latestMinorVersion(ctx, %q, %q)", unitPath, modulePath)
- um, err := ds.GetUnitMeta(ctx, unitPath, modulePath, internal.LatestVersion)
+ latest, err := ds.GetLatestInfo(ctx, unitPath, modulePath)
if err != nil {
- return "", err
+ log.Errorf(ctx, "Server.GetLatestInfo: %v", err)
+ } else {
+ latest.MinorVersion = linkVersion(latest.MinorVersion, latest.MinorModulePath)
}
- return linkVersion(um.Version, um.ModulePath), nil
+ return latest
}
diff --git a/internal/localdatasource/datasource.go b/internal/localdatasource/datasource.go
index 20a8ffd..83e029a 100644
--- a/internal/localdatasource/datasource.go
+++ b/internal/localdatasource/datasource.go
@@ -170,12 +170,9 @@
return "", fmt.Errorf("%s not loaded: %w", pkgPath, derrors.NotFound)
}
-// GetLatestMajorVersion returns the latest major version and the full package path
-// of any major version found given the seriesPath and the v1Path.
-// When fetching local modules, version is not accounted for, so an empty
-// string is returned.
-func (ds *DataSource) GetLatestMajorVersion(ctx context.Context, seriesPath string, v1Path string) (string, string, error) {
- return "", "", nil
+// GetLatestInfo is not implemented.
+func (ds *DataSource) GetLatestInfo(ctx context.Context, unitPath, modulePath string) (internal.LatestInfo, error) {
+ return internal.LatestInfo{}, nil
}
// GetNestedModules is not implemented.
diff --git a/internal/middleware/latestversion.go b/internal/middleware/latestversion.go
index d7f2e0d..5960584 100644
--- a/internal/middleware/latestversion.go
+++ b/internal/middleware/latestversion.go
@@ -12,6 +12,7 @@
"strings"
"golang.org/x/mod/module"
+ "golang.org/x/pkgsite/internal"
"golang.org/x/pkgsite/internal/log"
)
@@ -26,14 +27,7 @@
// latestInfoRegexp extracts values needed to determine the latest-version badge from a page's HTML.
var latestInfoRegexp = regexp.MustCompile(`data-version="([^"]*)" data-mpath="([^"]*)" data-ppath="([^"]*)" data-pagetype="([^"]*)"`)
-// LatestInfo holds information about the latest versions and paths of a unit.
-type LatestInfo struct {
- MinorVersion string // latest minor version for unit path, regardless of module
- MajorModulePath string // path of latest version of module
- MajorUnitPath string // path of unit in latest version of module
-}
-
-type latestFunc func(ctx context.Context, unitPath, modulePath string) LatestInfo
+type latestFunc func(ctx context.Context, unitPath, modulePath string) internal.LatestInfo
// LatestVersions replaces the HTML placeholder values for the badge and banner
// that displays whether the version of the package or module being served is
diff --git a/internal/middleware/latestversion_test.go b/internal/middleware/latestversion_test.go
index 7639287..977eb89 100644
--- a/internal/middleware/latestversion_test.go
+++ b/internal/middleware/latestversion_test.go
@@ -11,6 +11,8 @@
"net/http"
"net/http/httptest"
"testing"
+
+ "golang.org/x/pkgsite/internal"
)
func TestLatestMinorVersion(t *testing.T) {
@@ -154,8 +156,13 @@
}
func constLatestFunc(minorVersion, majorModPath, majorPackagePath string) latestFunc {
- return func(context.Context, string, string) LatestInfo {
- return LatestInfo{minorVersion, majorModPath, majorPackagePath}
+ return func(context.Context, string, string) internal.LatestInfo {
+ return internal.LatestInfo{
+ MinorVersion: minorVersion,
+ MinorModulePath: "",
+ MajorModulePath: majorModPath,
+ MajorUnitPath: majorPackagePath,
+ }
}
}
diff --git a/internal/postgres/version.go b/internal/postgres/version.go
index 1a9c4c4..d1e100a 100644
--- a/internal/postgres/version.go
+++ b/internal/postgres/version.go
@@ -14,6 +14,7 @@
"golang.org/x/pkgsite/internal"
"golang.org/x/pkgsite/internal/derrors"
"golang.org/x/pkgsite/internal/version"
+ "golang.org/x/sync/errgroup"
)
// GetVersionsForPath returns a list of tagged versions sorted in
@@ -102,15 +103,46 @@
return strings.Join(vs, ", ")
}
-// GetLatestMajorVersion returns the latest module path and the full package path
+// GetLatestInfo returns the latest information about the unit in the module.
+// See internal.LatestInfo for documentation about the returned values.
+func (db *DB) GetLatestInfo(ctx context.Context, unitPath, modulePath string) (latest internal.LatestInfo, err error) {
+ defer derrors.Wrap(&err, "DB.GetLatestInfo(ctx, %q, %q)", unitPath, modulePath)
+
+ group, gctx := errgroup.WithContext(ctx)
+
+ group.Go(func() error {
+ um, err := db.GetUnitMeta(gctx, unitPath, internal.UnknownModulePath, internal.LatestVersion)
+ if err != nil {
+ return err
+ }
+ latest.MinorVersion = um.Version
+ latest.MinorModulePath = um.ModulePath
+ return nil
+ })
+ group.Go(func() (err error) {
+ latest.MajorModulePath, latest.MajorUnitPath, err = db.getLatestMajorVersion(gctx, unitPath, modulePath)
+ return err
+ })
+ group.Go(func() (err error) {
+ latest.UnitExistsAtMinor, err = db.getLatestMinorModuleVersionInfo(gctx, unitPath, modulePath)
+ return err
+ })
+
+ if err := group.Wait(); err != nil {
+ return internal.LatestInfo{}, err
+ }
+ return latest, nil
+}
+
+// getLatestMajorVersion returns the latest module path and the full package path
// of the latest version found, given the fullPath and the modulePath.
// For example, in the module path "github.com/casbin/casbin", there
// is another module path with a greater major version "github.com/casbin/casbin/v3".
// This function will return "github.com/casbin/casbin/v3" or the input module path
// if no later module path was found. It also returns the full package path at the
// latest module version if it exists. If not, it returns the module path.
-func (db *DB) GetLatestMajorVersion(ctx context.Context, fullPath, modulePath string) (_ string, _ string, err error) {
- defer derrors.Wrap(&err, "DB.GetLatestMajorVersion(ctx, %q, %q)", fullPath, modulePath)
+func (db *DB) getLatestMajorVersion(ctx context.Context, fullPath, modulePath string) (_ string, _ string, err error) {
+ defer derrors.Wrap(&err, "DB.getLatestMajorVersion(ctx, %q, %q)", fullPath, modulePath)
var (
modID int
@@ -143,24 +175,23 @@
}
}
-// GetLatestMinorModuleVersion returns the latest minor version of modulePath,
-// and whether unitPath exists at that version.
-func (db *DB) GetLatestMinorModuleVersion(ctx context.Context, unitPath, modulePath string) (version string, unitExists bool, err error) {
- defer derrors.Wrap(&err, "DB.GetLatestMinorVersion(ctx, %q, %q)", unitPath, modulePath)
+// getLatestMinorModuleVersion reports whether unitPath exists at the latest version of modulePath.
+func (db *DB) getLatestMinorModuleVersionInfo(ctx context.Context, unitPath, modulePath string) (unitExists bool, err error) {
+ defer derrors.Wrap(&err, "DB.getLatestMinorVersion(ctx, %q, %q)", unitPath, modulePath)
// Find the latest version of the module path.
var modID int
- q, args, err := orderByLatest(squirrel.Select("m.version", "m.id").
+ q, args, err := orderByLatest(squirrel.Select("m.id").
From("modules m").
Where(squirrel.Eq{"m.module_path": modulePath})).
Limit(1).
ToSql()
if err != nil {
- return "", false, err
+ return false, err
}
row := db.db.QueryRow(ctx, q, args...)
- if err := row.Scan(&version, &modID); err != nil {
- return "", false, err
+ if err := row.Scan(&modID); err != nil {
+ return false, err
}
// See if the unit path exists at that version.
@@ -168,10 +199,10 @@
err = db.db.QueryRow(ctx, `SELECT 1 FROM units WHERE path = $1 AND module_id = $2`, unitPath, modID).Scan(&x)
switch err {
case nil:
- return version, true, nil
+ return true, nil
case sql.ErrNoRows:
- return version, false, nil
+ return false, nil
default:
- return "", false, err
+ return false, err
}
}
diff --git a/internal/postgres/version_test.go b/internal/postgres/version_test.go
index d4713a5..b3adc90 100644
--- a/internal/postgres/version_test.go
+++ b/internal/postgres/version_test.go
@@ -6,8 +6,6 @@
import (
"context"
- "database/sql"
- "errors"
"fmt"
"testing"
@@ -231,16 +229,17 @@
}
}
-func TestGetLatestMajorVersion(t *testing.T) {
+func TestGetLatestInfo(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
defer cancel()
-
defer ResetTestDB(testDB, t)
+
for _, m := range []*internal.Module{
- sample.Module("foo.com/bar", "v1.1.1", "baz", "faz"),
- sample.Module("foo.com/bar/v2", "v2.0.5", "baz", "faz"),
- sample.Module("foo.com/bar/v3", "v3.0.1", "baz"),
- sample.Module("bar.com/foo", sample.VersionString, sample.Suffix),
+ sample.Module("a.com/M", "v1.1.1", "all", "most", "some", "one", "D/other"),
+ sample.Module("a.com/M", "v1.2.0", "all", "most"),
+ sample.Module("a.com/M/v2", "v2.0.5", "all", "most"),
+ sample.Module("a.com/M/v3", "v3.0.1", "all", "some"),
+ sample.Module("a.com/M/D", "v1.3.0", "other"),
} {
if err := testDB.InsertModule(ctx, m); err != nil {
t.Fatal(err)
@@ -248,93 +247,84 @@
}
for _, test := range []struct {
- fullPath string
- modulePath string
- wantModulePath string
- wantPackagePath string
- wantErr error
+ unit string
+ want internal.LatestInfo
}{
{
- fullPath: "foo.com/bar",
- modulePath: "foo.com/bar",
- wantModulePath: "foo.com/bar/v3",
- wantPackagePath: "foo.com/bar/v3",
+ // A unit that is the module.
+ "a.com/M",
+ internal.LatestInfo{
+ MinorVersion: "v1.2.0",
+ MinorModulePath: "a.com/M",
+ UnitExistsAtMinor: true,
+ MajorModulePath: "a.com/M/v3",
+ MajorUnitPath: "a.com/M/v3",
+ },
},
{
- fullPath: "bar.com/foo",
- modulePath: "bar.com/foo",
- wantModulePath: "bar.com/foo",
- wantPackagePath: "bar.com/foo",
+ // A unit that exists in all versions of the module.
+ "a.com/M/all",
+ internal.LatestInfo{
+ MinorVersion: "v1.2.0",
+ MinorModulePath: "a.com/M",
+ UnitExistsAtMinor: true,
+ MajorModulePath: "a.com/M/v3",
+ MajorUnitPath: "a.com/M/v3/all",
+ },
},
{
- fullPath: "boo.com/far",
- modulePath: "boo.com/far",
- wantErr: sql.ErrNoRows,
+ // A unit that exists in most versions, but not the latest major.
+ "a.com/M/most",
+ internal.LatestInfo{
+ MinorVersion: "v1.2.0",
+ MinorModulePath: "a.com/M",
+ UnitExistsAtMinor: true,
+ MajorModulePath: "a.com/M/v3",
+ MajorUnitPath: "a.com/M/v3",
+ },
},
{
- fullPath: "foo.com/bar/baz",
- modulePath: "foo.com/bar",
- wantModulePath: "foo.com/bar/v3",
- wantPackagePath: "foo.com/bar/v3/baz",
+ // A unit that does not exist at the latest minor version, but does at the latest major.
+ "a.com/M/some",
+ internal.LatestInfo{
+ MinorVersion: "v1.1.1",
+ MinorModulePath: "a.com/M",
+ UnitExistsAtMinor: false,
+ MajorModulePath: "a.com/M/v3",
+ MajorUnitPath: "a.com/M/v3/some",
+ },
},
{
- fullPath: "foo.com/bar/faz",
- modulePath: "foo.com/bar",
- wantModulePath: "foo.com/bar/v3",
- wantPackagePath: "foo.com/bar/v3",
+ // A unit that does not exist at the latest minor or major versions.
+ "a.com/M/one",
+ internal.LatestInfo{
+ MinorVersion: "v1.1.1",
+ MinorModulePath: "a.com/M",
+ UnitExistsAtMinor: false,
+ MajorModulePath: "a.com/M/v3",
+ MajorUnitPath: "a.com/M/v3",
+ },
+ },
+ {
+ // A unit whose latest minor version is in a different module.
+ "a.com/M/D/other",
+ internal.LatestInfo{
+ MinorVersion: "v1.3.0",
+ MinorModulePath: "a.com/M/D",
+ UnitExistsAtMinor: false,
+ MajorModulePath: "a.com/M/v3",
+ MajorUnitPath: "a.com/M/v3",
+ },
},
} {
- gotVersion, gotPath, err := testDB.GetLatestMajorVersion(ctx, test.fullPath, test.modulePath)
- if err != nil {
- if test.wantErr == nil {
- t.Fatalf("got unexpected error %v", err)
+ t.Run(test.unit, func(t *testing.T) {
+ got, err := testDB.GetLatestInfo(ctx, test.unit, "a.com/M")
+ if err != nil {
+ t.Fatal(err)
}
- if !errors.Is(err, test.wantErr) {
- t.Errorf("got err = %v, want Is(%v)", err, test.wantErr)
+ if diff := cmp.Diff(test.want, got); diff != "" {
+ t.Errorf("mismatch (-want, +got):\n%s", diff)
}
- }
- if gotVersion != test.wantModulePath || gotPath != test.wantPackagePath {
- t.Errorf("testDB.GetLatestMajorVersion(%v, %v) = (%v, %v), want = (%v, %v)", test.fullPath, test.modulePath, gotVersion, gotPath, test.wantModulePath, test.wantPackagePath)
- }
- }
-}
-
-func TestGetLatestMinorModuleVersion(t *testing.T) {
- ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
- defer cancel()
- defer ResetTestDB(testDB, t)
-
- const (
- modulePath = "foo.com/M"
- latestVersion = "v1.2.0"
- )
-
- for _, m := range []*internal.Module{
- sample.Module(modulePath, "v1.1.0", "p1", "p2"),
- sample.Module(modulePath, latestVersion, "p1"),
- sample.Module(modulePath+"/v2", "v2.0.5", "p1", "p2"),
- } {
- if err := testDB.InsertModule(ctx, m); err != nil {
- t.Fatal(err)
- }
- }
-
- for _, test := range []struct {
- unitSuffix string
- wantPresent bool
- }{
- {"p1", true},
- {"p2", false},
- } {
- gotVersion, gotPresent, err := testDB.GetLatestMinorModuleVersion(ctx, modulePath+"/"+test.unitSuffix, modulePath)
- if err != nil {
- t.Fatal(err)
- }
- if gotVersion != latestVersion {
- t.Errorf("%s: got version %q, want %q", test.unitSuffix, gotVersion, latestVersion)
- }
- if gotPresent != test.wantPresent {
- t.Errorf("%s: got present %t, want %t", test.unitSuffix, gotPresent, test.wantPresent)
- }
+ })
}
}
diff --git a/internal/proxydatasource/datasource.go b/internal/proxydatasource/datasource.go
index 6e9a3ed..bf453b3 100644
--- a/internal/proxydatasource/datasource.go
+++ b/internal/proxydatasource/datasource.go
@@ -176,11 +176,31 @@
return nil, fmt.Errorf("%q missing from module %s: %w", fullPath, m.ModulePath, derrors.NotFound)
}
-// GetLatestMajorVersion returns the latest module path and the full package path
+// GetLatestInfo returns latest information for unitPath and modulePath.
+func (ds *DataSource) GetLatestInfo(ctx context.Context, unitPath, modulePath string) (latest internal.LatestInfo, err error) {
+ defer derrors.Wrap(&err, "GetLatestInfo(ctx, %q, %q)", unitPath, modulePath)
+
+ um, err := ds.GetUnitMeta(ctx, unitPath, internal.UnknownModulePath, internal.LatestVersion)
+ if err != nil {
+ return latest, err
+ }
+ latest.MinorVersion = um.Version
+ latest.MinorModulePath = um.ModulePath
+
+ latest.MajorModulePath, latest.MajorUnitPath, err = ds.getLatestMajorVersion(ctx, unitPath, modulePath)
+ if err != nil {
+ return latest, err
+ }
+ // Do not try to discover whether the unit is in the latest minor version; assume it is.
+ latest.UnitExistsAtMinor = true
+ return latest, nil
+}
+
+// getLatestMajorVersion returns the latest module path and the full package path
// of the latest version found in the proxy by iterating through vN versions.
// This function does not attempt to find whether the full path exists
// in the new major version.
-func (ds *DataSource) GetLatestMajorVersion(ctx context.Context, fullPath, modulePath string) (_ string, _ string, err error) {
+func (ds *DataSource) getLatestMajorVersion(ctx context.Context, fullPath, modulePath string) (_ string, _ string, err error) {
// We are checking if the full path is valid so that we can forward the error if not.
seriesPath := internal.SeriesPathForModule(modulePath)
info, err := ds.proxyClient.GetInfo(ctx, seriesPath, internal.LatestVersion)
diff --git a/internal/proxydatasource/datasource_test.go b/internal/proxydatasource/datasource_test.go
index 5fee0d8..fd4545b 100644
--- a/internal/proxydatasource/datasource_test.go
+++ b/internal/proxydatasource/datasource_test.go
@@ -197,24 +197,36 @@
}
}
-func TestDataSource_GetLatestMajorVersion(t *testing.T) {
+func TestDataSource_GetLatestInfo(t *testing.T) {
t.Helper()
testModules := []*proxy.Module{
{
ModulePath: "foo.com/bar",
+ Version: "v1.1.0",
+ Files: map[string]string{
+ "baz.go": "package bar",
+ },
},
{
ModulePath: "foo.com/bar/v2",
+ Version: "v2.0.5",
},
{
ModulePath: "foo.com/bar/v3",
},
{
ModulePath: "bar.com/foo",
+ Version: "v1.1.0",
+ Files: map[string]string{
+ "baz.go": "package foo",
+ },
},
{
ModulePath: "incompatible.com/bar",
Version: "v2.1.1+incompatible",
+ Files: map[string]string{
+ "baz.go": "package bar",
+ },
},
{
ModulePath: "incompatible.com/bar/v3",
@@ -263,7 +275,7 @@
wantPackagePath: "incompatible.com/bar/v3",
},
} {
- gotVersion, gotPath, err := ds.GetLatestMajorVersion(ctx, test.fullPath, test.modulePath)
+ gotLatest, err := ds.GetLatestInfo(ctx, test.fullPath, test.modulePath)
if err != nil {
if test.wantErr == nil {
t.Fatalf("got unexpected error %v", err)
@@ -272,8 +284,9 @@
t.Errorf("got err = %v, want Is(%v)", err, test.wantErr)
}
}
- if gotVersion != test.wantModulePath || gotPath != test.wantPackagePath {
- t.Errorf("ds.GetLatestMajorVersion(%v, %v) = (%v, %v), want = (%v, %v)", test.fullPath, test.modulePath, gotVersion, gotPath, test.wantModulePath, test.wantPackagePath)
+ if gotLatest.MajorModulePath != test.wantModulePath || gotLatest.MajorUnitPath != test.wantPackagePath {
+ t.Errorf("ds.GetLatestMajorVersion(%v, %v) = (%v, %v), want = (%v, %v)",
+ test.fullPath, test.modulePath, gotLatest.MajorModulePath, gotLatest.MajorUnitPath, test.wantModulePath, test.wantPackagePath)
}
}
}