blob: b83bb48485d0cfcfed0c39811be6204d00c53388 [file] [log] [blame]
// Copyright 2020 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 localdatasource
import (
"context"
"errors"
"os"
"testing"
"time"
"github.com/google/go-cmp/cmp"
"github.com/google/safehtml/template"
"golang.org/x/pkgsite/internal"
"golang.org/x/pkgsite/internal/derrors"
"golang.org/x/pkgsite/internal/fetch"
"golang.org/x/pkgsite/internal/godoc/dochtml"
"golang.org/x/pkgsite/internal/licenses"
"golang.org/x/pkgsite/internal/stdlib"
"golang.org/x/pkgsite/internal/testing/testhelper"
)
var (
ctx context.Context
cancel func()
datasource *DataSource
)
func setup(t *testing.T) (context.Context, func(), *DataSource, error) {
t.Helper()
// Setup only once.
if datasource != nil {
return ctx, cancel, datasource, nil
}
licenses.OmitExceptions = true
modules := []map[string]string{
{
"go.mod": "module github.com/my/module\n\ngo 1.12",
"LICENSE": testhelper.BSD0License,
"README.md": "README FILE FOR TESTING.",
"bar/COPYING": testhelper.MITLicense,
"bar/README.md": "Another README FILE FOR TESTING.",
"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())
}`,
},
{
"go.mod": "module github.com/no/license\n\ngo 1.12",
"LICENSE": "unknown",
"bar/bar.go": `
// package bar
package bar
// Bar returns the string "bar".
func Bar() string {
return "bar"
}`,
},
}
dochtml.LoadTemplates(template.TrustedSourceFromConstant("../../static/doc"))
datasource = New()
ctx, cancel = context.WithTimeout(context.Background(), 20*time.Second)
for _, module := range modules {
directory, err := testhelper.CreateTestDirectory(module)
if err != nil {
return ctx, func() { cancel() }, nil, err
}
defer os.RemoveAll(directory)
err = datasource.Load(ctx, directory)
if err != nil {
return ctx, func() { cancel() }, nil, err
}
}
return ctx, func() { cancel() }, datasource, nil
}
func TestGetUnitMeta(t *testing.T) {
ctx, cancel, ds, err := setup(t)
if err != nil {
t.Fatalf("setup failed: %s", err.Error())
}
defer cancel()
for _, test := range []struct {
path, modulePath string
want *internal.UnitMeta
wantErr error
}{
{
path: "github.com/my/module",
modulePath: "github.com/my/module",
want: &internal.UnitMeta{
Path: "github.com/my/module",
ModuleInfo: internal.ModuleInfo{
ModulePath: "github.com/my/module",
Version: fetch.LocalVersion,
CommitTime: fetch.LocalCommitTime,
IsRedistributable: true,
},
IsRedistributable: true,
},
},
{
path: "github.com/my/module/bar",
modulePath: "github.com/my/module",
want: &internal.UnitMeta{
Path: "github.com/my/module/bar",
Name: "bar",
ModuleInfo: internal.ModuleInfo{
ModulePath: "github.com/my/module",
Version: fetch.LocalVersion,
CommitTime: fetch.LocalCommitTime,
IsRedistributable: true,
},
IsRedistributable: true,
},
},
{
path: "github.com/my/module/foo",
modulePath: "github.com/my/module",
want: &internal.UnitMeta{
Path: "github.com/my/module/foo",
Name: "foo",
ModuleInfo: internal.ModuleInfo{
ModulePath: "github.com/my/module",
IsRedistributable: true,
Version: fetch.LocalVersion,
CommitTime: fetch.LocalCommitTime,
},
IsRedistributable: true,
},
},
{
path: "github.com/my/module/bar",
modulePath: internal.UnknownModulePath,
want: &internal.UnitMeta{
Path: "github.com/my/module/bar",
Name: "bar",
IsRedistributable: true,
ModuleInfo: internal.ModuleInfo{
ModulePath: "github.com/my/module",
Version: fetch.LocalVersion,
CommitTime: fetch.LocalCommitTime,
IsRedistributable: true,
},
},
},
{
path: "github.com/not/loaded",
modulePath: internal.UnknownModulePath,
wantErr: derrors.NotFound,
},
{
path: "net/http",
modulePath: stdlib.ModulePath,
wantErr: derrors.NotFound,
},
} {
t.Run(test.path, func(t *testing.T) {
got, err := ds.GetUnitMeta(ctx, test.path, test.modulePath, fetch.LocalVersion)
if test.wantErr != nil {
if !errors.Is(err, test.wantErr) {
t.Errorf("GetUnitMeta(%q, %q): %v; wantErr = %v)", test.path, test.modulePath, err, test.wantErr)
}
} else {
if err != nil {
t.Fatal(err)
}
if diff := cmp.Diff(test.want, got); diff != "" {
t.Errorf("mismatch (-want +got):\n%s", diff)
}
}
})
}
}
func TestGetUnit(t *testing.T) {
// This is a simple test to verify that data is fetched correctly. The
// return value of FetchResult is tested in internal/fetch so no need
// to repeat it.
ctx, cancel, ds, err := setup(t)
if err != nil {
t.Fatalf("setup failed: %s", err.Error())
}
defer cancel()
for _, test := range []struct {
path, modulePath string
wantLoaded bool
}{
{
path: "github.com/my/module",
modulePath: "github.com/my/module",
wantLoaded: true,
},
{
path: "github.com/my/module/foo",
modulePath: "github.com/my/module",
wantLoaded: true,
},
{
path: "github.com/no/license/bar",
modulePath: "github.com/no/license",
wantLoaded: true,
},
{
path: "github.com/not/loaded",
modulePath: internal.UnknownModulePath,
},
} {
t.Run(test.path, func(t *testing.T) {
um := &internal.UnitMeta{
Path: test.path,
ModuleInfo: internal.ModuleInfo{ModulePath: test.modulePath},
}
got, err := ds.GetUnit(ctx, um, 0, internal.BuildContext{})
if !test.wantLoaded {
if err == nil {
t.Fatalf("returned not loaded module %q", test.path)
}
return
}
if err != nil {
t.Fatalf("failed for %q: %q", test.path, err.Error())
}
if gotEmpty := (got.Documentation == nil && got.Readme == nil); gotEmpty {
t.Errorf("%q: gotEmpty = %t", test.path, gotEmpty)
}
})
}
}