blob: 11c886ada9e070c81953c96c1b9f28d84242bb6d [file] [log] [blame]
// 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 frontend
import (
"context"
"sort"
"testing"
"github.com/google/go-cmp/cmp"
"golang.org/x/pkgsite/internal"
"golang.org/x/pkgsite/internal/experiment"
"golang.org/x/pkgsite/internal/stdlib"
"golang.org/x/pkgsite/internal/testing/sample"
)
func TestExtractURLPathInfo(t *testing.T) {
for _, test := range []struct {
name, url string
want *urlPathInfo // nil => want non-nil error
}{
{
name: "path at latest",
url: "/github.com/hashicorp/vault/api",
want: &urlPathInfo{
modulePath: internal.UnknownModulePath,
fullPath: "github.com/hashicorp/vault/api",
requestedVersion: internal.LatestVersion,
},
},
{
name: "path at version in nested module",
url: "/github.com/hashicorp/vault/api@v1.0.3",
want: &urlPathInfo{
modulePath: internal.UnknownModulePath,
fullPath: "github.com/hashicorp/vault/api",
requestedVersion: "v1.0.3",
},
},
{
name: "package at version in parent module",
url: "/github.com/hashicorp/vault@v1.0.3/api",
want: &urlPathInfo{
modulePath: "github.com/hashicorp/vault",
fullPath: "github.com/hashicorp/vault/api",
requestedVersion: "v1.0.3",
},
},
{
name: "package at version trailing slash",
url: "/github.com/hashicorp/vault/api@v1.0.3/",
want: &urlPathInfo{
modulePath: internal.UnknownModulePath,
fullPath: "github.com/hashicorp/vault/api",
requestedVersion: "v1.0.3",
},
},
{
name: "stdlib module",
url: "/std",
want: &urlPathInfo{
modulePath: stdlib.ModulePath,
fullPath: "std",
requestedVersion: internal.LatestVersion,
},
},
{
name: "stdlib module at version",
url: "/std@go1.14",
want: &urlPathInfo{
modulePath: stdlib.ModulePath,
fullPath: "std",
requestedVersion: "v1.14.0",
},
},
{
name: "stdlib",
url: "/net/http",
want: &urlPathInfo{
modulePath: stdlib.ModulePath,
fullPath: "net/http",
requestedVersion: internal.LatestVersion,
},
},
{
name: "stdlib at version",
url: "/net/http@go1.14",
want: &urlPathInfo{
modulePath: stdlib.ModulePath,
fullPath: "net/http",
requestedVersion: "v1.14.0",
},
},
} {
t.Run(test.name, func(t *testing.T) {
got, err := extractURLPathInfo(test.url)
if err != nil {
t.Fatalf("extractURLPathInfo(%q): %v", test.url, err)
}
if diff := cmp.Diff(test.want, got, cmp.AllowUnexported(urlPathInfo{})); diff != "" {
t.Errorf("%q: mismatch (-want, +got):\n%s", test.url, diff)
}
})
}
}
func TestExtractURLPathInfo_Errors(t *testing.T) {
testCases := []struct {
name, url, wantModulePath, wantFullPath, wantVersion string
wantErr bool
}{
{
name: "invalid url",
url: "/",
wantErr: true,
},
{
name: "invalid url for github.com",
url: "/github.com/foo",
wantErr: true,
},
{
name: "invalid url missing module",
url: "@v1.0.0",
wantErr: true,
},
{
name: "explicit latest",
url: "/github.com/hashicorp/vault/api@latest",
wantErr: true,
},
{
name: "split stdlib",
url: "/net@go1.14/http",
wantErr: true,
},
}
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
got, err := extractURLPathInfo(test.url)
if (err != nil) != test.wantErr {
t.Fatalf("extractURLPathInfo(%q) error = (%v); want error %t)", test.url, err, test.wantErr)
}
if !test.wantErr && (test.wantModulePath != got.modulePath || test.wantVersion != got.requestedVersion || test.wantFullPath != got.fullPath) {
t.Fatalf("extractURLPathInfo(%q): %q, %q, %q, %v; want = %q, %q, %q, want err %t",
test.url, got.fullPath, got.modulePath, got.requestedVersion, err, test.wantFullPath, test.wantModulePath, test.wantVersion, test.wantErr)
}
})
}
}
func TestNewContextFromExps(t *testing.T) {
for _, test := range []struct {
mods []string
want []string
}{
{
mods: []string{"c", "a", "b"},
want: []string{"a", "b", "c"},
},
{
mods: []string{"d", "a"},
want: []string{"a", "b", "c", "d"},
},
{
mods: []string{"d", "!b", "!a", "c"},
want: []string{"c", "d"},
},
} {
ctx := experiment.NewContext(context.Background(), "a", "b", "c")
ctx = newContextFromExps(ctx, test.mods)
got := experiment.FromContext(ctx).Active()
sort.Strings(got)
if !cmp.Equal(got, test.want) {
t.Errorf("mods=%v:\ngot %v\nwant %v", test.mods, got, test.want)
}
}
}
func TestIsValidPath(t *testing.T) {
tests := []struct {
path string
want bool
}{
{"net/http", true},
{"github.com/foo", false},
{"github.com/foo", false},
{"/github.com/foo/bar", false},
{"github.com/foo/bar/", false},
{"github.com/foo/bar", true},
{"github.com/foo/bar/baz", true},
{"golang.org/dl", true},
{"golang.org/x", false},
{"golang.org/x/tools", true},
{"golang.org/x/tools/go/packages", true},
}
for _, test := range tests {
got := isValidPath(test.path)
if got != test.want {
t.Errorf("isValidPath(ctx, ds, %q) = %t, want %t", test.path, got, test.want)
}
}
}
func TestIsSupportedVersion(t *testing.T) {
tests := []struct {
path, version string
want bool
}{
{sample.ModulePath, "v1.2.3", true},
{sample.ModulePath, "v1.2.bad", false},
{sample.ModulePath, "latest", true},
{sample.ModulePath, "master", true},
{sample.ModulePath, "main", true},
{"net/http", "v1.2.3", true}, // isSupportedVersion expects the goTag is already converted to semver
{"net/http", "v1.2.3.bad", false},
{"net/http", "latest", true},
{"net/http", "master", false},
{"net/http", "main", false},
}
for _, test := range tests {
got := isSupportedVersion(test.path, test.version)
if got != test.want {
t.Errorf("isSupportedVersion(ctx, ds, %q, %q) = %t, want %t", test.path, test.version, got, test.want)
}
}
}