зеркало из https://github.com/golang/pkgsite.git
1112 строки
38 KiB
Go
1112 строки
38 KiB
Go
// 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 worker
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
"sort"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/google/go-cmp/cmp"
|
|
"github.com/google/go-cmp/cmp/cmpopts"
|
|
"github.com/google/safehtml/testconversions"
|
|
"golang.org/x/pkgsite/internal"
|
|
"golang.org/x/pkgsite/internal/derrors"
|
|
"golang.org/x/pkgsite/internal/fetch"
|
|
"golang.org/x/pkgsite/internal/licenses"
|
|
"golang.org/x/pkgsite/internal/postgres"
|
|
"golang.org/x/pkgsite/internal/proxy"
|
|
"golang.org/x/pkgsite/internal/source"
|
|
"golang.org/x/pkgsite/internal/stdlib"
|
|
"golang.org/x/pkgsite/internal/testing/testhelper"
|
|
)
|
|
|
|
var sourceTimeout = 1 * time.Second
|
|
|
|
var buildConstraintsMod = &proxy.TestModule{
|
|
ModulePath: "build.constraints/module",
|
|
Files: map[string]string{
|
|
"LICENSE": testhelper.BSD0License,
|
|
"cpu/cpu.go": `
|
|
// Package cpu implements processor feature detection
|
|
// used by the Go standard library.
|
|
package cpu`,
|
|
"cpu/cpu_arm.go": "package cpu\n\nconst CacheLinePadSize = 1",
|
|
"cpu/cpu_arm64.go": "package cpu\n\nconst CacheLinePadSize = 2",
|
|
"cpu/cpu_x86.go": "// +build 386 amd64 amd64p32\n\npackage cpu\n\nconst CacheLinePadSize = 3",
|
|
"ignore/ignore.go": "// +build ignore\n\npackage ignore",
|
|
},
|
|
}
|
|
|
|
var html = testconversions.MakeHTMLForTest
|
|
|
|
// Check that when the proxy says it does not have module@version,
|
|
// we delete it from the database.
|
|
func TestFetchAndUpdateState_NotFound(t *testing.T) {
|
|
ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
|
|
defer cancel()
|
|
|
|
defer postgres.ResetTestDB(testDB, t)
|
|
|
|
const (
|
|
modulePath = "github.com/take/down"
|
|
version = "v1.0.0"
|
|
)
|
|
|
|
proxyClient, teardownProxy := proxy.SetupTestProxy(t, []*proxy.TestModule{
|
|
{
|
|
ModulePath: modulePath,
|
|
Version: version,
|
|
Files: map[string]string{
|
|
"foo/foo.go": "// Package foo\npackage foo\n\nconst Foo = 42",
|
|
"README.md": "This is a readme",
|
|
"LICENSE": testhelper.MITLicense,
|
|
},
|
|
},
|
|
})
|
|
sourceClient := source.NewClient(sourceTimeout)
|
|
|
|
checkStatus := func(want int) {
|
|
t.Helper()
|
|
vs, err := testDB.GetModuleVersionState(ctx, modulePath, version)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if vs.Status != want {
|
|
t.Fatalf("testDB.GetModuleVersionState(ctx, %q, %q): status = %v, want = %d", modulePath, version, vs.Status, want)
|
|
}
|
|
if want != http.StatusNotFound {
|
|
vm, err := testDB.GetVersionMap(ctx, modulePath, version)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if vm.Status != want {
|
|
t.Fatalf("testDB.GetVersionMap(ctx, %q, %q): status = %d, want = %d", modulePath, version, vm.Status, want)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Fetch a module@version that the proxy serves successfully.
|
|
if _, err := FetchAndUpdateState(ctx, modulePath, version, proxyClient, sourceClient, testDB, "appVersionLabel"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// Verify that the module status is recorded correctly, and that the version is in the DB.
|
|
checkStatus(http.StatusOK)
|
|
|
|
if _, err := testDB.GetModuleInfo(ctx, modulePath, version); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
gotStates, err := testDB.GetPackageVersionStatesForModule(ctx, modulePath, version)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
wantStates := []*internal.PackageVersionState{
|
|
{
|
|
PackagePath: "github.com/take/down/foo",
|
|
ModulePath: modulePath,
|
|
Version: version,
|
|
Status: http.StatusOK,
|
|
},
|
|
}
|
|
if diff := cmp.Diff(wantStates, gotStates); diff != "" {
|
|
t.Errorf("testDB.GetPackageVersionStatesForModule(ctx, %q, %q) mismatch (-want +got):\n%s", modulePath, version, diff)
|
|
}
|
|
|
|
teardownProxy()
|
|
|
|
// Take down the module, by having the proxy serve a 404/410 for it.
|
|
proxyMux := proxy.TestProxy([]*proxy.TestModule{}) // serve no versions, not even the defaults.
|
|
proxyMux.HandleFunc(fmt.Sprintf("/%s/@v/%s.info", modulePath, version),
|
|
func(w http.ResponseWriter, r *http.Request) { http.Error(w, "taken down", http.StatusGone) })
|
|
proxyClient, teardownProxy2 := proxy.TestProxyServer(t, proxyMux)
|
|
defer teardownProxy2()
|
|
|
|
// Now fetch it again.
|
|
if code, _ := FetchAndUpdateState(ctx, modulePath, version, proxyClient, sourceClient, testDB, "appVersionLabel"); code != http.StatusNotFound {
|
|
t.Fatalf("FetchAndUpdateState(ctx, %q, %q, proxyClient, sourceClient, testDB): got code %d, want 404/410", modulePath, version, code)
|
|
}
|
|
|
|
// The new state should have a status of Not Found.
|
|
checkStatus(http.StatusNotFound)
|
|
|
|
gotStates, err = testDB.GetPackageVersionStatesForModule(ctx, modulePath, version)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if diff := cmp.Diff(wantStates, gotStates); diff != "" {
|
|
t.Errorf("testDB.GetPackageVersionStatesForModule(ctx, %q, %q) mismatch (-want +got):\n%s", modulePath, version, diff)
|
|
}
|
|
|
|
// The module should no longer be in the database:
|
|
// - It shouldn't be in the modules table. That also covers licenses, packages and paths tables
|
|
// via foreign key constraints with ON DELETE CASCADE.
|
|
// - It shouldn't be in other tables like search_documents and the various imports tables.
|
|
if _, err := testDB.GetModuleInfo(ctx, modulePath, version); !errors.Is(err, derrors.NotFound) {
|
|
t.Fatalf("GetModuleInfo: got %v, want NotFound", err)
|
|
}
|
|
|
|
checkNotInTable := func(table, column string) {
|
|
q := fmt.Sprintf("SELECT 1 FROM %s WHERE %s = $1 LIMIT 1", table, column)
|
|
var x int
|
|
err := testDB.Underlying().QueryRow(ctx, q, modulePath).Scan(&x)
|
|
if err != sql.ErrNoRows {
|
|
t.Errorf("table %s: got %v, want ErrNoRows", table, err)
|
|
}
|
|
}
|
|
|
|
checkNotInTable("search_documents", "module_path")
|
|
checkNotInTable("imports_unique", "from_module_path")
|
|
checkNotInTable("imports", "from_module_path")
|
|
}
|
|
|
|
func TestFetchAndUpdateState_Excluded(t *testing.T) {
|
|
// Check that an excluded module is not processed, and is marked excluded in module_version_states.
|
|
ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
|
|
defer cancel()
|
|
|
|
defer postgres.ResetTestDB(testDB, t)
|
|
|
|
proxyClient, teardownProxy := proxy.SetupTestProxy(t, nil)
|
|
defer teardownProxy()
|
|
sourceClient := source.NewClient(sourceTimeout)
|
|
|
|
const (
|
|
modulePath = "github.com/my/module"
|
|
version = "v1.0.0"
|
|
)
|
|
if err := testDB.InsertExcludedPrefix(ctx, "github.com/my/m", "user", "for testing"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
checkModuleNotFound(t, ctx, modulePath, version, proxyClient, sourceClient, http.StatusForbidden, derrors.Excluded)
|
|
}
|
|
|
|
func checkModuleNotFound(t *testing.T, ctx context.Context, modulePath, version string, proxyClient *proxy.Client, sourceClient *source.Client, wantCode int, wantErr error) {
|
|
t.Helper()
|
|
code, err := FetchAndUpdateState(ctx, modulePath, version, proxyClient, sourceClient, testDB, "appVersionLabel")
|
|
if code != wantCode || !errors.Is(err, wantErr) {
|
|
t.Fatalf("got %d, %v; want %d, Is(err, %v)", code, err, wantCode, wantErr)
|
|
}
|
|
_, err = testDB.GetModuleInfo(ctx, modulePath, version)
|
|
if !errors.Is(err, derrors.NotFound) {
|
|
t.Fatalf("got %v, want Is(NotFound)", err)
|
|
}
|
|
vs, err := testDB.GetModuleVersionState(ctx, modulePath, version)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if vs.Status != wantCode {
|
|
t.Fatalf("testDB.GetModuleVersionState(ctx, %q, %q): status=%v, want %d", modulePath, version, vs.Status, wantCode)
|
|
}
|
|
_, err = testDB.GetVersionMap(ctx, modulePath, version)
|
|
if !errors.Is(err, derrors.NotFound) {
|
|
t.Fatalf("got %v, want Is(NotFound)", err)
|
|
}
|
|
}
|
|
|
|
func TestFetchAndUpdateState_BadRequestedVersion(t *testing.T) {
|
|
ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
|
|
defer cancel()
|
|
|
|
defer postgres.ResetTestDB(testDB, t)
|
|
|
|
proxyClient, teardownProxy := proxy.SetupTestProxy(t, []*proxy.TestModule{buildConstraintsMod})
|
|
defer teardownProxy()
|
|
sourceClient := source.NewClient(sourceTimeout)
|
|
|
|
const (
|
|
modulePath = "build.constraints/module"
|
|
version = "badversion"
|
|
want = http.StatusNotFound
|
|
)
|
|
|
|
code, _ := FetchAndUpdateState(ctx, modulePath, version, proxyClient, sourceClient, testDB, "appVersionLabel")
|
|
if code != want {
|
|
t.Fatalf("got code %d, want %d", code, want)
|
|
}
|
|
_, err := testDB.GetModuleVersionState(ctx, modulePath, version)
|
|
if !errors.Is(err, derrors.NotFound) {
|
|
t.Fatal(err)
|
|
}
|
|
vm, err := testDB.GetVersionMap(ctx, modulePath, version)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if vm.Status != http.StatusNotFound {
|
|
t.Fatalf("testDB.GetVersionMap(ctx, %q, %q): status=%v, want %d", modulePath, version, vm.Status, http.StatusNotFound)
|
|
}
|
|
}
|
|
|
|
func TestFetchAndUpdateState_Incomplete(t *testing.T) {
|
|
// Check that we store the special "incomplete" status in module_version_states.
|
|
ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
|
|
defer cancel()
|
|
|
|
defer postgres.ResetTestDB(testDB, t)
|
|
|
|
proxyClient, teardownProxy := proxy.SetupTestProxy(t, []*proxy.TestModule{buildConstraintsMod})
|
|
defer teardownProxy()
|
|
sourceClient := source.NewClient(sourceTimeout)
|
|
|
|
const (
|
|
modulePath = "build.constraints/module"
|
|
version = "v1.0.0"
|
|
want = hasIncompletePackagesCode
|
|
)
|
|
|
|
code, err := FetchAndUpdateState(ctx, modulePath, version, proxyClient, sourceClient, testDB, "appVersionLabel")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if code != want {
|
|
t.Fatalf("got code %d, want %d", code, want)
|
|
}
|
|
vs, err := testDB.GetModuleVersionState(ctx, modulePath, version)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if vs.Status != want {
|
|
t.Fatalf("testDB.GetModuleVersionState(ctx, %q, %q): status=%v, want %d", modulePath, version, vs.Status, want)
|
|
}
|
|
vm, err := testDB.GetVersionMap(ctx, modulePath, version)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if vm.Status != want {
|
|
t.Fatalf("testDB.GetVersionMap(ctx, %q, %q): status=%v, want %d", modulePath, version, vm.Status, want)
|
|
}
|
|
gotStates, err := testDB.GetPackageVersionStatesForModule(ctx, modulePath, version)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
wantStates := []*internal.PackageVersionState{
|
|
{
|
|
PackagePath: "build.constraints/module/cpu",
|
|
ModulePath: "build.constraints/module",
|
|
Version: "v1.0.0",
|
|
Status: 200,
|
|
},
|
|
{
|
|
PackagePath: "build.constraints/module/ignore",
|
|
ModulePath: "build.constraints/module",
|
|
Version: "v1.0.0",
|
|
Status: 600,
|
|
},
|
|
}
|
|
sort.Slice(gotStates, func(i, j int) bool {
|
|
return gotStates[i].PackagePath < gotStates[j].PackagePath
|
|
})
|
|
if diff := cmp.Diff(wantStates, gotStates); diff != "" {
|
|
t.Errorf("testDB.GetPackageVersionStatesForModule(ctx, %q, %q) mismatch (-want +got):\n%s", modulePath, version, diff)
|
|
}
|
|
}
|
|
|
|
func TestFetchAndUpdateState_Mismatch(t *testing.T) {
|
|
// Check that an excluded module is not processed, and is marked excluded in module_version_states.
|
|
ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
|
|
defer cancel()
|
|
|
|
defer postgres.ResetTestDB(testDB, t)
|
|
|
|
const (
|
|
modulePath = "github.com/mis/match"
|
|
version = "v1.0.0"
|
|
goModPath = "other"
|
|
)
|
|
proxyClient, teardownProxy := proxy.SetupTestProxy(t, []*proxy.TestModule{
|
|
{
|
|
ModulePath: modulePath,
|
|
Version: version,
|
|
Files: map[string]string{
|
|
"go.mod": "module " + goModPath,
|
|
"foo/foo.go": "// Package foo\npackage foo\n\nconst Foo = 42",
|
|
},
|
|
},
|
|
})
|
|
defer teardownProxy()
|
|
sourceClient := source.NewClient(sourceTimeout)
|
|
|
|
code, err := FetchAndUpdateState(ctx, modulePath, version, proxyClient, sourceClient, testDB, "appVersionLabel")
|
|
wantErr := derrors.AlternativeModule
|
|
wantCode := derrors.ToHTTPStatus(wantErr)
|
|
if code != wantCode || !errors.Is(err, wantErr) {
|
|
t.Fatalf("got %d, %v; want %d, Is(err, derrors.AlternativeModule)", code, err, wantCode)
|
|
}
|
|
_, err = testDB.GetModuleInfo(ctx, modulePath, version)
|
|
if !errors.Is(err, derrors.NotFound) {
|
|
t.Fatalf("got %v, want Is(NotFound)", err)
|
|
}
|
|
vs, err := testDB.GetModuleVersionState(ctx, modulePath, version)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if vs.Status != wantCode {
|
|
t.Errorf("testDB.GetModuleVersionState(ctx, %q, %q): status=%v, want %d", modulePath, version, vs.Status, wantCode)
|
|
}
|
|
|
|
if vs.GoModPath != goModPath {
|
|
t.Errorf("testDB.GetModuleVersionState(ctx, %q, %q): goModPath=%q, want %q", modulePath, version, vs.GoModPath, goModPath)
|
|
}
|
|
|
|
_, err = testDB.GetVersionMap(ctx, modulePath, version)
|
|
if !errors.Is(err, derrors.NotFound) {
|
|
t.Fatalf("got %v, want Is(NotFound)", err)
|
|
}
|
|
}
|
|
|
|
func TestFetchAndUpdateState_DeleteOlder(t *testing.T) {
|
|
// Check that fetching an alternative module deletes all older versions of that
|
|
// module from search_documents (but not versions).
|
|
ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
|
|
defer cancel()
|
|
|
|
defer postgres.ResetTestDB(testDB, t)
|
|
|
|
const (
|
|
modulePath = "github.com/m"
|
|
mismatchVersion = "v1.0.0"
|
|
olderVersion = "v0.9.0"
|
|
)
|
|
|
|
proxyClient, teardownProxy := proxy.SetupTestProxy(t, []*proxy.TestModule{
|
|
{
|
|
// mismatched version; will cause deletion
|
|
ModulePath: modulePath,
|
|
Version: mismatchVersion,
|
|
Files: map[string]string{
|
|
"go.mod": "module other",
|
|
"foo/foo.go": "package foo",
|
|
},
|
|
},
|
|
{
|
|
// older version; should be deleted
|
|
ModulePath: modulePath,
|
|
Version: olderVersion,
|
|
Files: map[string]string{
|
|
"foo/foo.go": "package foo",
|
|
},
|
|
},
|
|
})
|
|
defer teardownProxy()
|
|
sourceClient := source.NewClient(sourceTimeout)
|
|
|
|
if _, err := FetchAndUpdateState(ctx, modulePath, olderVersion, proxyClient, sourceClient, testDB, "appVersionLabel"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
gotModule, gotVersion, gotFound := postgres.GetFromSearchDocuments(ctx, t, testDB, modulePath+"/foo")
|
|
if !gotFound || gotModule != modulePath || gotVersion != olderVersion {
|
|
t.Fatalf("got (%q, %q, %t), want (%q, %q, true)", gotModule, gotVersion, gotFound, modulePath, olderVersion)
|
|
}
|
|
|
|
code, _ := FetchAndUpdateState(ctx, modulePath, mismatchVersion, proxyClient, sourceClient, testDB, "appVersionLabel")
|
|
if want := derrors.ToHTTPStatus(derrors.AlternativeModule); code != want {
|
|
t.Fatalf("got %d, want %d", code, want)
|
|
}
|
|
|
|
if _, _, gotFound := postgres.GetFromSearchDocuments(ctx, t, testDB, modulePath+"/foo"); gotFound {
|
|
t.Fatal("older version found in search documents")
|
|
}
|
|
}
|
|
|
|
func TestSkipIncompletePackage(t *testing.T) {
|
|
ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
|
|
defer cancel()
|
|
defer postgres.ResetTestDB(testDB, t)
|
|
badModule := map[string]string{
|
|
"foo/foo.go": "// Package foo\npackage foo\n\nconst Foo = 42",
|
|
"README.md": "This is a readme",
|
|
"LICENSE": testhelper.MITLicense,
|
|
}
|
|
var bigFile strings.Builder
|
|
bigFile.WriteString("package bar\n")
|
|
bigFile.WriteString("const Bar = 123\n")
|
|
for bigFile.Len() <= fetch.MaxFileSize {
|
|
bigFile.WriteString("// All work and no play makes Jack a dull boy.\n")
|
|
}
|
|
badModule["bar/bar.go"] = bigFile.String()
|
|
var (
|
|
modulePath = "github.com/my/module"
|
|
version = "v1.0.0"
|
|
)
|
|
proxyClient, teardownProxy := proxy.SetupTestProxy(t, []*proxy.TestModule{
|
|
{
|
|
ModulePath: modulePath,
|
|
Version: version,
|
|
Files: badModule,
|
|
},
|
|
})
|
|
defer teardownProxy()
|
|
sourceClient := source.NewClient(sourceTimeout)
|
|
|
|
code, err := FetchAndUpdateState(ctx, modulePath, version, proxyClient, sourceClient, testDB, "appVersionLabel")
|
|
if err != nil {
|
|
t.Fatalf("FetchAndUpdateState(%q, %q, %v, %v, %v): %v", modulePath, version, proxyClient, sourceClient, testDB, err)
|
|
}
|
|
if code != hasIncompletePackagesCode {
|
|
t.Errorf("FetchAndUpdateState(%q, %q, %v, %v, %v): hasIncompletePackages=false, want true",
|
|
modulePath, version, proxyClient, sourceClient, testDB)
|
|
}
|
|
|
|
pkgFoo := modulePath + "/foo"
|
|
if _, err := testDB.LegacyGetPackage(ctx, pkgFoo, internal.UnknownModulePath, version); err != nil {
|
|
t.Errorf("got %v, want nil", err)
|
|
}
|
|
pkgBar := modulePath + "/bar"
|
|
if _, err := testDB.LegacyGetPackage(ctx, pkgBar, internal.UnknownModulePath, version); !errors.Is(err, derrors.NotFound) {
|
|
t.Errorf("got %v, want NotFound", err)
|
|
}
|
|
}
|
|
|
|
// Test that large string literals and slices are trimmed when
|
|
// rendering documentation, rather than being included verbatim.
|
|
//
|
|
// This makes it viable for us to show documentation for packages that
|
|
// would otherwise exceed HTML size limit and not get shown at all.
|
|
func TestTrimLargeCode(t *testing.T) {
|
|
ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
|
|
defer cancel()
|
|
defer postgres.ResetTestDB(testDB, t)
|
|
trimmedModule := map[string]string{
|
|
"foo/foo.go": "// Package foo\npackage foo\n\nconst Foo = 42",
|
|
"LICENSE": testhelper.MITLicense,
|
|
}
|
|
// Create a package with a large string literal. It should not be included verbatim.
|
|
{
|
|
var b strings.Builder
|
|
b.WriteString("package bar\n\n")
|
|
b.WriteString("const Bar = `\n")
|
|
for b.Len() <= fetch.MaxDocumentationHTML {
|
|
b.WriteString("All work and no play makes Jack a dull boy.\n")
|
|
}
|
|
b.WriteString("`\n")
|
|
trimmedModule["bar/bar.go"] = b.String()
|
|
}
|
|
// Create a package with a large slice. It should not be included verbatim.
|
|
{
|
|
var b strings.Builder
|
|
b.WriteString("package baz\n\n")
|
|
b.WriteString("var Baz = []string{\n")
|
|
for b.Len() <= fetch.MaxDocumentationHTML {
|
|
b.WriteString("`All work and no play makes Jack a dull boy.`,\n")
|
|
}
|
|
b.WriteString("}\n")
|
|
trimmedModule["baz/baz.go"] = b.String()
|
|
}
|
|
var (
|
|
modulePath = "github.com/my/module"
|
|
version = "v1.0.0"
|
|
)
|
|
proxyClient, teardownProxy := proxy.SetupTestProxy(t, []*proxy.TestModule{
|
|
{
|
|
ModulePath: modulePath,
|
|
Version: version,
|
|
Files: trimmedModule,
|
|
},
|
|
})
|
|
defer teardownProxy()
|
|
sourceClient := source.NewClient(sourceTimeout)
|
|
|
|
code, err := FetchAndUpdateState(ctx, modulePath, version, proxyClient, sourceClient, testDB, "appVersionLabel")
|
|
if err != nil {
|
|
t.Fatalf("FetchAndUpdateState(%q, %q, %v, %v, %v): %v", modulePath, version, proxyClient, sourceClient, testDB, err)
|
|
}
|
|
if code == hasIncompletePackagesCode {
|
|
t.Errorf("FetchAndUpdateState(%q, %q, %v, %v, %v): hasIncompletePackages=true, want false",
|
|
modulePath, version, proxyClient, sourceClient, testDB)
|
|
}
|
|
|
|
pkgFoo := modulePath + "/foo"
|
|
if _, err := testDB.LegacyGetPackage(ctx, pkgFoo, internal.UnknownModulePath, version); err != nil {
|
|
t.Errorf("got %v, want nil", err)
|
|
}
|
|
pkgBar := modulePath + "/bar"
|
|
if _, err := testDB.LegacyGetPackage(ctx, pkgBar, internal.UnknownModulePath, version); err != nil {
|
|
t.Errorf("got %v, want nil", err)
|
|
}
|
|
pkgBaz := modulePath + "/baz"
|
|
if _, err := testDB.LegacyGetPackage(ctx, pkgBaz, internal.UnknownModulePath, version); err != nil {
|
|
t.Errorf("got %v, want nil", err)
|
|
}
|
|
}
|
|
|
|
func TestFetch_V1Path(t *testing.T) {
|
|
ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
|
|
defer cancel()
|
|
defer postgres.ResetTestDB(testDB, t)
|
|
proxyClient, tearDown := proxy.SetupTestProxy(t, []*proxy.TestModule{
|
|
{
|
|
ModulePath: "my.mod/foo",
|
|
Version: "v1.0.0",
|
|
Files: map[string]string{
|
|
"foo.go": "package foo\nconst Foo = 41",
|
|
"LICENSE": testhelper.MITLicense,
|
|
},
|
|
},
|
|
})
|
|
defer tearDown()
|
|
sourceClient := source.NewClient(sourceTimeout)
|
|
if _, err := FetchAndUpdateState(ctx, "my.mod/foo", "v1.0.0", proxyClient, sourceClient, testDB, "appVersionLabel"); err != nil {
|
|
t.Fatalf("FetchAndUpdateState: %v", err)
|
|
}
|
|
pkg, err := testDB.LegacyGetPackage(ctx, "my.mod/foo", internal.UnknownModulePath, "v1.0.0")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if got, want := pkg.V1Path, "my.mod/foo"; got != want {
|
|
t.Errorf("V1Path = %q, want %q", got, want)
|
|
}
|
|
}
|
|
|
|
func TestReFetch(t *testing.T) {
|
|
// This test checks that re-fetching a version will cause its data to be
|
|
// overwritten. This is achieved by fetching against two different versions
|
|
// of the (fake) proxy, though in reality the most likely cause of changes to
|
|
// a version is updates to our data model or fetch logic.
|
|
ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
|
|
defer cancel()
|
|
defer postgres.ResetTestDB(testDB, t)
|
|
|
|
var (
|
|
modulePath = "github.com/my/module"
|
|
version = "v1.0.0"
|
|
pkgFoo = "github.com/my/module/foo"
|
|
foo = map[string]string{
|
|
"foo/foo.go": "// Package foo\npackage foo\n\nconst Foo = 42",
|
|
"README.md": "This is a readme",
|
|
"LICENSE": testhelper.MITLicense,
|
|
}
|
|
pkgBar = "github.com/my/module/bar"
|
|
foobar = map[string]string{
|
|
"foo/foo.go": "// Package foo\npackage foo\n\nconst Foo = 42",
|
|
"README.md": "This is a readme",
|
|
"LICENSE": testhelper.MITLicense,
|
|
"bar/bar.go": "// Package bar\npackage bar\n\nconst Bar = 21",
|
|
}
|
|
)
|
|
|
|
// First fetch and insert a version containing package foo, and verify that
|
|
// foo can be retrieved.
|
|
proxyClient, teardownProxy := proxy.SetupTestProxy(t, []*proxy.TestModule{
|
|
{
|
|
ModulePath: modulePath,
|
|
Version: version,
|
|
Files: foo,
|
|
},
|
|
})
|
|
defer teardownProxy()
|
|
sourceClient := source.NewClient(sourceTimeout)
|
|
if _, err := FetchAndUpdateState(ctx, modulePath, version, proxyClient, sourceClient, testDB, "appVersionLabel"); err != nil {
|
|
t.Fatalf("FetchAndUpdateState(%q, %q, %v, %v, %v): %v", modulePath, version, proxyClient, sourceClient, testDB, err)
|
|
}
|
|
|
|
if _, err := testDB.LegacyGetPackage(ctx, pkgFoo, internal.UnknownModulePath, version); err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
// Now re-fetch and verify that contents were overwritten.
|
|
proxyClient, teardownProxy = proxy.SetupTestProxy(t, []*proxy.TestModule{
|
|
{
|
|
ModulePath: modulePath,
|
|
Version: version,
|
|
Files: foobar,
|
|
},
|
|
})
|
|
defer teardownProxy()
|
|
|
|
if _, err := FetchAndUpdateState(ctx, modulePath, version, proxyClient, sourceClient, testDB, "appVersionLabel"); err != nil {
|
|
t.Fatalf("FetchAndUpdateState(%q, %q, %v, %v, %v): %v", modulePath, version, proxyClient, sourceClient, testDB, err)
|
|
}
|
|
want := &internal.LegacyVersionedPackage{
|
|
LegacyModuleInfo: internal.LegacyModuleInfo{
|
|
ModuleInfo: internal.ModuleInfo{
|
|
ModulePath: modulePath,
|
|
Version: version,
|
|
CommitTime: time.Date(2019, 1, 30, 0, 0, 0, 0, time.UTC),
|
|
VersionType: "release",
|
|
IsRedistributable: true,
|
|
HasGoMod: false,
|
|
SourceInfo: source.NewGitHubInfo("https://github.com/my/module", "", "v1.0.0"),
|
|
},
|
|
LegacyReadmeFilePath: "README.md",
|
|
LegacyReadmeContents: "This is a readme",
|
|
},
|
|
LegacyPackage: internal.LegacyPackage{
|
|
Path: "github.com/my/module/bar",
|
|
Name: "bar",
|
|
Synopsis: "Package bar",
|
|
DocumentationHTML: html("Bar returns the string "bar"."),
|
|
V1Path: "github.com/my/module/bar",
|
|
Licenses: []*licenses.Metadata{
|
|
{Types: []string{"MIT"}, FilePath: "LICENSE"},
|
|
},
|
|
IsRedistributable: true,
|
|
GOOS: "linux",
|
|
GOARCH: "amd64",
|
|
},
|
|
}
|
|
got, err := testDB.LegacyGetPackage(ctx, pkgBar, internal.UnknownModulePath, version)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if diff := cmp.Diff(want, got, cmpopts.IgnoreFields(internal.LegacyPackage{}, "DocumentationHTML"), cmp.AllowUnexported(source.Info{})); diff != "" {
|
|
t.Errorf("testDB.LegacyGetPackage(ctx, %q, %q) mismatch (-want +got):\n%s", pkgBar, version, diff)
|
|
}
|
|
|
|
// Now re-fetch and verify that contents were overwritten.
|
|
proxyClient, teardownProxy = proxy.SetupTestProxy(t, []*proxy.TestModule{
|
|
{
|
|
ModulePath: modulePath,
|
|
Version: version,
|
|
Files: foo,
|
|
},
|
|
})
|
|
defer teardownProxy()
|
|
if _, err := FetchAndUpdateState(ctx, modulePath, version, proxyClient, sourceClient, testDB, "appVersionLabel"); !errors.Is(err, derrors.DBModuleInsertInvalid) {
|
|
t.Fatalf("FetchAndUpdateState(%q, %q, %v, %v, %v): %v", modulePath, version, proxyClient, sourceClient, testDB, err)
|
|
}
|
|
}
|
|
|
|
var testProxyCommitTime = time.Date(2019, 1, 30, 0, 0, 0, 0, time.UTC)
|
|
|
|
func TestFetchAndInsertModule(t *testing.T) {
|
|
ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
|
|
defer cancel()
|
|
|
|
const goRepositoryURLPrefix = "https://github.com/golang"
|
|
|
|
stdlib.UseTestData = true
|
|
defer func() { stdlib.UseTestData = false }()
|
|
|
|
proxyClient, teardownProxy := proxy.SetupTestProxy(t, []*proxy.TestModule{
|
|
buildConstraintsMod,
|
|
{
|
|
ModulePath: "github.com/my/module",
|
|
Files: map[string]string{
|
|
"go.mod": "module github.com/my/module\n\ngo 1.12",
|
|
"LICENSE": testhelper.BSD0License,
|
|
"README.md": "README FILE FOR TESTING.",
|
|
"bar/LICENSE": testhelper.MITLicense,
|
|
"bar/bar.go": `
|
|
// package bar
|
|
package bar
|
|
|
|
// Bar returns the string "bar".
|
|
func Bar() string {
|
|
return "bar"
|
|
}`,
|
|
"foo/LICENSE.md": testhelper.MITLicense,
|
|
"foo/foo.go": `
|
|
// package foo
|
|
package foo
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/my/module/bar"
|
|
)
|
|
|
|
// FooBar returns the string "foo bar".
|
|
func FooBar() string {
|
|
return fmt.Sprintf("foo %s", bar.Bar())
|
|
}`,
|
|
},
|
|
},
|
|
|
|
{
|
|
ModulePath: "nonredistributable.mod/module",
|
|
Files: map[string]string{
|
|
"go.mod": "module nonredistributable.mod/module\n\ngo 1.13",
|
|
"LICENSE": testhelper.BSD0License,
|
|
"README.md": "README FILE FOR TESTING.",
|
|
"bar/baz/COPYING": testhelper.MITLicense,
|
|
"bar/baz/baz.go": `
|
|
// package baz
|
|
package baz
|
|
|
|
// Baz returns the string "baz".
|
|
func Baz() string {
|
|
return "baz"
|
|
}
|
|
`,
|
|
"bar/LICENSE": testhelper.MITLicense,
|
|
"bar/bar.go": `
|
|
// package bar
|
|
package bar
|
|
|
|
// Bar returns the string "bar".
|
|
func Bar() string {
|
|
return "bar"
|
|
}`,
|
|
"foo/LICENSE.md": testhelper.UnknownLicense,
|
|
"foo/foo.go": `
|
|
// package foo
|
|
package foo
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/my/module/bar"
|
|
)
|
|
|
|
// FooBar returns the string "foo bar".
|
|
func FooBar() string {
|
|
return fmt.Sprintf("foo %s", bar.Bar())
|
|
}`,
|
|
},
|
|
},
|
|
})
|
|
defer teardownProxy()
|
|
|
|
myModuleV100 := &internal.LegacyVersionedPackage{
|
|
LegacyModuleInfo: internal.LegacyModuleInfo{
|
|
ModuleInfo: internal.ModuleInfo{
|
|
ModulePath: "github.com/my/module",
|
|
Version: "v1.0.0",
|
|
CommitTime: testProxyCommitTime,
|
|
SourceInfo: source.NewGitHubInfo("https://github.com/my/module", "", "v1.0.0"),
|
|
VersionType: "release",
|
|
IsRedistributable: true,
|
|
HasGoMod: true,
|
|
},
|
|
LegacyReadmeFilePath: "README.md",
|
|
LegacyReadmeContents: "README FILE FOR TESTING.",
|
|
},
|
|
LegacyPackage: internal.LegacyPackage{
|
|
Path: "github.com/my/module/bar",
|
|
Name: "bar",
|
|
Synopsis: "package bar",
|
|
DocumentationHTML: html("Bar returns the string "bar"."),
|
|
V1Path: "github.com/my/module/bar",
|
|
Licenses: []*licenses.Metadata{
|
|
{Types: []string{"BSD-0-Clause"}, FilePath: "LICENSE"},
|
|
{Types: []string{"MIT"}, FilePath: "bar/LICENSE"},
|
|
},
|
|
IsRedistributable: true,
|
|
GOOS: "linux",
|
|
GOARCH: "amd64",
|
|
},
|
|
}
|
|
|
|
testCases := []struct {
|
|
modulePath string
|
|
version string
|
|
pkg string
|
|
want *internal.LegacyVersionedPackage
|
|
moreWantDoc []string // Additional substrings we expect to see in DocumentationHTML.
|
|
dontWantDoc []string // Substrings we expect not to see in DocumentationHTML.
|
|
}{
|
|
{
|
|
modulePath: "github.com/my/module",
|
|
version: "v1.0.0",
|
|
pkg: "github.com/my/module/bar",
|
|
want: myModuleV100,
|
|
},
|
|
{
|
|
modulePath: "github.com/my/module",
|
|
version: internal.LatestVersion,
|
|
pkg: "github.com/my/module/bar",
|
|
want: myModuleV100,
|
|
},
|
|
{
|
|
// nonredistributable.mod/module is redistributable, as are its
|
|
// packages bar and bar/baz. But package foo is not.
|
|
modulePath: "nonredistributable.mod/module",
|
|
version: "v1.0.0",
|
|
pkg: "nonredistributable.mod/module/bar/baz",
|
|
want: &internal.LegacyVersionedPackage{
|
|
LegacyModuleInfo: internal.LegacyModuleInfo{
|
|
ModuleInfo: internal.ModuleInfo{
|
|
ModulePath: "nonredistributable.mod/module",
|
|
Version: "v1.0.0",
|
|
CommitTime: testProxyCommitTime,
|
|
VersionType: "release",
|
|
SourceInfo: nil,
|
|
IsRedistributable: true,
|
|
HasGoMod: true,
|
|
},
|
|
LegacyReadmeFilePath: "README.md",
|
|
LegacyReadmeContents: "README FILE FOR TESTING.",
|
|
},
|
|
LegacyPackage: internal.LegacyPackage{
|
|
Path: "nonredistributable.mod/module/bar/baz",
|
|
Name: "baz",
|
|
Synopsis: "package baz",
|
|
DocumentationHTML: html("Baz returns the string "baz"."),
|
|
V1Path: "nonredistributable.mod/module/bar/baz",
|
|
Licenses: []*licenses.Metadata{
|
|
{Types: []string{"BSD-0-Clause"}, FilePath: "LICENSE"},
|
|
{Types: []string{"MIT"}, FilePath: "bar/LICENSE"},
|
|
{Types: []string{"MIT"}, FilePath: "bar/baz/COPYING"},
|
|
},
|
|
IsRedistributable: true,
|
|
GOOS: "linux",
|
|
GOARCH: "amd64",
|
|
},
|
|
},
|
|
}, {
|
|
modulePath: "nonredistributable.mod/module",
|
|
version: "v1.0.0",
|
|
pkg: "nonredistributable.mod/module/foo",
|
|
want: &internal.LegacyVersionedPackage{
|
|
LegacyModuleInfo: internal.LegacyModuleInfo{
|
|
ModuleInfo: internal.ModuleInfo{
|
|
ModulePath: "nonredistributable.mod/module",
|
|
Version: "v1.0.0",
|
|
CommitTime: testProxyCommitTime,
|
|
VersionType: "release",
|
|
SourceInfo: nil,
|
|
IsRedistributable: true,
|
|
HasGoMod: true,
|
|
},
|
|
LegacyReadmeFilePath: "README.md",
|
|
LegacyReadmeContents: "README FILE FOR TESTING.",
|
|
},
|
|
LegacyPackage: internal.LegacyPackage{
|
|
Path: "nonredistributable.mod/module/foo",
|
|
Name: "foo",
|
|
Synopsis: "",
|
|
V1Path: "nonredistributable.mod/module/foo",
|
|
Licenses: []*licenses.Metadata{
|
|
{Types: []string{"BSD-0-Clause"}, FilePath: "LICENSE"},
|
|
{Types: []string{"UNKNOWN"}, FilePath: "foo/LICENSE.md"},
|
|
},
|
|
GOOS: "linux",
|
|
GOARCH: "amd64",
|
|
IsRedistributable: false,
|
|
},
|
|
},
|
|
}, {
|
|
modulePath: "std",
|
|
version: "v1.12.5",
|
|
pkg: "context",
|
|
want: &internal.LegacyVersionedPackage{
|
|
LegacyModuleInfo: internal.LegacyModuleInfo{
|
|
ModuleInfo: internal.ModuleInfo{
|
|
ModulePath: "std",
|
|
Version: "v1.12.5",
|
|
CommitTime: stdlib.TestCommitTime,
|
|
VersionType: "release",
|
|
SourceInfo: source.NewGitHubInfo(goRepositoryURLPrefix+"/go", "src", "go1.12.5"),
|
|
IsRedistributable: true,
|
|
HasGoMod: true,
|
|
},
|
|
LegacyReadmeFilePath: "README.md",
|
|
LegacyReadmeContents: "# The Go Programming Language\n",
|
|
},
|
|
LegacyPackage: internal.LegacyPackage{
|
|
Path: "context",
|
|
Name: "context",
|
|
Synopsis: "Package context defines the Context type, which carries deadlines, cancelation signals, and other request-scoped values across API boundaries and between processes.",
|
|
DocumentationHTML: html("This example demonstrates the use of a cancelable context to prevent a\ngoroutine leak."),
|
|
V1Path: "context",
|
|
Licenses: []*licenses.Metadata{
|
|
{
|
|
Types: []string{"BSD-3-Clause"},
|
|
FilePath: "LICENSE",
|
|
},
|
|
},
|
|
IsRedistributable: true,
|
|
GOOS: "linux",
|
|
GOARCH: "amd64",
|
|
},
|
|
},
|
|
}, {
|
|
modulePath: "std",
|
|
version: "v1.12.5",
|
|
pkg: "builtin",
|
|
want: &internal.LegacyVersionedPackage{
|
|
LegacyModuleInfo: internal.LegacyModuleInfo{
|
|
ModuleInfo: internal.ModuleInfo{
|
|
ModulePath: "std",
|
|
Version: "v1.12.5",
|
|
CommitTime: stdlib.TestCommitTime,
|
|
VersionType: "release",
|
|
SourceInfo: source.NewGitHubInfo(goRepositoryURLPrefix+"/go", "src", "go1.12.5"),
|
|
IsRedistributable: true,
|
|
HasGoMod: true,
|
|
},
|
|
|
|
LegacyReadmeFilePath: "README.md",
|
|
LegacyReadmeContents: "# The Go Programming Language\n",
|
|
},
|
|
LegacyPackage: internal.LegacyPackage{
|
|
Path: "builtin",
|
|
Name: "builtin",
|
|
Synopsis: "Package builtin provides documentation for Go's predeclared identifiers.",
|
|
DocumentationHTML: html("int64 is the set of all signed 64-bit integers."),
|
|
V1Path: "builtin",
|
|
Licenses: []*licenses.Metadata{
|
|
{
|
|
Types: []string{"BSD-3-Clause"},
|
|
FilePath: "LICENSE",
|
|
},
|
|
},
|
|
IsRedistributable: true,
|
|
GOOS: "linux",
|
|
GOARCH: "amd64",
|
|
},
|
|
},
|
|
}, {
|
|
modulePath: "std",
|
|
version: "v1.12.5",
|
|
pkg: "encoding/json",
|
|
want: &internal.LegacyVersionedPackage{
|
|
LegacyModuleInfo: internal.LegacyModuleInfo{
|
|
ModuleInfo: internal.ModuleInfo{
|
|
ModulePath: "std",
|
|
Version: "v1.12.5",
|
|
CommitTime: stdlib.TestCommitTime,
|
|
VersionType: "release",
|
|
SourceInfo: source.NewGitHubInfo(goRepositoryURLPrefix+"/go", "src", "go1.12.5"),
|
|
IsRedistributable: true,
|
|
HasGoMod: true,
|
|
},
|
|
LegacyReadmeFilePath: "README.md",
|
|
LegacyReadmeContents: "# The Go Programming Language\n",
|
|
},
|
|
LegacyPackage: internal.LegacyPackage{
|
|
Path: "encoding/json",
|
|
Name: "json",
|
|
Synopsis: "Package json implements encoding and decoding of JSON as defined in RFC 7159.",
|
|
DocumentationHTML: html("The mapping between JSON and Go values is described\nin the documentation for the Marshal and Unmarshal functions."),
|
|
V1Path: "encoding/json",
|
|
Licenses: []*licenses.Metadata{
|
|
{
|
|
Types: []string{"BSD-3-Clause"},
|
|
FilePath: "LICENSE",
|
|
},
|
|
},
|
|
IsRedistributable: true,
|
|
GOOS: "linux",
|
|
GOARCH: "amd64",
|
|
},
|
|
},
|
|
moreWantDoc: []string{
|
|
"Example (CustomMarshalJSON)",
|
|
`<summary class="Documentation-exampleDetailsHeader">Example (CustomMarshalJSON) <a href="#example-package-CustomMarshalJSON">¶</a></summary>`,
|
|
"Package (CustomMarshalJSON)",
|
|
`<li><a href="#example-package-CustomMarshalJSON">Package (CustomMarshalJSON)</a></li>`,
|
|
"Decoder.Decode (Stream)",
|
|
`<li><a href="#example-Decoder.Decode-Stream">Decoder.Decode (Stream)</a></li>`,
|
|
},
|
|
dontWantDoc: []string{
|
|
"Example (customMarshalJSON)",
|
|
"Package (customMarshalJSON)",
|
|
"Decoder.Decode (stream)",
|
|
},
|
|
}, {
|
|
modulePath: "build.constraints/module",
|
|
version: "v1.0.0",
|
|
pkg: "build.constraints/module/cpu",
|
|
want: &internal.LegacyVersionedPackage{
|
|
LegacyModuleInfo: internal.LegacyModuleInfo{
|
|
ModuleInfo: internal.ModuleInfo{
|
|
ModulePath: "build.constraints/module",
|
|
Version: "v1.0.0",
|
|
CommitTime: testProxyCommitTime,
|
|
VersionType: "release",
|
|
SourceInfo: nil,
|
|
IsRedistributable: true,
|
|
HasGoMod: false,
|
|
},
|
|
},
|
|
LegacyPackage: internal.LegacyPackage{
|
|
Path: "build.constraints/module/cpu",
|
|
Name: "cpu",
|
|
Synopsis: "Package cpu implements processor feature detection used by the Go standard library.",
|
|
DocumentationHTML: html("const CacheLinePadSize = 3"),
|
|
V1Path: "build.constraints/module/cpu",
|
|
Licenses: []*licenses.Metadata{
|
|
{Types: []string{"BSD-0-Clause"}, FilePath: "LICENSE"},
|
|
},
|
|
IsRedistributable: true,
|
|
GOOS: "linux",
|
|
GOARCH: "amd64",
|
|
},
|
|
},
|
|
dontWantDoc: []string{
|
|
"const CacheLinePadSize = 1",
|
|
"const CacheLinePadSize = 2",
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, test := range testCases {
|
|
t.Run(test.pkg, func(t *testing.T) {
|
|
defer postgres.ResetTestDB(testDB, t)
|
|
|
|
sourceClient := source.NewClient(sourceTimeout)
|
|
|
|
if _, err := FetchAndUpdateState(ctx, test.modulePath, test.version, proxyClient, sourceClient, testDB, "appVersionLabel"); err != nil {
|
|
t.Fatalf("FetchAndUpdateState(%q, %q, %v, %v, %v): %v", test.modulePath, test.version, proxyClient, sourceClient, testDB, err)
|
|
}
|
|
|
|
gotModuleInfo, err := testDB.GetModuleInfo(ctx, test.modulePath, test.want.Version)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if diff := cmp.Diff(test.want.ModuleInfo, *gotModuleInfo, cmp.AllowUnexported(source.Info{})); diff != "" {
|
|
t.Fatalf("testDB.GetModuleInfo(ctx, %q, %q) mismatch (-want +got):\n%s", test.modulePath, test.version, diff)
|
|
}
|
|
|
|
gotPkg, err := testDB.LegacyGetPackage(ctx, test.pkg, internal.UnknownModulePath, test.version)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
sort.Slice(gotPkg.Licenses, func(i, j int) bool {
|
|
return gotPkg.Licenses[i].FilePath < gotPkg.Licenses[j].FilePath
|
|
})
|
|
if diff := cmp.Diff(test.want, gotPkg, cmpopts.IgnoreFields(internal.LegacyPackage{}, "DocumentationHTML"), cmp.AllowUnexported(source.Info{})); diff != "" {
|
|
t.Errorf("testDB.LegacyGetPackage(ctx, %q, %q) mismatch (-want +got):\n%s", test.pkg, test.version, diff)
|
|
}
|
|
if got, want := gotPkg.DocumentationHTML.String(), test.want.DocumentationHTML.String(); len(want) == 0 && len(got) != 0 {
|
|
t.Errorf("got non-empty documentation but want empty:\ngot: %q\nwant: %q", got, want)
|
|
} else if !strings.Contains(got, want) {
|
|
t.Errorf("got documentation doesn't contain wanted documentation substring:\ngot: %q\nwant (substring): %q", got, want)
|
|
}
|
|
for _, want := range test.moreWantDoc {
|
|
if got := gotPkg.DocumentationHTML.String(); !strings.Contains(got, want) {
|
|
t.Errorf("got documentation doesn't contain wanted documentation substring:\ngot: %q\nwant (substring): %q", got, want)
|
|
}
|
|
}
|
|
for _, dontWant := range test.dontWantDoc {
|
|
if got := gotPkg.DocumentationHTML.String(); strings.Contains(got, dontWant) {
|
|
t.Errorf("got documentation contains unwanted documentation substring:\ngot: %q\ndontWant (substring): %q", got, dontWant)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestFetchAndInsertModuleTimeout(t *testing.T) {
|
|
defer postgres.ResetTestDB(testDB, t)
|
|
|
|
proxyClient, teardownProxy := proxy.SetupTestProxy(t, nil)
|
|
defer teardownProxy()
|
|
sourceClient := source.NewClient(sourceTimeout)
|
|
|
|
name := "my.mod/version"
|
|
version := "v1.0.0"
|
|
wantErrString := "deadline exceeded"
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 0)
|
|
defer cancel()
|
|
_, err := FetchAndUpdateState(ctx, name, version, proxyClient, sourceClient, testDB, "appVersionLabel")
|
|
if err == nil || !strings.Contains(err.Error(), wantErrString) {
|
|
t.Fatalf("FetchAndUpdateState(%q, %q, %v, %v, %v) returned error %v, want error containing %q",
|
|
name, version, proxyClient, sourceClient, testDB, err, wantErrString)
|
|
}
|
|
}
|