2019-10-08 07:03:40 +03:00
|
|
|
// 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"
|
|
|
|
"net/http"
|
|
|
|
"net/url"
|
|
|
|
"testing"
|
|
|
|
|
2020-07-06 16:58:43 +03:00
|
|
|
"github.com/google/go-cmp/cmp"
|
2020-04-21 23:51:29 +03:00
|
|
|
"golang.org/x/pkgsite/internal"
|
|
|
|
"golang.org/x/pkgsite/internal/stdlib"
|
2019-10-08 07:03:40 +03:00
|
|
|
)
|
|
|
|
|
2020-07-06 16:58:43 +03:00
|
|
|
func TestExtractURLPathInfo(t *testing.T) {
|
|
|
|
for _, test := range []struct {
|
|
|
|
in string
|
|
|
|
want *urlPathInfo // nil => want non-nil error
|
|
|
|
}{
|
|
|
|
{"", nil},
|
|
|
|
{
|
|
|
|
"/a.com",
|
|
|
|
&urlPathInfo{
|
|
|
|
fullPath: "a.com",
|
|
|
|
modulePath: internal.UnknownModulePath,
|
|
|
|
requestedVersion: internal.LatestVersion,
|
|
|
|
isModule: false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"/a.com@v1.2.3",
|
|
|
|
&urlPathInfo{
|
|
|
|
fullPath: "a.com",
|
|
|
|
modulePath: internal.UnknownModulePath,
|
|
|
|
requestedVersion: "v1.2.3",
|
|
|
|
isModule: false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"/a.com@v1.2.3/b",
|
|
|
|
&urlPathInfo{
|
|
|
|
fullPath: "a.com/b",
|
|
|
|
modulePath: "a.com",
|
|
|
|
requestedVersion: "v1.2.3",
|
|
|
|
isModule: false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"/encoding/json",
|
|
|
|
&urlPathInfo{
|
|
|
|
fullPath: "encoding/json",
|
|
|
|
modulePath: "std",
|
|
|
|
requestedVersion: internal.LatestVersion,
|
|
|
|
isModule: false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"/encoding/json@go1.12",
|
|
|
|
&urlPathInfo{
|
|
|
|
fullPath: "encoding/json",
|
|
|
|
modulePath: "std",
|
|
|
|
requestedVersion: "v1.12.0",
|
|
|
|
isModule: false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"/mod/a.com",
|
|
|
|
&urlPathInfo{
|
|
|
|
fullPath: "a.com",
|
|
|
|
modulePath: internal.UnknownModulePath,
|
|
|
|
requestedVersion: internal.LatestVersion,
|
|
|
|
isModule: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"/mod/a.com@v1.2.3",
|
|
|
|
&urlPathInfo{
|
|
|
|
fullPath: "a.com",
|
|
|
|
modulePath: internal.UnknownModulePath,
|
|
|
|
requestedVersion: "v1.2.3",
|
|
|
|
isModule: true,
|
|
|
|
},
|
|
|
|
},
|
2020-07-06 17:13:21 +03:00
|
|
|
{
|
|
|
|
"/moda.com",
|
|
|
|
&urlPathInfo{
|
|
|
|
fullPath: "moda.com",
|
|
|
|
modulePath: internal.UnknownModulePath,
|
|
|
|
requestedVersion: internal.LatestVersion,
|
|
|
|
isModule: false,
|
|
|
|
},
|
|
|
|
},
|
2020-07-06 16:58:43 +03:00
|
|
|
} {
|
|
|
|
got, err := extractURLPathInfo(test.in)
|
|
|
|
if err != nil {
|
|
|
|
if test.want != nil {
|
|
|
|
t.Errorf("%q: got error %v", test.in, err)
|
|
|
|
}
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if test.want == nil {
|
|
|
|
t.Errorf("%q: got no error, wanted one", test.in)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if diff := cmp.Diff(test.want, got, cmp.AllowUnexported(urlPathInfo{})); diff != "" {
|
|
|
|
t.Errorf("%q: mismatch (-want, +got):\n%s", test.in, diff)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-08 07:03:40 +03:00
|
|
|
func TestParseDetailsURLPath(t *testing.T) {
|
|
|
|
testCases := []struct {
|
2020-03-03 00:33:04 +03:00
|
|
|
name, url, wantModulePath, wantFullPath, wantVersion string
|
|
|
|
wantErr bool
|
2019-10-08 07:03:40 +03:00
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "latest",
|
|
|
|
url: "/github.com/hashicorp/vault/api",
|
2019-10-22 00:04:13 +03:00
|
|
|
wantModulePath: internal.UnknownModulePath,
|
2020-03-03 00:33:04 +03:00
|
|
|
wantFullPath: "github.com/hashicorp/vault/api",
|
2019-10-08 07:03:40 +03:00
|
|
|
wantVersion: internal.LatestVersion,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "package at version in nested module",
|
|
|
|
url: "/github.com/hashicorp/vault/api@v1.0.3",
|
2019-10-22 00:04:13 +03:00
|
|
|
wantModulePath: internal.UnknownModulePath,
|
2020-03-03 00:33:04 +03:00
|
|
|
wantFullPath: "github.com/hashicorp/vault/api",
|
2019-10-08 07:03:40 +03:00
|
|
|
wantVersion: "v1.0.3",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "package at version in parent module",
|
|
|
|
url: "/github.com/hashicorp/vault@v1.0.3/api",
|
|
|
|
wantModulePath: "github.com/hashicorp/vault",
|
2020-03-03 00:33:04 +03:00
|
|
|
wantFullPath: "github.com/hashicorp/vault/api",
|
2019-10-08 07:03:40 +03:00
|
|
|
wantVersion: "v1.0.3",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "package at version trailing slash",
|
|
|
|
url: "/github.com/hashicorp/vault/api@v1.0.3/",
|
2019-10-22 00:04:13 +03:00
|
|
|
wantModulePath: internal.UnknownModulePath,
|
2020-03-03 00:33:04 +03:00
|
|
|
wantFullPath: "github.com/hashicorp/vault/api",
|
2019-10-08 07:03:40 +03:00
|
|
|
wantVersion: "v1.0.3",
|
|
|
|
},
|
2020-03-03 00:33:04 +03:00
|
|
|
{
|
|
|
|
name: "stdlib",
|
|
|
|
url: "net/http",
|
|
|
|
wantModulePath: stdlib.ModulePath,
|
|
|
|
wantFullPath: "net/http",
|
|
|
|
wantVersion: internal.LatestVersion,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "stdlib at version",
|
|
|
|
url: "net/http@go1.14",
|
|
|
|
wantModulePath: stdlib.ModulePath,
|
|
|
|
wantFullPath: "net/http",
|
|
|
|
wantVersion: "go1.14",
|
|
|
|
},
|
2019-10-08 07:03:40 +03:00
|
|
|
{
|
|
|
|
name: "invalid url",
|
|
|
|
url: "/",
|
|
|
|
wantErr: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "invalid url missing module",
|
|
|
|
url: "@v1.0.0",
|
|
|
|
wantErr: true,
|
|
|
|
},
|
2020-03-03 00:33:04 +03:00
|
|
|
{
|
|
|
|
name: "explicit latest",
|
|
|
|
url: "/github.com/hashicorp/vault/api@latest",
|
|
|
|
wantErr: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "split stdlib",
|
|
|
|
url: "/net@go1.14/http",
|
|
|
|
wantErr: true,
|
|
|
|
},
|
2019-10-08 07:03:40 +03:00
|
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
|
|
u, parseErr := url.Parse(tc.url)
|
|
|
|
if parseErr != nil {
|
|
|
|
t.Errorf("url.Parse(%q): %v", tc.url, parseErr)
|
|
|
|
}
|
|
|
|
|
|
|
|
gotPkg, gotModule, gotVersion, err := parseDetailsURLPath(u.Path)
|
|
|
|
if (err != nil) != tc.wantErr {
|
|
|
|
t.Fatalf("parseDetailsURLPath(%q) error = (%v); want error %t)", u, err, tc.wantErr)
|
|
|
|
}
|
2020-03-03 00:33:04 +03:00
|
|
|
if !tc.wantErr && (tc.wantModulePath != gotModule || tc.wantVersion != gotVersion || tc.wantFullPath != gotPkg) {
|
2019-10-08 07:03:40 +03:00
|
|
|
t.Fatalf("parseDetailsURLPath(%q): %q, %q, %q, %v; want = %q, %q, %q, want err %t",
|
2020-03-03 00:33:04 +03:00
|
|
|
u, gotPkg, gotModule, gotVersion, err, tc.wantFullPath, tc.wantModulePath, tc.wantVersion, tc.wantErr)
|
2019-10-08 07:03:40 +03:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-01 17:28:42 +03:00
|
|
|
func TestValidatePathAndVersion(t *testing.T) {
|
2019-12-06 01:17:48 +03:00
|
|
|
tests := []struct {
|
|
|
|
path, version string
|
|
|
|
want int
|
|
|
|
}{
|
|
|
|
{"import/path", "v1.2.3", http.StatusOK},
|
|
|
|
{"import/path", "v1.2.bad", http.StatusBadRequest},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range tests {
|
2020-07-01 17:28:42 +03:00
|
|
|
err := validatePathAndVersion(context.Background(), fakeDataSource{}, test.path, test.version)
|
internal/frontend: handlers return error
Instead of serving an error page themselves, top-level handlers return
an error with the information for serving the error page.
This is a largely mechanical rewrite that removes a lot of clumsiness
from the handling code. For example, instead of
if err != nil {
log.Errorf(ctx, "frobbing: %v", err)
s.serveErrorPage(w, r, http.StatusInternalServerError, nil)
return
}
the code is both simpler and more idiomatic:
if err != nil {
return fmt.Errorf("frobbing: %v", err)
}
It is still possible to include an errorPage with the error, like so:
if err != nil {
return &serverError{
status: http.StatusBadRequest,
epage: &errorPage{...},
err: err,
}
}
Change-Id: Id076894b1cb912fe0731fdf6fbdb7b0e5b972bcb
Reviewed-on: https://team-review.git.corp.google.com/c/golang/discovery/+/686039
CI-Result: Cloud Build <devtools-proctor-result-processor@system.gserviceaccount.com>
Reviewed-by: Julie Qiu <julieqiu@google.com>
2020-03-08 18:05:56 +03:00
|
|
|
var got int
|
|
|
|
if err == nil {
|
|
|
|
got = 200
|
|
|
|
} else if serr, ok := err.(*serverError); ok {
|
|
|
|
got = serr.status
|
|
|
|
} else {
|
|
|
|
got = -1
|
|
|
|
}
|
|
|
|
if got != test.want {
|
2020-07-01 17:28:42 +03:00
|
|
|
t.Errorf("validatePathAndVersion(ctx, ds, %q, %q): got code %d, want %d", test.path, test.version, got, test.want)
|
2019-12-06 01:17:48 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-08 07:03:40 +03:00
|
|
|
type fakeDataSource struct {
|
2019-12-03 09:37:56 +03:00
|
|
|
internal.DataSource
|
2019-10-08 07:03:40 +03:00
|
|
|
}
|