cmd/go: delete internal packages moved to x/mod

This change deletes several internal packages, replaces imports to
them with the equivalent golang.org/x/mod packages, updates x/mod, and
re-runs 'go mod vendor'.

Packages are replaced as follows:

cmd/go/internal/modfile → golang.org/x/mod/modfile
cmd/go/internal/module → golang.org/x/mod/module
cmd/go/internal/semver → golang.org/x/mod/semver
cmd/go/internal/sumdb → golang.org/x/mod/sumdb
cmd/go/internal/dirhash → golang.org/x/mod/sumdb/dirhash
cmd/go/internal/note → golang.org/x/mod/sumdb/note
cmd/go/internal/tlog → golang.org/x/mod/sumdb/tlog

Updates #31761
Fixes #34924

Change-Id: Ie3bf677bb0be49af969f654a0214243a6547eb57
Reviewed-on: https://go-review.googlesource.com/c/go/+/202698
Run-TryBot: Jay Conrod <jayconrod@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
This commit is contained in:
Jay Conrod 2019-10-16 15:26:15 -04:00
parent cc47b0d2cd
commit 1fb7d5472e
104 changed files with 4421 additions and 2990 deletions

View File

@ -6,7 +6,8 @@ require (
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f
github.com/ianlancetaylor/demangle v0.0.0-20180524225900-fc6590592b44 // indirect
golang.org/x/arch v0.0.0-20190815191158-8a70ba74b3a1
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550
golang.org/x/mod v0.1.1-0.20191029194233-18c3998b6452
golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82 // indirect
golang.org/x/tools v0.0.0-20191018203202-04252eccb9d5
)

View File

@ -5,11 +5,15 @@ github.com/ianlancetaylor/demangle v0.0.0-20180524225900-fc6590592b44/go.mod h1:
golang.org/x/arch v0.0.0-20190815191158-8a70ba74b3a1 h1:A71BZbKSu+DtCNry/x5JKn20C+64DirDHmePEA8k0FY=
golang.org/x/arch v0.0.0-20190815191158-8a70ba74b3a1/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c h1:Vj5n4GlwjmQteupaxJ9+0FNOmBrHfq7vN4btdGoDZgI=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/mod v0.1.1-0.20191029194233-18c3998b6452 h1:ES2W0A+AqNBCkgWga22gheu9IUDjq3TDmeCdY1A7jhk=
golang.org/x/mod v0.1.1-0.20191029194233-18c3998b6452/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82 h1:vsphBvatvfbhlb4PO1BYSr9dzugGxJ/SQHoNufZJq1w=
golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
@ -17,4 +21,6 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20191018203202-04252eccb9d5 h1:TFUhCYbgGMOGnRxJv+j0iAcxCjk8oGjXXWNejQBhUUs=
golang.org/x/tools v0.0.0-20191018203202-04252eccb9d5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=

View File

@ -1,135 +0,0 @@
// Copyright 2018 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 dirhash
import (
"archive/zip"
"crypto/sha256"
"encoding/base64"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"strings"
"testing"
)
func h(s string) string {
return fmt.Sprintf("%x", sha256.Sum256([]byte(s)))
}
func htop(k string, s string) string {
sum := sha256.Sum256([]byte(s))
return k + ":" + base64.StdEncoding.EncodeToString(sum[:])
}
func TestHash1(t *testing.T) {
files := []string{"xyz", "abc"}
open := func(name string) (io.ReadCloser, error) {
return ioutil.NopCloser(strings.NewReader("data for " + name)), nil
}
want := htop("h1", fmt.Sprintf("%s %s\n%s %s\n", h("data for abc"), "abc", h("data for xyz"), "xyz"))
out, err := Hash1(files, open)
if err != nil {
t.Fatal(err)
}
if out != want {
t.Errorf("Hash1(...) = %s, want %s", out, want)
}
_, err = Hash1([]string{"xyz", "a\nbc"}, open)
if err == nil {
t.Error("Hash1: expected error on newline in filenames")
}
}
func TestHashDir(t *testing.T) {
dir, err := ioutil.TempDir("", "dirhash-test-")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(dir)
if err := ioutil.WriteFile(filepath.Join(dir, "xyz"), []byte("data for xyz"), 0666); err != nil {
t.Fatal(err)
}
if err := ioutil.WriteFile(filepath.Join(dir, "abc"), []byte("data for abc"), 0666); err != nil {
t.Fatal(err)
}
want := htop("h1", fmt.Sprintf("%s %s\n%s %s\n", h("data for abc"), "prefix/abc", h("data for xyz"), "prefix/xyz"))
out, err := HashDir(dir, "prefix", Hash1)
if err != nil {
t.Fatalf("HashDir: %v", err)
}
if out != want {
t.Errorf("HashDir(...) = %s, want %s", out, want)
}
}
func TestHashZip(t *testing.T) {
f, err := ioutil.TempFile("", "dirhash-test-")
if err != nil {
t.Fatal(err)
}
defer os.Remove(f.Name())
defer f.Close()
z := zip.NewWriter(f)
w, err := z.Create("prefix/xyz")
if err != nil {
t.Fatal(err)
}
w.Write([]byte("data for xyz"))
w, err = z.Create("prefix/abc")
if err != nil {
t.Fatal(err)
}
w.Write([]byte("data for abc"))
if err := z.Close(); err != nil {
t.Fatal(err)
}
if err := f.Close(); err != nil {
t.Fatal(err)
}
want := htop("h1", fmt.Sprintf("%s %s\n%s %s\n", h("data for abc"), "prefix/abc", h("data for xyz"), "prefix/xyz"))
out, err := HashZip(f.Name(), Hash1)
if err != nil {
t.Fatalf("HashDir: %v", err)
}
if out != want {
t.Errorf("HashDir(...) = %s, want %s", out, want)
}
}
func TestDirFiles(t *testing.T) {
dir, err := ioutil.TempDir("", "dirfiles-test-")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(dir)
if err := ioutil.WriteFile(filepath.Join(dir, "xyz"), []byte("data for xyz"), 0666); err != nil {
t.Fatal(err)
}
if err := ioutil.WriteFile(filepath.Join(dir, "abc"), []byte("data for abc"), 0666); err != nil {
t.Fatal(err)
}
if err := os.Mkdir(filepath.Join(dir, "subdir"), 0777); err != nil {
t.Fatal(err)
}
if err := ioutil.WriteFile(filepath.Join(dir, "subdir", "xyz"), []byte("data for subdir xyz"), 0666); err != nil {
t.Fatal(err)
}
prefix := "foo/bar@v2.3.4"
out, err := DirFiles(dir, prefix)
if err != nil {
t.Fatalf("DirFiles: %v", err)
}
for _, file := range out {
if !strings.HasPrefix(file, prefix) {
t.Errorf("Dir file = %s, want prefix %s", file, prefix)
}
}
}

View File

@ -11,7 +11,7 @@ import (
"unicode/utf8"
)
// The following functions are copied verbatim from cmd/go/internal/module/module.go,
// The following functions are copied verbatim from golang.org/x/mod/module/module.go,
// with a change to additionally reject Windows short-names,
// and one to accept arbitrary letters (golang.org/issue/29101).
//

View File

@ -5,16 +5,17 @@
package modcmd
import (
"cmd/go/internal/cfg"
"encoding/json"
"os"
"cmd/go/internal/base"
"cmd/go/internal/cfg"
"cmd/go/internal/modfetch"
"cmd/go/internal/modload"
"cmd/go/internal/module"
"cmd/go/internal/par"
"cmd/go/internal/work"
"golang.org/x/mod/module"
)
var cmdDownload = &base.Command{

View File

@ -16,10 +16,11 @@ import (
"cmd/go/internal/base"
"cmd/go/internal/modfetch"
"cmd/go/internal/modfile"
"cmd/go/internal/modload"
"cmd/go/internal/module"
"cmd/go/internal/work"
"golang.org/x/mod/modfile"
"golang.org/x/mod/module"
)
var cmdEdit = &base.Command{

View File

@ -8,15 +8,16 @@ package modcmd
import (
"bufio"
"cmd/go/internal/cfg"
"os"
"sort"
"cmd/go/internal/base"
"cmd/go/internal/cfg"
"cmd/go/internal/modload"
"cmd/go/internal/module"
"cmd/go/internal/par"
"cmd/go/internal/work"
"golang.org/x/mod/module"
)
var cmdGraph = &base.Command{

View File

@ -14,8 +14,9 @@ import (
"cmd/go/internal/cfg"
"cmd/go/internal/modfetch"
"cmd/go/internal/modload"
"cmd/go/internal/module"
"cmd/go/internal/work"
"golang.org/x/mod/module"
)
var cmdTidy = &base.Command{

View File

@ -18,9 +18,10 @@ import (
"cmd/go/internal/cfg"
"cmd/go/internal/imports"
"cmd/go/internal/modload"
"cmd/go/internal/module"
"cmd/go/internal/semver"
"cmd/go/internal/work"
"golang.org/x/mod/module"
"golang.org/x/mod/semver"
)
var cmdVendor = &base.Command{

View File

@ -6,17 +6,18 @@ package modcmd
import (
"bytes"
"cmd/go/internal/cfg"
"fmt"
"io/ioutil"
"os"
"cmd/go/internal/base"
"cmd/go/internal/dirhash"
"cmd/go/internal/cfg"
"cmd/go/internal/modfetch"
"cmd/go/internal/modload"
"cmd/go/internal/module"
"cmd/go/internal/work"
"golang.org/x/mod/module"
"golang.org/x/mod/sumdb/dirhash"
)
var cmdVerify = &base.Command{

View File

@ -5,12 +5,14 @@
package modcmd
import (
"cmd/go/internal/base"
"cmd/go/internal/modload"
"cmd/go/internal/module"
"cmd/go/internal/work"
"fmt"
"strings"
"cmd/go/internal/base"
"cmd/go/internal/modload"
"cmd/go/internal/work"
"golang.org/x/mod/module"
)
var cmdWhy = &base.Command{

View File

@ -13,10 +13,11 @@ import (
"cmd/go/internal/base"
"cmd/go/internal/modfetch"
"cmd/go/internal/modfile"
"cmd/go/internal/module"
"cmd/go/internal/par"
"cmd/go/internal/semver"
"golang.org/x/mod/modfile"
"golang.org/x/mod/module"
"golang.org/x/mod/semver"
)
// ConvertLegacyConfig converts legacy config to modfile.

View File

@ -19,8 +19,9 @@ import (
"cmd/go/internal/cfg"
"cmd/go/internal/modfetch"
"cmd/go/internal/modfetch/codehost"
"cmd/go/internal/modfile"
"cmd/go/internal/module"
"golang.org/x/mod/modfile"
"golang.org/x/mod/module"
)
func TestMain(m *testing.M) {

View File

@ -12,9 +12,9 @@ import (
"strconv"
"strings"
"cmd/go/internal/modfile"
"cmd/go/internal/module"
"cmd/go/internal/semver"
"golang.org/x/mod/modfile"
"golang.org/x/mod/module"
"golang.org/x/mod/semver"
)
func ParseGopkgLock(file string, data []byte) (*modfile.File, error) {

View File

@ -7,8 +7,8 @@ package modconv
import (
"strings"
"cmd/go/internal/modfile"
"cmd/go/internal/module"
"golang.org/x/mod/modfile"
"golang.org/x/mod/module"
)
func ParseGlideLock(file string, data []byte) (*modfile.File, error) {

View File

@ -7,8 +7,8 @@ package modconv
import (
"strings"
"cmd/go/internal/modfile"
"cmd/go/internal/module"
"golang.org/x/mod/modfile"
"golang.org/x/mod/module"
)
func ParseGLOCKFILE(file string, data []byte) (*modfile.File, error) {

View File

@ -7,8 +7,8 @@ package modconv
import (
"encoding/json"
"cmd/go/internal/modfile"
"cmd/go/internal/module"
"golang.org/x/mod/modfile"
"golang.org/x/mod/module"
)
func ParseGodepsJSON(file string, data []byte) (*modfile.File, error) {

View File

@ -4,7 +4,7 @@
package modconv
import "cmd/go/internal/modfile"
import "golang.org/x/mod/modfile"
var Converters = map[string]func(string, []byte) (*modfile.File, error){
"GLOCKFILE": ParseGLOCKFILE,

View File

@ -7,8 +7,8 @@ package modconv
import (
"strings"
"cmd/go/internal/modfile"
"cmd/go/internal/module"
"golang.org/x/mod/modfile"
"golang.org/x/mod/module"
)
func ParseDependenciesTSV(file string, data []byte) (*modfile.File, error) {

View File

@ -7,8 +7,8 @@ package modconv
import (
"strings"
"cmd/go/internal/modfile"
"cmd/go/internal/module"
"golang.org/x/mod/modfile"
"golang.org/x/mod/module"
)
func ParseVendorConf(file string, data []byte) (*modfile.File, error) {

View File

@ -7,8 +7,8 @@ package modconv
import (
"encoding/json"
"cmd/go/internal/modfile"
"cmd/go/internal/module"
"golang.org/x/mod/modfile"
"golang.org/x/mod/module"
)
func ParseVendorJSON(file string, data []byte) (*modfile.File, error) {

View File

@ -7,8 +7,8 @@ package modconv
import (
"encoding/json"
"cmd/go/internal/modfile"
"cmd/go/internal/module"
"golang.org/x/mod/modfile"
"golang.org/x/mod/module"
)
func ParseVendorManifest(file string, data []byte) (*modfile.File, error) {

View File

@ -7,8 +7,8 @@ package modconv
import (
"strings"
"cmd/go/internal/modfile"
"cmd/go/internal/module"
"golang.org/x/mod/modfile"
"golang.org/x/mod/module"
)
func ParseVendorYML(file string, data []byte) (*modfile.File, error) {

View File

@ -6,7 +6,7 @@
package modfetch
import "cmd/go/internal/module"
import "golang.org/x/mod/module"
func useSumDB(mod module.Version) bool {
return false

View File

@ -18,10 +18,11 @@ import (
"cmd/go/internal/cfg"
"cmd/go/internal/lockedfile"
"cmd/go/internal/modfetch/codehost"
"cmd/go/internal/module"
"cmd/go/internal/par"
"cmd/go/internal/renameio"
"cmd/go/internal/semver"
"golang.org/x/mod/module"
"golang.org/x/mod/semver"
)
var QuietLookup bool // do not print about lookups

View File

@ -22,8 +22,9 @@ import (
"cmd/go/internal/lockedfile"
"cmd/go/internal/par"
"cmd/go/internal/semver"
"cmd/go/internal/web"
"golang.org/x/mod/semver"
)
// GitRepo returns the code repository at the given Git remote reference.

View File

@ -16,9 +16,10 @@ import (
"time"
"cmd/go/internal/modfetch/codehost"
"cmd/go/internal/modfile"
"cmd/go/internal/module"
"cmd/go/internal/semver"
"golang.org/x/mod/modfile"
"golang.org/x/mod/module"
"golang.org/x/mod/semver"
)
// A codeRepo implements modfetch.Repo using an underlying codehost.Repo.

View File

@ -19,10 +19,11 @@ import (
"cmd/go/internal/base"
"cmd/go/internal/cfg"
"cmd/go/internal/dirhash"
"cmd/go/internal/module"
"cmd/go/internal/par"
"cmd/go/internal/renameio"
"golang.org/x/mod/module"
"golang.org/x/mod/sumdb/dirhash"
)
var downloadCache par.Cache

View File

@ -22,9 +22,10 @@ import (
"cmd/go/internal/base"
"cmd/go/internal/cfg"
"cmd/go/internal/modfetch/codehost"
"cmd/go/internal/module"
"cmd/go/internal/semver"
"cmd/go/internal/web"
"golang.org/x/mod/module"
"golang.org/x/mod/semver"
)
var HelpGoproxy = &base.Command{

View File

@ -40,9 +40,10 @@ import (
"strings"
"time"
"cmd/go/internal/module"
"cmd/go/internal/semver"
"internal/lazyregexp"
"golang.org/x/mod/module"
"golang.org/x/mod/semver"
)
var pseudoVersionRE = lazyregexp.New(`^v[0-9]+\.(0\.0-|\d+\.\d+-([^+]*\.)?0\.)\d{14}-[A-Za-z0-9]+(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$`)

View File

@ -17,9 +17,10 @@ import (
"cmd/go/internal/get"
"cmd/go/internal/modfetch/codehost"
"cmd/go/internal/par"
"cmd/go/internal/semver"
"cmd/go/internal/str"
web "cmd/go/internal/web"
"golang.org/x/mod/semver"
)
const traceRepo = false // trace all repo actions, for debugging

View File

@ -24,11 +24,11 @@ import (
"cmd/go/internal/cfg"
"cmd/go/internal/get"
"cmd/go/internal/lockedfile"
"cmd/go/internal/module"
"cmd/go/internal/note"
"cmd/go/internal/str"
"cmd/go/internal/sumdb"
"cmd/go/internal/web"
"golang.org/x/mod/module"
"golang.org/x/mod/sumdb"
"golang.org/x/mod/sumdb/note"
)
// useSumDB reports whether to use the Go checksum database for the given module.

View File

@ -15,8 +15,8 @@ import (
"strings"
"cmd/go/internal/modfetch/codehost"
"cmd/go/internal/module"
"cmd/go/internal/str"
"golang.org/x/mod/module"
)
func Unzip(dir, zipfile, prefix string, maxSize int64) error {

View File

@ -1,388 +0,0 @@
// Copyright 2018 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 modfile
import (
"bytes"
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"reflect"
"strings"
"testing"
)
// exists reports whether the named file exists.
func exists(name string) bool {
_, err := os.Stat(name)
return err == nil
}
// Test that reading and then writing the golden files
// does not change their output.
func TestPrintGolden(t *testing.T) {
outs, err := filepath.Glob("testdata/*.golden")
if err != nil {
t.Fatal(err)
}
for _, out := range outs {
testPrint(t, out, out)
}
}
// testPrint is a helper for testing the printer.
// It reads the file named in, reformats it, and compares
// the result to the file named out.
func testPrint(t *testing.T, in, out string) {
data, err := ioutil.ReadFile(in)
if err != nil {
t.Error(err)
return
}
golden, err := ioutil.ReadFile(out)
if err != nil {
t.Error(err)
return
}
base := "testdata/" + filepath.Base(in)
f, err := parse(in, data)
if err != nil {
t.Error(err)
return
}
ndata := Format(f)
if !bytes.Equal(ndata, golden) {
t.Errorf("formatted %s incorrectly: diff shows -golden, +ours", base)
tdiff(t, string(golden), string(ndata))
return
}
}
func TestParseLax(t *testing.T) {
badFile := []byte(`module m
surprise attack
x y (
z
)
exclude v1.2.3
replace <-!!!
`)
_, err := ParseLax("file", badFile, nil)
if err != nil {
t.Fatalf("ParseLax did not ignore irrelevant errors: %v", err)
}
}
// Test that when files in the testdata directory are parsed
// and printed and parsed again, we get the same parse tree
// both times.
func TestPrintParse(t *testing.T) {
outs, err := filepath.Glob("testdata/*")
if err != nil {
t.Fatal(err)
}
for _, out := range outs {
data, err := ioutil.ReadFile(out)
if err != nil {
t.Error(err)
continue
}
base := "testdata/" + filepath.Base(out)
f, err := parse(base, data)
if err != nil {
t.Errorf("parsing original: %v", err)
continue
}
ndata := Format(f)
f2, err := parse(base, ndata)
if err != nil {
t.Errorf("parsing reformatted: %v", err)
continue
}
eq := eqchecker{file: base}
if err := eq.check(f, f2); err != nil {
t.Errorf("not equal (parse/Format/parse): %v", err)
}
pf1, err := Parse(base, data, nil)
if err != nil {
switch base {
case "testdata/replace2.in", "testdata/gopkg.in.golden":
t.Errorf("should parse %v: %v", base, err)
}
}
if err == nil {
pf2, err := Parse(base, ndata, nil)
if err != nil {
t.Errorf("Parsing reformatted: %v", err)
continue
}
eq := eqchecker{file: base}
if err := eq.check(pf1, pf2); err != nil {
t.Errorf("not equal (parse/Format/Parse): %v", err)
}
ndata2, err := pf1.Format()
if err != nil {
t.Errorf("reformat: %v", err)
}
pf3, err := Parse(base, ndata2, nil)
if err != nil {
t.Errorf("Parsing reformatted2: %v", err)
continue
}
eq = eqchecker{file: base}
if err := eq.check(pf1, pf3); err != nil {
t.Errorf("not equal (Parse/Format/Parse): %v", err)
}
ndata = ndata2
}
if strings.HasSuffix(out, ".in") {
golden, err := ioutil.ReadFile(strings.TrimSuffix(out, ".in") + ".golden")
if err != nil {
t.Error(err)
continue
}
if !bytes.Equal(ndata, golden) {
t.Errorf("formatted %s incorrectly: diff shows -golden, +ours", base)
tdiff(t, string(golden), string(ndata))
return
}
}
}
}
// An eqchecker holds state for checking the equality of two parse trees.
type eqchecker struct {
file string
pos Position
}
// errorf returns an error described by the printf-style format and arguments,
// inserting the current file position before the error text.
func (eq *eqchecker) errorf(format string, args ...interface{}) error {
return fmt.Errorf("%s:%d: %s", eq.file, eq.pos.Line,
fmt.Sprintf(format, args...))
}
// check checks that v and w represent the same parse tree.
// If not, it returns an error describing the first difference.
func (eq *eqchecker) check(v, w interface{}) error {
return eq.checkValue(reflect.ValueOf(v), reflect.ValueOf(w))
}
var (
posType = reflect.TypeOf(Position{})
commentsType = reflect.TypeOf(Comments{})
)
// checkValue checks that v and w represent the same parse tree.
// If not, it returns an error describing the first difference.
func (eq *eqchecker) checkValue(v, w reflect.Value) error {
// inner returns the innermost expression for v.
// if v is a non-nil interface value, it returns the concrete
// value in the interface.
inner := func(v reflect.Value) reflect.Value {
for {
if v.Kind() == reflect.Interface && !v.IsNil() {
v = v.Elem()
continue
}
break
}
return v
}
v = inner(v)
w = inner(w)
if v.Kind() == reflect.Invalid && w.Kind() == reflect.Invalid {
return nil
}
if v.Kind() == reflect.Invalid {
return eq.errorf("nil interface became %s", w.Type())
}
if w.Kind() == reflect.Invalid {
return eq.errorf("%s became nil interface", v.Type())
}
if v.Type() != w.Type() {
return eq.errorf("%s became %s", v.Type(), w.Type())
}
if p, ok := v.Interface().(Expr); ok {
eq.pos, _ = p.Span()
}
switch v.Kind() {
default:
return eq.errorf("unexpected type %s", v.Type())
case reflect.Bool, reflect.Int, reflect.String:
vi := v.Interface()
wi := w.Interface()
if vi != wi {
return eq.errorf("%v became %v", vi, wi)
}
case reflect.Slice:
vl := v.Len()
wl := w.Len()
for i := 0; i < vl || i < wl; i++ {
if i >= vl {
return eq.errorf("unexpected %s", w.Index(i).Type())
}
if i >= wl {
return eq.errorf("missing %s", v.Index(i).Type())
}
if err := eq.checkValue(v.Index(i), w.Index(i)); err != nil {
return err
}
}
case reflect.Struct:
// Fields in struct must match.
t := v.Type()
n := t.NumField()
for i := 0; i < n; i++ {
tf := t.Field(i)
switch {
default:
if err := eq.checkValue(v.Field(i), w.Field(i)); err != nil {
return err
}
case tf.Type == posType: // ignore positions
case tf.Type == commentsType: // ignore comment assignment
}
}
case reflect.Ptr, reflect.Interface:
if v.IsNil() != w.IsNil() {
if v.IsNil() {
return eq.errorf("unexpected %s", w.Elem().Type())
}
return eq.errorf("missing %s", v.Elem().Type())
}
if err := eq.checkValue(v.Elem(), w.Elem()); err != nil {
return err
}
}
return nil
}
// diff returns the output of running diff on b1 and b2.
func diff(b1, b2 []byte) (data []byte, err error) {
f1, err := ioutil.TempFile("", "testdiff")
if err != nil {
return nil, err
}
defer os.Remove(f1.Name())
defer f1.Close()
f2, err := ioutil.TempFile("", "testdiff")
if err != nil {
return nil, err
}
defer os.Remove(f2.Name())
defer f2.Close()
f1.Write(b1)
f2.Write(b2)
data, err = exec.Command("diff", "-u", f1.Name(), f2.Name()).CombinedOutput()
if len(data) > 0 {
// diff exits with a non-zero status when the files don't match.
// Ignore that failure as long as we get output.
err = nil
}
return
}
// tdiff logs the diff output to t.Error.
func tdiff(t *testing.T, a, b string) {
data, err := diff([]byte(a), []byte(b))
if err != nil {
t.Error(err)
return
}
t.Error(string(data))
}
var modulePathTests = []struct {
input []byte
expected string
}{
{input: []byte("module \"github.com/rsc/vgotest\""), expected: "github.com/rsc/vgotest"},
{input: []byte("module github.com/rsc/vgotest"), expected: "github.com/rsc/vgotest"},
{input: []byte("module \"github.com/rsc/vgotest\""), expected: "github.com/rsc/vgotest"},
{input: []byte("module github.com/rsc/vgotest"), expected: "github.com/rsc/vgotest"},
{input: []byte("module `github.com/rsc/vgotest`"), expected: "github.com/rsc/vgotest"},
{input: []byte("module \"github.com/rsc/vgotest/v2\""), expected: "github.com/rsc/vgotest/v2"},
{input: []byte("module github.com/rsc/vgotest/v2"), expected: "github.com/rsc/vgotest/v2"},
{input: []byte("module \"gopkg.in/yaml.v2\""), expected: "gopkg.in/yaml.v2"},
{input: []byte("module gopkg.in/yaml.v2"), expected: "gopkg.in/yaml.v2"},
{input: []byte("module \"gopkg.in/check.v1\"\n"), expected: "gopkg.in/check.v1"},
{input: []byte("module \"gopkg.in/check.v1\n\""), expected: ""},
{input: []byte("module gopkg.in/check.v1\n"), expected: "gopkg.in/check.v1"},
{input: []byte("module \"gopkg.in/check.v1\"\r\n"), expected: "gopkg.in/check.v1"},
{input: []byte("module gopkg.in/check.v1\r\n"), expected: "gopkg.in/check.v1"},
{input: []byte("module \"gopkg.in/check.v1\"\n\n"), expected: "gopkg.in/check.v1"},
{input: []byte("module gopkg.in/check.v1\n\n"), expected: "gopkg.in/check.v1"},
{input: []byte("module \n\"gopkg.in/check.v1\"\n\n"), expected: ""},
{input: []byte("module \ngopkg.in/check.v1\n\n"), expected: ""},
{input: []byte("module \"gopkg.in/check.v1\"asd"), expected: ""},
{input: []byte("module \n\"gopkg.in/check.v1\"\n\n"), expected: ""},
{input: []byte("module \ngopkg.in/check.v1\n\n"), expected: ""},
{input: []byte("module \"gopkg.in/check.v1\"asd"), expected: ""},
{input: []byte("module \nmodule a/b/c "), expected: "a/b/c"},
{input: []byte("module \" \""), expected: " "},
{input: []byte("module "), expected: ""},
{input: []byte("module \" a/b/c \""), expected: " a/b/c "},
{input: []byte("module \"github.com/rsc/vgotest1\" // with a comment"), expected: "github.com/rsc/vgotest1"},
}
func TestModulePath(t *testing.T) {
for _, test := range modulePathTests {
t.Run(string(test.input), func(t *testing.T) {
result := ModulePath(test.input)
if result != test.expected {
t.Fatalf("ModulePath(%q): %s, want %s", string(test.input), result, test.expected)
}
})
}
}
func TestGoVersion(t *testing.T) {
for _, test := range []struct {
desc, input string
ok bool
}{
{desc: "empty", input: "module m\ngo \n", ok: false},
{desc: "one", input: "module m\ngo 1\n", ok: false},
{desc: "two", input: "module m\ngo 1.22\n", ok: true},
{desc: "three", input: "module m\ngo 1.22.333", ok: false},
{desc: "before", input: "module m\ngo v1.2\n", ok: false},
{desc: "after", input: "module m\ngo 1.2rc1\n", ok: false},
{desc: "space", input: "module m\ngo 1.2 3.4\n", ok: false},
} {
t.Run(test.desc, func(t *testing.T) {
if _, err := Parse("go.mod", []byte(test.input), nil); err == nil && !test.ok {
t.Error("unexpected success")
} else if err != nil && test.ok {
t.Errorf("unexpected error: %v", err)
}
})
}
}

View File

@ -1,163 +0,0 @@
// Copyright 2018 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 modfile
import (
"bytes"
"fmt"
"testing"
"cmd/go/internal/module"
)
var addRequireTests = []struct {
in string
path string
vers string
out string
}{
{
`
module m
require x.y/z v1.2.3
`,
"x.y/z", "v1.5.6",
`
module m
require x.y/z v1.5.6
`,
},
{
`
module m
require x.y/z v1.2.3
`,
"x.y/w", "v1.5.6",
`
module m
require (
x.y/z v1.2.3
x.y/w v1.5.6
)
`,
},
{
`
module m
require x.y/z v1.2.3
require x.y/q/v2 v2.3.4
`,
"x.y/w", "v1.5.6",
`
module m
require x.y/z v1.2.3
require (
x.y/q/v2 v2.3.4
x.y/w v1.5.6
)
`,
},
}
var setRequireTests = []struct {
in string
mods []struct {
path string
vers string
}
out string
}{
{
`module m
require (
x.y/b v1.2.3
x.y/a v1.2.3
)
`,
[]struct {
path string
vers string
}{
{"x.y/a", "v1.2.3"},
{"x.y/b", "v1.2.3"},
{"x.y/c", "v1.2.3"},
},
`module m
require (
x.y/a v1.2.3
x.y/b v1.2.3
x.y/c v1.2.3
)
`,
},
}
func TestAddRequire(t *testing.T) {
for i, tt := range addRequireTests {
t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) {
f, err := Parse("in", []byte(tt.in), nil)
if err != nil {
t.Fatal(err)
}
g, err := Parse("out", []byte(tt.out), nil)
if err != nil {
t.Fatal(err)
}
golden, err := g.Format()
if err != nil {
t.Fatal(err)
}
if err := f.AddRequire(tt.path, tt.vers); err != nil {
t.Fatal(err)
}
out, err := f.Format()
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(out, golden) {
t.Errorf("have:\n%s\nwant:\n%s", out, golden)
}
})
}
}
func TestSetRequire(t *testing.T) {
for i, tt := range setRequireTests {
t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) {
f, err := Parse("in", []byte(tt.in), nil)
if err != nil {
t.Fatal(err)
}
g, err := Parse("out", []byte(tt.out), nil)
if err != nil {
t.Fatal(err)
}
golden, err := g.Format()
if err != nil {
t.Fatal(err)
}
var mods []*Require
for _, mod := range tt.mods {
mods = append(mods, &Require{
Mod: module.Version{
Path: mod.path,
Version: mod.vers,
},
})
}
f.SetRequire(mods)
out, err := f.Format()
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(out, golden) {
t.Errorf("have:\n%s\nwant:\n%s", out, golden)
}
})
}
}

View File

@ -1,29 +0,0 @@
// comment
x "y" z
// block
block ( // block-eol
// x-before-line
"x" ( y // x-eol
"x1"
"x2"
// line
"x3"
"x4"
"x5"
// y-line
"y" // y-eol
"z" // z-eol
) // block-eol2
block2 (
x
y
z
)
// eof

View File

@ -1,29 +0,0 @@
// comment
x "y" z
// block
block ( // block-eol
// x-before-line
"x" ( y // x-eol
"x1"
"x2"
// line
"x3"
"x4"
"x5"
// y-line
"y" // y-eol
"z" // z-eol
) // block-eol2
block2 (x
y
z
)
// eof

View File

@ -1,10 +0,0 @@
// comment
module "x" // eol
// mid comment
// comment 2
// comment 2 line 2
module "y" // eoy
// comment 3

View File

@ -1,8 +0,0 @@
// comment
module "x" // eol
// mid comment
// comment 2
// comment 2 line 2
module "y" // eoy
// comment 3

View File

@ -1,6 +0,0 @@
module x
require (
gopkg.in/mgo.v2 v2.0.0-20160818020120-3f83fa500528
gopkg.in/yaml.v2 v2.2.1
)

View File

@ -1 +0,0 @@
module abc

View File

@ -1 +0,0 @@
module "abc"

View File

@ -1,5 +0,0 @@
module abc
replace xyz v1.2.3 => /tmp/z
replace xyz v1.3.4 => my/xyz v1.3.4-me

View File

@ -1,5 +0,0 @@
module "abc"
replace "xyz" v1.2.3 => "/tmp/z"
replace "xyz" v1.3.4 => "my/xyz" v1.3.4-me

View File

@ -1,10 +0,0 @@
module abc
replace (
xyz v1.2.3 => /tmp/z
xyz v1.3.4 => my/xyz v1.3.4-me
xyz v1.4.5 => "/tmp/my dir"
xyz v1.5.6 => my/xyz v1.5.6
xyz => my/other/xyz v1.5.4
)

View File

@ -1,10 +0,0 @@
module "abc"
replace (
"xyz" v1.2.3 => "/tmp/z"
"xyz" v1.3.4 => "my/xyz" "v1.3.4-me"
xyz "v1.4.5" => "/tmp/my dir"
xyz v1.5.6 => my/xyz v1.5.6
xyz => my/other/xyz v1.5.4
)

View File

@ -1,7 +0,0 @@
module "x"
module "y"
require "x"
require x

View File

@ -6,17 +6,6 @@
package modget
import (
"cmd/go/internal/base"
"cmd/go/internal/get"
"cmd/go/internal/imports"
"cmd/go/internal/load"
"cmd/go/internal/modload"
"cmd/go/internal/module"
"cmd/go/internal/mvs"
"cmd/go/internal/par"
"cmd/go/internal/search"
"cmd/go/internal/semver"
"cmd/go/internal/work"
"errors"
"fmt"
"os"
@ -24,6 +13,19 @@ import (
"sort"
"strings"
"sync"
"cmd/go/internal/base"
"cmd/go/internal/get"
"cmd/go/internal/imports"
"cmd/go/internal/load"
"cmd/go/internal/modload"
"cmd/go/internal/mvs"
"cmd/go/internal/par"
"cmd/go/internal/search"
"cmd/go/internal/work"
"golang.org/x/mod/module"
"golang.org/x/mod/semver"
)
var CmdGet = &base.Command{

View File

@ -6,13 +6,6 @@ package modload
import (
"bytes"
"cmd/go/internal/base"
"cmd/go/internal/cfg"
"cmd/go/internal/modfetch"
"cmd/go/internal/modinfo"
"cmd/go/internal/module"
"cmd/go/internal/search"
"cmd/go/internal/semver"
"encoding/hex"
"fmt"
"internal/goroot"
@ -20,6 +13,15 @@ import (
"path/filepath"
"runtime/debug"
"strings"
"cmd/go/internal/base"
"cmd/go/internal/cfg"
"cmd/go/internal/modfetch"
"cmd/go/internal/modinfo"
"cmd/go/internal/search"
"golang.org/x/mod/module"
"golang.org/x/mod/semver"
)
var (

View File

@ -18,11 +18,12 @@ import (
"cmd/go/internal/cfg"
"cmd/go/internal/load"
"cmd/go/internal/modfetch"
"cmd/go/internal/module"
"cmd/go/internal/par"
"cmd/go/internal/search"
"cmd/go/internal/semver"
"cmd/go/internal/str"
"golang.org/x/mod/module"
"golang.org/x/mod/semver"
)
type ImportMissingError struct {

View File

@ -25,12 +25,13 @@ import (
"cmd/go/internal/modconv"
"cmd/go/internal/modfetch"
"cmd/go/internal/modfetch/codehost"
"cmd/go/internal/modfile"
"cmd/go/internal/module"
"cmd/go/internal/mvs"
"cmd/go/internal/renameio"
"cmd/go/internal/search"
"cmd/go/internal/semver"
"golang.org/x/mod/modfile"
"golang.org/x/mod/module"
"golang.org/x/mod/semver"
)
var (

View File

@ -13,9 +13,10 @@ import (
"cmd/go/internal/base"
"cmd/go/internal/cfg"
"cmd/go/internal/modinfo"
"cmd/go/internal/module"
"cmd/go/internal/par"
"cmd/go/internal/search"
"golang.org/x/mod/module"
)
func ListModules(args []string, listU, listVersions bool) []*modinfo.ModulePublic {

View File

@ -22,13 +22,14 @@ import (
"cmd/go/internal/cfg"
"cmd/go/internal/imports"
"cmd/go/internal/modfetch"
"cmd/go/internal/modfile"
"cmd/go/internal/module"
"cmd/go/internal/mvs"
"cmd/go/internal/par"
"cmd/go/internal/search"
"cmd/go/internal/semver"
"cmd/go/internal/str"
"golang.org/x/mod/modfile"
"golang.org/x/mod/module"
"golang.org/x/mod/semver"
)
// buildList is the list of modules to use for building packages.

View File

@ -14,10 +14,11 @@ import (
"cmd/go/internal/imports"
"cmd/go/internal/modfetch"
"cmd/go/internal/module"
"cmd/go/internal/search"
"cmd/go/internal/semver"
"cmd/go/internal/str"
"golang.org/x/mod/module"
"golang.org/x/mod/semver"
)
// Query looks up a revision of a given module given a version query string.

View File

@ -17,7 +17,8 @@ import (
"cmd/go/internal/cfg"
"cmd/go/internal/modfetch"
"cmd/go/internal/modfetch/codehost"
"cmd/go/internal/module"
"golang.org/x/mod/module"
)
func TestMain(m *testing.M) {

View File

@ -13,8 +13,9 @@ import (
"cmd/go/internal/base"
"cmd/go/internal/cfg"
"cmd/go/internal/imports"
"cmd/go/internal/module"
"cmd/go/internal/search"
"golang.org/x/mod/module"
)
// matchPackages returns a list of packages in the list of modules

View File

@ -1,343 +0,0 @@
// Copyright 2018 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 module
import "testing"
var checkTests = []struct {
path string
version string
ok bool
}{
{"rsc.io/quote", "0.1.0", false},
{"rsc io/quote", "v1.0.0", false},
{"github.com/go-yaml/yaml", "v0.8.0", true},
{"github.com/go-yaml/yaml", "v1.0.0", true},
{"github.com/go-yaml/yaml", "v2.0.0", false},
{"github.com/go-yaml/yaml", "v2.1.5", false},
{"github.com/go-yaml/yaml", "v3.0.0", false},
{"github.com/go-yaml/yaml/v2", "v1.0.0", false},
{"github.com/go-yaml/yaml/v2", "v2.0.0", true},
{"github.com/go-yaml/yaml/v2", "v2.1.5", true},
{"github.com/go-yaml/yaml/v2", "v3.0.0", false},
{"gopkg.in/yaml.v0", "v0.8.0", true},
{"gopkg.in/yaml.v0", "v1.0.0", false},
{"gopkg.in/yaml.v0", "v2.0.0", false},
{"gopkg.in/yaml.v0", "v2.1.5", false},
{"gopkg.in/yaml.v0", "v3.0.0", false},
{"gopkg.in/yaml.v1", "v0.8.0", false},
{"gopkg.in/yaml.v1", "v1.0.0", true},
{"gopkg.in/yaml.v1", "v2.0.0", false},
{"gopkg.in/yaml.v1", "v2.1.5", false},
{"gopkg.in/yaml.v1", "v3.0.0", false},
// For gopkg.in, .v1 means v1 only (not v0).
// But early versions of vgo still generated v0 pseudo-versions for it.
// Even though now we'd generate those as v1 pseudo-versions,
// we accept the old pseudo-versions to avoid breaking existing go.mod files.
// For example gopkg.in/yaml.v2@v2.2.1's go.mod requires check.v1 at a v0 pseudo-version.
{"gopkg.in/check.v1", "v0.0.0", false},
{"gopkg.in/check.v1", "v0.0.0-20160102150405-abcdef123456", true},
{"gopkg.in/yaml.v2", "v1.0.0", false},
{"gopkg.in/yaml.v2", "v2.0.0", true},
{"gopkg.in/yaml.v2", "v2.1.5", true},
{"gopkg.in/yaml.v2", "v3.0.0", false},
{"rsc.io/quote", "v17.0.0", false},
{"rsc.io/quote", "v17.0.0+incompatible", true},
}
func TestCheck(t *testing.T) {
for _, tt := range checkTests {
err := Check(tt.path, tt.version)
if tt.ok && err != nil {
t.Errorf("Check(%q, %q) = %v, wanted nil error", tt.path, tt.version, err)
} else if !tt.ok && err == nil {
t.Errorf("Check(%q, %q) succeeded, wanted error", tt.path, tt.version)
}
}
}
var checkPathTests = []struct {
path string
ok bool
importOK bool
fileOK bool
}{
{"x.y/z", true, true, true},
{"x.y", true, true, true},
{"", false, false, false},
{"x.y/\xFFz", false, false, false},
{"/x.y/z", false, false, false},
{"x./z", false, false, false},
{".x/z", false, false, true},
{"-x/z", false, false, false},
{"x..y/z", true, true, true},
{"x.y/z/../../w", false, false, false},
{"x.y//z", false, false, false},
{"x.y/z//w", false, false, false},
{"x.y/z/", false, false, false},
{"x.y/z/v0", false, true, true},
{"x.y/z/v1", false, true, true},
{"x.y/z/v2", true, true, true},
{"x.y/z/v2.0", false, true, true},
{"X.y/z", false, true, true},
{"!x.y/z", false, false, true},
{"_x.y/z", false, true, true},
{"x.y!/z", false, false, true},
{"x.y\"/z", false, false, false},
{"x.y#/z", false, false, true},
{"x.y$/z", false, false, true},
{"x.y%/z", false, false, true},
{"x.y&/z", false, false, true},
{"x.y'/z", false, false, false},
{"x.y(/z", false, false, true},
{"x.y)/z", false, false, true},
{"x.y*/z", false, false, false},
{"x.y+/z", false, true, true},
{"x.y,/z", false, false, true},
{"x.y-/z", true, true, true},
{"x.y./zt", false, false, false},
{"x.y:/z", false, false, false},
{"x.y;/z", false, false, false},
{"x.y</z", false, false, false},
{"x.y=/z", false, false, true},
{"x.y>/z", false, false, false},
{"x.y?/z", false, false, false},
{"x.y@/z", false, false, true},
{"x.y[/z", false, false, true},
{"x.y\\/z", false, false, false},
{"x.y]/z", false, false, true},
{"x.y^/z", false, false, true},
{"x.y_/z", false, true, true},
{"x.y`/z", false, false, false},
{"x.y{/z", false, false, true},
{"x.y}/z", false, false, true},
{"x.y~/z", false, true, true},
{"x.y/z!", false, false, true},
{"x.y/z\"", false, false, false},
{"x.y/z#", false, false, true},
{"x.y/z$", false, false, true},
{"x.y/z%", false, false, true},
{"x.y/z&", false, false, true},
{"x.y/z'", false, false, false},
{"x.y/z(", false, false, true},
{"x.y/z)", false, false, true},
{"x.y/z*", false, false, false},
{"x.y/z+", true, true, true},
{"x.y/z,", false, false, true},
{"x.y/z-", true, true, true},
{"x.y/z.t", true, true, true},
{"x.y/z/t", true, true, true},
{"x.y/z:", false, false, false},
{"x.y/z;", false, false, false},
{"x.y/z<", false, false, false},
{"x.y/z=", false, false, true},
{"x.y/z>", false, false, false},
{"x.y/z?", false, false, false},
{"x.y/z@", false, false, true},
{"x.y/z[", false, false, true},
{"x.y/z\\", false, false, false},
{"x.y/z]", false, false, true},
{"x.y/z^", false, false, true},
{"x.y/z_", true, true, true},
{"x.y/z`", false, false, false},
{"x.y/z{", false, false, true},
{"x.y/z}", false, false, true},
{"x.y/z~", true, true, true},
{"x.y/x.foo", true, true, true},
{"x.y/aux.foo", false, false, false},
{"x.y/prn", false, false, false},
{"x.y/prn2", true, true, true},
{"x.y/com", true, true, true},
{"x.y/com1", false, false, false},
{"x.y/com1.txt", false, false, false},
{"x.y/calm1", true, true, true},
{"github.com/!123/logrus", false, false, true},
// TODO: CL 41822 allowed Unicode letters in old "go get"
// without due consideration of the implications, and only on github.com (!).
// For now, we disallow non-ASCII characters in module mode,
// in both module paths and general import paths,
// until we can get the implications right.
// When we do, we'll enable them everywhere, not just for GitHub.
{"github.com/user/unicode/испытание", false, false, true},
{".../x", false, false, false},
{"../x", false, false, false},
{"./y", false, false, false},
{"x:y", false, false, false},
{`\temp\foo`, false, false, false},
{".gitignore", false, false, true},
{".github/ISSUE_TEMPLATE", false, false, true},
{"x☺y", false, false, false},
}
func TestCheckPath(t *testing.T) {
for _, tt := range checkPathTests {
err := CheckPath(tt.path)
if tt.ok && err != nil {
t.Errorf("CheckPath(%q) = %v, wanted nil error", tt.path, err)
} else if !tt.ok && err == nil {
t.Errorf("CheckPath(%q) succeeded, wanted error", tt.path)
}
err = CheckImportPath(tt.path)
if tt.importOK && err != nil {
t.Errorf("CheckImportPath(%q) = %v, wanted nil error", tt.path, err)
} else if !tt.importOK && err == nil {
t.Errorf("CheckImportPath(%q) succeeded, wanted error", tt.path)
}
err = CheckFilePath(tt.path)
if tt.fileOK && err != nil {
t.Errorf("CheckFilePath(%q) = %v, wanted nil error", tt.path, err)
} else if !tt.fileOK && err == nil {
t.Errorf("CheckFilePath(%q) succeeded, wanted error", tt.path)
}
}
}
var splitPathVersionTests = []struct {
pathPrefix string
version string
}{
{"x.y/z", ""},
{"x.y/z", "/v2"},
{"x.y/z", "/v3"},
{"x.y/v", ""},
{"gopkg.in/yaml", ".v0"},
{"gopkg.in/yaml", ".v1"},
{"gopkg.in/yaml", ".v2"},
{"gopkg.in/yaml", ".v3"},
}
func TestSplitPathVersion(t *testing.T) {
for _, tt := range splitPathVersionTests {
pathPrefix, version, ok := SplitPathVersion(tt.pathPrefix + tt.version)
if pathPrefix != tt.pathPrefix || version != tt.version || !ok {
t.Errorf("SplitPathVersion(%q) = %q, %q, %v, want %q, %q, true", tt.pathPrefix+tt.version, pathPrefix, version, ok, tt.pathPrefix, tt.version)
}
}
for _, tt := range checkPathTests {
pathPrefix, version, ok := SplitPathVersion(tt.path)
if pathPrefix+version != tt.path {
t.Errorf("SplitPathVersion(%q) = %q, %q, %v, doesn't add to input", tt.path, pathPrefix, version, ok)
}
}
}
var escapeTests = []struct {
path string
esc string // empty means same as path
}{
{path: "ascii.com/abcdefghijklmnopqrstuvwxyz.-+/~_0123456789"},
{path: "github.com/GoogleCloudPlatform/omega", esc: "github.com/!google!cloud!platform/omega"},
}
func TestEscapePath(t *testing.T) {
// Check invalid paths.
for _, tt := range checkPathTests {
if !tt.ok {
_, err := EscapePath(tt.path)
if err == nil {
t.Errorf("EscapePath(%q): succeeded, want error (invalid path)", tt.path)
}
}
}
// Check encodings.
for _, tt := range escapeTests {
esc, err := EscapePath(tt.path)
if err != nil {
t.Errorf("EscapePath(%q): unexpected error: %v", tt.path, err)
continue
}
want := tt.esc
if want == "" {
want = tt.path
}
if esc != want {
t.Errorf("EscapePath(%q) = %q, want %q", tt.path, esc, want)
}
}
}
var badUnescape = []string{
"github.com/GoogleCloudPlatform/omega",
"github.com/!google!cloud!platform!/omega",
"github.com/!0google!cloud!platform/omega",
"github.com/!_google!cloud!platform/omega",
"github.com/!!google!cloud!platform/omega",
"",
}
func TestUnescapePath(t *testing.T) {
// Check invalid decodings.
for _, bad := range badUnescape {
_, err := UnescapePath(bad)
if err == nil {
t.Errorf("UnescapePath(%q): succeeded, want error (invalid decoding)", bad)
}
}
// Check invalid paths (or maybe decodings).
for _, tt := range checkPathTests {
if !tt.ok {
path, err := UnescapePath(tt.path)
if err == nil {
t.Errorf("UnescapePath(%q) = %q, want error (invalid path)", tt.path, path)
}
}
}
// Check encodings.
for _, tt := range escapeTests {
esc := tt.esc
if esc == "" {
esc = tt.path
}
path, err := UnescapePath(esc)
if err != nil {
t.Errorf("UnescapePath(%q): unexpected error: %v", esc, err)
continue
}
if path != tt.path {
t.Errorf("UnescapePath(%q) = %q, want %q", esc, path, tt.path)
}
}
}
func TestMatchPathMajor(t *testing.T) {
for _, test := range []struct {
v, pathMajor string
want bool
}{
{"v0.0.0", "", true},
{"v0.0.0", "/v2", false},
{"v0.0.0", ".v0", true},
{"v0.0.0-20190510104115-cbcb75029529", ".v1", true},
{"v1.0.0", "/v2", false},
{"v1.0.0", ".v1", true},
{"v1.0.0", ".v1-unstable", true},
{"v2.0.0+incompatible", "", true},
{"v2.0.0", "", false},
{"v2.0.0", "/v2", true},
{"v2.0.0", ".v2", true},
} {
if got := MatchPathMajor(test.v, test.pathMajor); got != test.want {
t.Errorf("MatchPathMajor(%q, %q) = %v, want %v", test.v, test.pathMajor, got, test.want)
}
}
}

View File

@ -13,8 +13,9 @@ import (
"sync"
"sync/atomic"
"cmd/go/internal/module"
"cmd/go/internal/par"
"golang.org/x/mod/module"
)
// A Reqs is the requirement graph on which Minimal Version Selection (MVS) operates.

View File

@ -10,7 +10,7 @@ import (
"strings"
"testing"
"cmd/go/internal/module"
"golang.org/x/mod/module"
)
var tests = `

View File

@ -1,128 +0,0 @@
// 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 note_test
import (
"fmt"
"io"
"os"
"cmd/go/internal/note"
)
func ExampleSign() {
skey := "PRIVATE+KEY+PeterNeumann+c74f20a3+AYEKFALVFGyNhPJEMzD1QIDr+Y7hfZx09iUvxdXHKDFz"
text := "If you think cryptography is the answer to your problem,\n" +
"then you don't know what your problem is.\n"
signer, err := note.NewSigner(skey)
if err != nil {
fmt.Println(err)
return
}
msg, err := note.Sign(&note.Note{Text: text}, signer)
if err != nil {
fmt.Println(err)
return
}
os.Stdout.Write(msg)
// Output:
// If you think cryptography is the answer to your problem,
// then you don't know what your problem is.
//
// — PeterNeumann x08go/ZJkuBS9UG/SffcvIAQxVBtiFupLLr8pAcElZInNIuGUgYN1FFYC2pZSNXgKvqfqdngotpRZb6KE6RyyBwJnAM=
}
func ExampleOpen() {
vkey := "PeterNeumann+c74f20a3+ARpc2QcUPDhMQegwxbzhKqiBfsVkmqq/LDE4izWy10TW"
msg := []byte("If you think cryptography is the answer to your problem,\n" +
"then you don't know what your problem is.\n" +
"\n" +
"— PeterNeumann x08go/ZJkuBS9UG/SffcvIAQxVBtiFupLLr8pAcElZInNIuGUgYN1FFYC2pZSNXgKvqfqdngotpRZb6KE6RyyBwJnAM=\n")
verifier, err := note.NewVerifier(vkey)
if err != nil {
fmt.Println(err)
return
}
verifiers := note.VerifierList(verifier)
n, err := note.Open(msg, verifiers)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%s (%08x):\n%s", n.Sigs[0].Name, n.Sigs[0].Hash, n.Text)
// Output:
// PeterNeumann (c74f20a3):
// If you think cryptography is the answer to your problem,
// then you don't know what your problem is.
}
var rand = struct {
Reader io.Reader
}{
zeroReader{},
}
type zeroReader struct{}
func (zeroReader) Read(buf []byte) (int, error) {
for i := range buf {
buf[i] = 0
}
return len(buf), nil
}
func ExampleSign_add_signatures() {
vkey := "PeterNeumann+c74f20a3+ARpc2QcUPDhMQegwxbzhKqiBfsVkmqq/LDE4izWy10TW"
msg := []byte("If you think cryptography is the answer to your problem,\n" +
"then you don't know what your problem is.\n" +
"\n" +
"— PeterNeumann x08go/ZJkuBS9UG/SffcvIAQxVBtiFupLLr8pAcElZInNIuGUgYN1FFYC2pZSNXgKvqfqdngotpRZb6KE6RyyBwJnAM=\n")
verifier, err := note.NewVerifier(vkey)
if err != nil {
fmt.Println(err)
return
}
verifiers := note.VerifierList(verifier)
n, err := note.Open([]byte(msg), verifiers)
if err != nil {
fmt.Println(err)
return
}
skey, vkey, err := note.GenerateKey(rand.Reader, "EnochRoot")
if err != nil {
fmt.Println(err)
return
}
_ = vkey // give to verifiers
me, err := note.NewSigner(skey)
if err != nil {
fmt.Println(err)
return
}
msg, err = note.Sign(n, me)
if err != nil {
fmt.Println(err)
return
}
os.Stdout.Write(msg)
// Output:
// If you think cryptography is the answer to your problem,
// then you don't know what your problem is.
//
// — PeterNeumann x08go/ZJkuBS9UG/SffcvIAQxVBtiFupLLr8pAcElZInNIuGUgYN1FFYC2pZSNXgKvqfqdngotpRZb6KE6RyyBwJnAM=
// — EnochRoot rwz+eBzmZa0SO3NbfRGzPCpDckykFXSdeX+MNtCOXm2/5n2tiOHp+vAF1aGrQ5ovTG01oOTGwnWLox33WWd1RvMc+QQ=
}

View File

@ -1,472 +0,0 @@
// 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 note
import (
"crypto/ed25519"
"crypto/rand"
"errors"
"strings"
"testing"
"testing/iotest"
)
func TestNewVerifier(t *testing.T) {
vkey := "PeterNeumann+c74f20a3+ARpc2QcUPDhMQegwxbzhKqiBfsVkmqq/LDE4izWy10TW"
_, err := NewVerifier(vkey)
if err != nil {
t.Fatal(err)
}
// Check various manglings are not accepted.
badKey := func(k string) {
_, err := NewVerifier(k)
if err == nil {
t.Errorf("NewVerifier(%q) succeeded, should have failed", k)
}
}
b := []byte(vkey)
for i := 0; i <= len(b); i++ {
for j := i + 1; j <= len(b); j++ {
if i != 0 || j != len(b) {
badKey(string(b[i:j]))
}
}
}
for i := 0; i < len(b); i++ {
b[i]++
badKey(string(b))
b[i]--
}
badKey("PeterNeumann+cc469956+ARpc2QcUPDhMQegwxbzhKqiBfsVkmqq/LDE4izWy10TWBADKEY==") // wrong length key, with adjusted key hash
badKey("PeterNeumann+173116ae+ZRpc2QcUPDhMQegwxbzhKqiBfsVkmqq/LDE4izWy10TW") // unknown algorithm, with adjusted key hash
}
func TestNewSigner(t *testing.T) {
skey := "PRIVATE+KEY+PeterNeumann+c74f20a3+AYEKFALVFGyNhPJEMzD1QIDr+Y7hfZx09iUvxdXHKDFz"
_, err := NewSigner(skey)
if err != nil {
t.Fatal(err)
}
// Check various manglings are not accepted.
b := []byte(skey)
for i := 0; i <= len(b); i++ {
for j := i + 1; j <= len(b); j++ {
if i == 0 && j == len(b) {
continue
}
_, err := NewSigner(string(b[i:j]))
if err == nil {
t.Errorf("NewSigner(%q) succeeded, should have failed", b[i:j])
}
}
}
for i := 0; i < len(b); i++ {
b[i]++
_, err := NewSigner(string(b))
if err == nil {
t.Errorf("NewSigner(%q) succeeded, should have failed", b)
}
b[i]--
}
}
func testSignerAndVerifier(t *testing.T, Name string, signer Signer, verifier Verifier) {
if name := signer.Name(); name != Name {
t.Errorf("signer.Name() = %q, want %q", name, Name)
}
if name := verifier.Name(); name != Name {
t.Errorf("verifier.Name() = %q, want %q", name, Name)
}
shash := signer.KeyHash()
vhash := verifier.KeyHash()
if shash != vhash {
t.Errorf("signer.KeyHash() = %#08x != verifier.KeyHash() = %#08x", shash, vhash)
}
msg := []byte("hi")
sig, err := signer.Sign(msg)
if err != nil {
t.Fatalf("signer.Sign: %v", err)
}
if !verifier.Verify(msg, sig) {
t.Fatalf("verifier.Verify failed on signature returned by signer.Sign")
}
sig[0]++
if verifier.Verify(msg, sig) {
t.Fatalf("verifier.Verify succceeded on corrupt signature")
}
sig[0]--
msg[0]++
if verifier.Verify(msg, sig) {
t.Fatalf("verifier.Verify succceeded on corrupt message")
}
}
func TestGenerateKey(t *testing.T) {
// Generate key pair, make sure it is all self-consistent.
const Name = "EnochRoot"
skey, vkey, err := GenerateKey(rand.Reader, Name)
if err != nil {
t.Fatalf("GenerateKey: %v", err)
}
signer, err := NewSigner(skey)
if err != nil {
t.Fatalf("NewSigner: %v", err)
}
verifier, err := NewVerifier(vkey)
if err != nil {
t.Fatalf("NewVerifier: %v", err)
}
testSignerAndVerifier(t, Name, signer, verifier)
// Check that GenerateKey returns error from rand reader.
_, _, err = GenerateKey(iotest.TimeoutReader(iotest.OneByteReader(rand.Reader)), Name)
if err == nil {
t.Fatalf("GenerateKey succeeded with error-returning rand reader")
}
}
func TestFromEd25519(t *testing.T) {
const Name = "EnochRoot"
pub, priv, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
t.Fatalf("GenerateKey: %v", err)
}
signer, err := newSignerFromEd25519Seed(Name, priv.Seed())
if err != nil {
t.Fatalf("newSignerFromEd25519Seed: %v", err)
}
vkey, err := NewEd25519VerifierKey(Name, pub)
if err != nil {
t.Fatalf("NewEd25519VerifierKey: %v", err)
}
verifier, err := NewVerifier(vkey)
if err != nil {
t.Fatalf("NewVerifier: %v", err)
}
testSignerAndVerifier(t, Name, signer, verifier)
// Check that wrong key sizes return errors.
_, err = NewEd25519VerifierKey(Name, pub[:len(pub)-1])
if err == nil {
t.Errorf("NewEd25519VerifierKey succeeded with a seed of the wrong size")
}
}
// newSignerFromEd25519Seed constructs a new signer from a verifier name and a
// crypto/ed25519 private key seed.
func newSignerFromEd25519Seed(name string, seed []byte) (Signer, error) {
if len(seed) != ed25519.SeedSize {
return nil, errors.New("invalid seed size")
}
priv := ed25519.NewKeyFromSeed(seed)
pub := priv[32:]
pubkey := append([]byte{algEd25519}, pub...)
hash := keyHash(name, pubkey)
s := &signer{
name: name,
hash: uint32(hash),
sign: func(msg []byte) ([]byte, error) {
return ed25519.Sign(priv, msg), nil
},
}
return s, nil
}
func TestSign(t *testing.T) {
skey := "PRIVATE+KEY+PeterNeumann+c74f20a3+AYEKFALVFGyNhPJEMzD1QIDr+Y7hfZx09iUvxdXHKDFz"
text := "If you think cryptography is the answer to your problem,\n" +
"then you don't know what your problem is.\n"
signer, err := NewSigner(skey)
if err != nil {
t.Fatal(err)
}
msg, err := Sign(&Note{Text: text}, signer)
if err != nil {
t.Fatal(err)
}
want := `If you think cryptography is the answer to your problem,
then you don't know what your problem is.
PeterNeumann x08go/ZJkuBS9UG/SffcvIAQxVBtiFupLLr8pAcElZInNIuGUgYN1FFYC2pZSNXgKvqfqdngotpRZb6KE6RyyBwJnAM=
`
if string(msg) != want {
t.Errorf("Sign: wrong output\nhave:\n%s\nwant:\n%s", msg, want)
}
// Check that existing signature is replaced by new one.
msg, err = Sign(&Note{Text: text, Sigs: []Signature{{Name: "PeterNeumann", Hash: 0xc74f20a3, Base64: "BADSIGN="}}}, signer)
if err != nil {
t.Fatal(err)
}
if string(msg) != want {
t.Errorf("Sign replacing signature: wrong output\nhave:\n%s\nwant:\n%s", msg, want)
}
// Check various bad inputs.
_, err = Sign(&Note{Text: "abc"}, signer)
if err == nil || err.Error() != "malformed note" {
t.Fatalf("Sign with short text: %v, want malformed note error", err)
}
_, err = Sign(&Note{Text: text, Sigs: []Signature{{Name: "a+b", Base64: "ABCD"}}})
if err == nil || err.Error() != "malformed note" {
t.Fatalf("Sign with bad name: %v, want malformed note error", err)
}
_, err = Sign(&Note{Text: text, Sigs: []Signature{{Name: "PeterNeumann", Hash: 0xc74f20a3, Base64: "BADHASH="}}})
if err == nil || err.Error() != "malformed note" {
t.Fatalf("Sign with bad pre-filled signature: %v, want malformed note error", err)
}
_, err = Sign(&Note{Text: text}, &badSigner{signer})
if err == nil || err.Error() != "invalid signer" {
t.Fatalf("Sign with bad signer: %v, want invalid signer error", err)
}
_, err = Sign(&Note{Text: text}, &errSigner{signer})
if err != errSurprise {
t.Fatalf("Sign with failing signer: %v, want errSurprise", err)
}
}
func TestVerifierList(t *testing.T) {
peterKey := "PeterNeumann+c74f20a3+ARpc2QcUPDhMQegwxbzhKqiBfsVkmqq/LDE4izWy10TW"
peterVerifier, err := NewVerifier(peterKey)
if err != nil {
t.Fatal(err)
}
enochKey := "EnochRoot+af0cfe78+ATtqJ7zOtqQtYqOo0CpvDXNlMhV3HeJDpjrASKGLWdop"
enochVerifier, err := NewVerifier(enochKey)
if err != nil {
t.Fatal(err)
}
list := VerifierList(peterVerifier, enochVerifier, enochVerifier)
v, err := list.Verifier("PeterNeumann", 0xc74f20a3)
if v != peterVerifier || err != nil {
t.Fatalf("list.Verifier(peter) = %v, %v, want %v, nil", v, err, peterVerifier)
}
v, err = list.Verifier("PeterNeumann", 0xc74f20a4)
if v != nil || err == nil || err.Error() != "unknown key PeterNeumann+c74f20a4" {
t.Fatalf("list.Verifier(peter bad hash) = %v, %v, want nil, unknown key error", v, err)
}
v, err = list.Verifier("PeterNeuman", 0xc74f20a3)
if v != nil || err == nil || err.Error() != "unknown key PeterNeuman+c74f20a3" {
t.Fatalf("list.Verifier(peter bad name) = %v, %v, want nil, unknown key error", v, err)
}
v, err = list.Verifier("EnochRoot", 0xaf0cfe78)
if v != nil || err == nil || err.Error() != "ambiguous key EnochRoot+af0cfe78" {
t.Fatalf("list.Verifier(enoch) = %v, %v, want nil, ambiguous key error", v, err)
}
}
type badSigner struct {
Signer
}
func (b *badSigner) Name() string {
return "bad name"
}
var errSurprise = errors.New("surprise!")
type errSigner struct {
Signer
}
func (e *errSigner) Sign([]byte) ([]byte, error) {
return nil, errSurprise
}
func TestOpen(t *testing.T) {
peterKey := "PeterNeumann+c74f20a3+ARpc2QcUPDhMQegwxbzhKqiBfsVkmqq/LDE4izWy10TW"
peterVerifier, err := NewVerifier(peterKey)
if err != nil {
t.Fatal(err)
}
enochKey := "EnochRoot+af0cfe78+ATtqJ7zOtqQtYqOo0CpvDXNlMhV3HeJDpjrASKGLWdop"
enochVerifier, err := NewVerifier(enochKey)
if err != nil {
t.Fatal(err)
}
text := `If you think cryptography is the answer to your problem,
then you don't know what your problem is.
`
peterSig := "— PeterNeumann x08go/ZJkuBS9UG/SffcvIAQxVBtiFupLLr8pAcElZInNIuGUgYN1FFYC2pZSNXgKvqfqdngotpRZb6KE6RyyBwJnAM=\n"
enochSig := "— EnochRoot rwz+eBzmZa0SO3NbfRGzPCpDckykFXSdeX+MNtCOXm2/5n2tiOHp+vAF1aGrQ5ovTG01oOTGwnWLox33WWd1RvMc+QQ=\n"
peter := Signature{"PeterNeumann", 0xc74f20a3, "x08go/ZJkuBS9UG/SffcvIAQxVBtiFupLLr8pAcElZInNIuGUgYN1FFYC2pZSNXgKvqfqdngotpRZb6KE6RyyBwJnAM="}
enoch := Signature{"EnochRoot", 0xaf0cfe78, "rwz+eBzmZa0SO3NbfRGzPCpDckykFXSdeX+MNtCOXm2/5n2tiOHp+vAF1aGrQ5ovTG01oOTGwnWLox33WWd1RvMc+QQ="}
// Check one signature verified, one not.
n, err := Open([]byte(text+"\n"+peterSig+enochSig), VerifierList(peterVerifier))
if err != nil {
t.Fatal(err)
}
if n.Text != text {
t.Errorf("n.Text = %q, want %q", n.Text, text)
}
if len(n.Sigs) != 1 || n.Sigs[0] != peter {
t.Errorf("n.Sigs:\nhave %v\nwant %v", n.Sigs, []Signature{peter})
}
if len(n.UnverifiedSigs) != 1 || n.UnverifiedSigs[0] != enoch {
t.Errorf("n.UnverifiedSigs:\nhave %v\nwant %v", n.Sigs, []Signature{peter})
}
// Check both verified.
n, err = Open([]byte(text+"\n"+peterSig+enochSig), VerifierList(peterVerifier, enochVerifier))
if err != nil {
t.Fatal(err)
}
if len(n.Sigs) != 2 || n.Sigs[0] != peter || n.Sigs[1] != enoch {
t.Errorf("n.Sigs:\nhave %v\nwant %v", n.Sigs, []Signature{peter, enoch})
}
if len(n.UnverifiedSigs) != 0 {
t.Errorf("n.UnverifiedSigs:\nhave %v\nwant %v", n.Sigs, []Signature{})
}
// Check both unverified.
n, err = Open([]byte(text+"\n"+peterSig+enochSig), VerifierList())
if n != nil || err == nil {
t.Fatalf("Open unverified = %v, %v, want nil, error", n, err)
}
e, ok := err.(*UnverifiedNoteError)
if !ok {
t.Fatalf("Open unverified: err is %T, want *UnverifiedNoteError", err)
}
if err.Error() != "note has no verifiable signatures" {
t.Fatalf("Open unverified: err.Error() = %q, want %q", err.Error(), "note has no verifiable signatures")
}
n = e.Note
if n == nil {
t.Fatalf("Open unverified: missing note in UnverifiedNoteError")
}
if len(n.Sigs) != 0 {
t.Errorf("n.Sigs:\nhave %v\nwant %v", n.Sigs, []Signature{})
}
if len(n.UnverifiedSigs) != 2 || n.UnverifiedSigs[0] != peter || n.UnverifiedSigs[1] != enoch {
t.Errorf("n.UnverifiedSigs:\nhave %v\nwant %v", n.Sigs, []Signature{peter, enoch})
}
// Check duplicated verifier.
_, err = Open([]byte(text+"\n"+enochSig), VerifierList(enochVerifier, peterVerifier, enochVerifier))
if err == nil || err.Error() != "ambiguous key EnochRoot+af0cfe78" {
t.Fatalf("Open with duplicated verifier: err=%v, want ambiguous key", err)
}
// Check unused duplicated verifier.
_, err = Open([]byte(text+"\n"+peterSig), VerifierList(enochVerifier, peterVerifier, enochVerifier))
if err != nil {
t.Fatal(err)
}
// Check too many signatures.
n, err = Open([]byte(text+"\n"+strings.Repeat(peterSig, 101)), VerifierList(peterVerifier))
if n != nil || err == nil || err.Error() != "malformed note" {
t.Fatalf("Open too many verified signatures = %v, %v, want nil, malformed note error", n, err)
}
n, err = Open([]byte(text+"\n"+strings.Repeat(peterSig, 101)), VerifierList())
if n != nil || err == nil || err.Error() != "malformed note" {
t.Fatalf("Open too many verified signatures = %v, %v, want nil, malformed note error", n, err)
}
// Invalid signature.
n, err = Open([]byte(text+"\n"+peterSig[:60]+"ABCD"+peterSig[60:]), VerifierList(peterVerifier))
if n != nil || err == nil || err.Error() != "invalid signature for key PeterNeumann+c74f20a3" {
t.Fatalf("Open too many verified signatures = %v, %v, want nil, invalid signature error", n, err)
}
// Duplicated verified and unverified signatures.
enochABCD := Signature{"EnochRoot", 0xaf0cfe78, "rwz+eBzmZa0SO3NbfRGzPCpDckykFXSdeX+MNtCOXm2/5n" + "ABCD" + "2tiOHp+vAF1aGrQ5ovTG01oOTGwnWLox33WWd1RvMc+QQ="}
n, err = Open([]byte(text+"\n"+peterSig+peterSig+enochSig+enochSig+enochSig[:60]+"ABCD"+enochSig[60:]), VerifierList(peterVerifier))
if err != nil {
t.Fatal(err)
}
if len(n.Sigs) != 1 || n.Sigs[0] != peter {
t.Errorf("n.Sigs:\nhave %v\nwant %v", n.Sigs, []Signature{peter})
}
if len(n.UnverifiedSigs) != 2 || n.UnverifiedSigs[0] != enoch || n.UnverifiedSigs[1] != enochABCD {
t.Errorf("n.UnverifiedSigs:\nhave %v\nwant %v", n.UnverifiedSigs, []Signature{enoch, enochABCD})
}
// Invalid encoded message syntax.
badMsgs := []string{
text,
text + "\n",
text + "\n" + peterSig[:len(peterSig)-1],
"\x01" + text + "\n" + peterSig,
"\xff" + text + "\n" + peterSig,
text + "\n" + "— Bad Name x08go/ZJkuBS9UG/SffcvIAQxVBtiFupLLr8pAcElZInNIuGUgYN1FFYC2pZSNXgKvqfqdngotpRZb6KE6RyyBwJnAM=",
text + "\n" + peterSig + "Unexpected line.\n",
}
for _, msg := range badMsgs {
n, err := Open([]byte(msg), VerifierList(peterVerifier))
if n != nil || err == nil || err.Error() != "malformed note" {
t.Fatalf("Open bad msg = %v, %v, want nil, malformed note error\nmsg:\n%s", n, err, msg)
}
}
}
func BenchmarkOpen(b *testing.B) {
vkey := "PeterNeumann+c74f20a3+ARpc2QcUPDhMQegwxbzhKqiBfsVkmqq/LDE4izWy10TW"
msg := []byte("If you think cryptography is the answer to your problem,\n" +
"then you don't know what your problem is.\n" +
"\n" +
"— PeterNeumann x08go/ZJkuBS9UG/SffcvIAQxVBtiFupLLr8pAcElZInNIuGUgYN1FFYC2pZSNXgKvqfqdngotpRZb6KE6RyyBwJnAM=\n")
verifier, err := NewVerifier(vkey)
if err != nil {
b.Fatal(err)
}
verifiers := VerifierList(verifier)
verifiers0 := VerifierList()
// Try with 0 signatures and 1 signature so we can tell how much each signature adds.
b.Run("Sig0", func(b *testing.B) {
for i := 0; i < b.N; i++ {
_, err := Open(msg, verifiers0)
e, ok := err.(*UnverifiedNoteError)
if !ok {
b.Fatal("expected UnverifiedNoteError")
}
n := e.Note
if len(n.Sigs) != 0 || len(n.UnverifiedSigs) != 1 {
b.Fatal("wrong signature count")
}
}
})
b.Run("Sig1", func(b *testing.B) {
for i := 0; i < b.N; i++ {
n, err := Open(msg, verifiers)
if err != nil {
b.Fatal(err)
}
if len(n.Sigs) != 1 || len(n.UnverifiedSigs) != 0 {
b.Fatal("wrong signature count")
}
}
})
}

View File

@ -1,183 +0,0 @@
// Copyright 2018 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 semver
import (
"strings"
"testing"
)
var tests = []struct {
in string
out string
}{
{"bad", ""},
{"v1-alpha.beta.gamma", ""},
{"v1-pre", ""},
{"v1+meta", ""},
{"v1-pre+meta", ""},
{"v1.2-pre", ""},
{"v1.2+meta", ""},
{"v1.2-pre+meta", ""},
{"v1.0.0-alpha", "v1.0.0-alpha"},
{"v1.0.0-alpha.1", "v1.0.0-alpha.1"},
{"v1.0.0-alpha.beta", "v1.0.0-alpha.beta"},
{"v1.0.0-beta", "v1.0.0-beta"},
{"v1.0.0-beta.2", "v1.0.0-beta.2"},
{"v1.0.0-beta.11", "v1.0.0-beta.11"},
{"v1.0.0-rc.1", "v1.0.0-rc.1"},
{"v1", "v1.0.0"},
{"v1.0", "v1.0.0"},
{"v1.0.0", "v1.0.0"},
{"v1.2", "v1.2.0"},
{"v1.2.0", "v1.2.0"},
{"v1.2.3-456", "v1.2.3-456"},
{"v1.2.3-456.789", "v1.2.3-456.789"},
{"v1.2.3-456-789", "v1.2.3-456-789"},
{"v1.2.3-456a", "v1.2.3-456a"},
{"v1.2.3-pre", "v1.2.3-pre"},
{"v1.2.3-pre+meta", "v1.2.3-pre"},
{"v1.2.3-pre.1", "v1.2.3-pre.1"},
{"v1.2.3-zzz", "v1.2.3-zzz"},
{"v1.2.3", "v1.2.3"},
{"v1.2.3+meta", "v1.2.3"},
{"v1.2.3+meta-pre", "v1.2.3"},
{"v1.2.3+meta-pre.sha.256a", "v1.2.3"},
}
func TestIsValid(t *testing.T) {
for _, tt := range tests {
ok := IsValid(tt.in)
if ok != (tt.out != "") {
t.Errorf("IsValid(%q) = %v, want %v", tt.in, ok, !ok)
}
}
}
func TestCanonical(t *testing.T) {
for _, tt := range tests {
out := Canonical(tt.in)
if out != tt.out {
t.Errorf("Canonical(%q) = %q, want %q", tt.in, out, tt.out)
}
}
}
func TestMajor(t *testing.T) {
for _, tt := range tests {
out := Major(tt.in)
want := ""
if i := strings.Index(tt.out, "."); i >= 0 {
want = tt.out[:i]
}
if out != want {
t.Errorf("Major(%q) = %q, want %q", tt.in, out, want)
}
}
}
func TestMajorMinor(t *testing.T) {
for _, tt := range tests {
out := MajorMinor(tt.in)
var want string
if tt.out != "" {
want = tt.in
if i := strings.Index(want, "+"); i >= 0 {
want = want[:i]
}
if i := strings.Index(want, "-"); i >= 0 {
want = want[:i]
}
switch strings.Count(want, ".") {
case 0:
want += ".0"
case 1:
// ok
case 2:
want = want[:strings.LastIndex(want, ".")]
}
}
if out != want {
t.Errorf("MajorMinor(%q) = %q, want %q", tt.in, out, want)
}
}
}
func TestPrerelease(t *testing.T) {
for _, tt := range tests {
pre := Prerelease(tt.in)
var want string
if tt.out != "" {
if i := strings.Index(tt.out, "-"); i >= 0 {
want = tt.out[i:]
}
}
if pre != want {
t.Errorf("Prerelease(%q) = %q, want %q", tt.in, pre, want)
}
}
}
func TestBuild(t *testing.T) {
for _, tt := range tests {
build := Build(tt.in)
var want string
if tt.out != "" {
if i := strings.Index(tt.in, "+"); i >= 0 {
want = tt.in[i:]
}
}
if build != want {
t.Errorf("Build(%q) = %q, want %q", tt.in, build, want)
}
}
}
func TestCompare(t *testing.T) {
for i, ti := range tests {
for j, tj := range tests {
cmp := Compare(ti.in, tj.in)
var want int
if ti.out == tj.out {
want = 0
} else if i < j {
want = -1
} else {
want = +1
}
if cmp != want {
t.Errorf("Compare(%q, %q) = %d, want %d", ti.in, tj.in, cmp, want)
}
}
}
}
func TestMax(t *testing.T) {
for i, ti := range tests {
for j, tj := range tests {
max := Max(ti.in, tj.in)
want := Canonical(ti.in)
if i < j {
want = Canonical(tj.in)
}
if max != want {
t.Errorf("Max(%q, %q) = %q, want %q", ti.in, tj.in, max, want)
}
}
}
}
var (
v1 = "v1.0.0+metadata-dash"
v2 = "v1.0.0+metadata-dash1"
)
func BenchmarkCompare(b *testing.B) {
for i := 0; i < b.N; i++ {
if Compare(v1, v2) != 0 {
b.Fatalf("bad compare")
}
}
}

View File

@ -1,460 +0,0 @@
// 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 sumdb
import (
"bytes"
"fmt"
"strings"
"sync"
"testing"
"cmd/go/internal/note"
"cmd/go/internal/tlog"
)
const (
testName = "localhost.localdev/sumdb"
testVerifierKey = "localhost.localdev/sumdb+00000c67+AcTrnkbUA+TU4heY3hkjiSES/DSQniBqIeQ/YppAUtK6"
testSignerKey = "PRIVATE+KEY+localhost.localdev/sumdb+00000c67+AXu6+oaVaOYuQOFrf1V59JK1owcFlJcHwwXHDfDGxSPk"
)
func TestClientLookup(t *testing.T) {
tc := newTestClient(t)
tc.mustHaveLatest(1)
// Basic lookup.
tc.mustLookup("rsc.io/sampler", "v1.3.0", "rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4=")
tc.mustHaveLatest(3)
// Everything should now be cached, both for the original package and its /go.mod.
tc.getOK = false
tc.mustLookup("rsc.io/sampler", "v1.3.0", "rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4=")
tc.mustLookup("rsc.io/sampler", "v1.3.0/go.mod", "rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=")
tc.mustHaveLatest(3)
tc.getOK = true
tc.getTileOK = false // the cache has what we need
// Lookup with multiple returned lines.
tc.mustLookup("rsc.io/quote", "v1.5.2", "rsc.io/quote v1.5.2 h1:w5fcysjrx7yqtD/aO+QwRjYZOKnaM9Uh2b40tElTs3Y=\nrsc.io/quote v1.5.2 h2:xyzzy")
tc.mustHaveLatest(3)
// Lookup with need for !-encoding.
// rsc.io/Quote is the only record written after rsc.io/samper,
// so it is the only one that should need more tiles.
tc.getTileOK = true
tc.mustLookup("rsc.io/Quote", "v1.5.2", "rsc.io/Quote v1.5.2 h1:uppercase!=")
tc.mustHaveLatest(4)
}
func TestClientBadTiles(t *testing.T) {
tc := newTestClient(t)
flipBits := func() {
for url, data := range tc.remote {
if strings.Contains(url, "/tile/") {
for i := range data {
data[i] ^= 0x80
}
}
}
}
// Bad tiles in initial download.
tc.mustHaveLatest(1)
flipBits()
_, err := tc.client.Lookup("rsc.io/sampler", "v1.3.0")
tc.mustError(err, "rsc.io/sampler@v1.3.0: initializing sumdb.Client: checking tree#1: downloaded inconsistent tile")
flipBits()
tc.newClient()
tc.mustLookup("rsc.io/sampler", "v1.3.0", "rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4=")
// Bad tiles after initial download.
flipBits()
_, err = tc.client.Lookup("rsc.io/Quote", "v1.5.2")
tc.mustError(err, "rsc.io/Quote@v1.5.2: checking tree#3 against tree#4: downloaded inconsistent tile")
flipBits()
tc.newClient()
tc.mustLookup("rsc.io/Quote", "v1.5.2", "rsc.io/Quote v1.5.2 h1:uppercase!=")
// Bad starting tree hash looks like bad tiles.
tc.newClient()
text := tlog.FormatTree(tlog.Tree{N: 1, Hash: tlog.Hash{}})
data, err := note.Sign(&note.Note{Text: string(text)}, tc.signer)
if err != nil {
tc.t.Fatal(err)
}
tc.config[testName+"/latest"] = data
_, err = tc.client.Lookup("rsc.io/sampler", "v1.3.0")
tc.mustError(err, "rsc.io/sampler@v1.3.0: initializing sumdb.Client: checking tree#1: downloaded inconsistent tile")
}
func TestClientFork(t *testing.T) {
tc := newTestClient(t)
tc2 := tc.fork()
tc.addRecord("rsc.io/pkg1@v1.5.2", `rsc.io/pkg1 v1.5.2 h1:hash!=
`)
tc.addRecord("rsc.io/pkg1@v1.5.4", `rsc.io/pkg1 v1.5.4 h1:hash!=
`)
tc.mustLookup("rsc.io/pkg1", "v1.5.2", "rsc.io/pkg1 v1.5.2 h1:hash!=")
tc2.addRecord("rsc.io/pkg1@v1.5.3", `rsc.io/pkg1 v1.5.3 h1:hash!=
`)
tc2.addRecord("rsc.io/pkg1@v1.5.4", `rsc.io/pkg1 v1.5.4 h1:hash!=
`)
tc2.mustLookup("rsc.io/pkg1", "v1.5.4", "rsc.io/pkg1 v1.5.4 h1:hash!=")
key := "/lookup/rsc.io/pkg1@v1.5.2"
tc2.remote[key] = tc.remote[key]
_, err := tc2.client.Lookup("rsc.io/pkg1", "v1.5.2")
tc2.mustError(err, ErrSecurity.Error())
/*
SECURITY ERROR
go.sum database server misbehavior detected!
old database:
go.sum database tree!
5
nWzN20+pwMt62p7jbv1/NlN95ePTlHijabv5zO/s36w=
localhost.localdev/sumdb AAAMZ5/2FVAdMH58kmnz/0h299pwyskEbzDzoa2/YaPdhvLya4YWDFQQxu2TQb5GpwAH4NdWnTwuhILafisyf3CNbgg=
new database:
go.sum database tree
6
wc4SkQt52o5W2nQ8To2ARs+mWuUJjss+sdleoiqxMmM=
localhost.localdev/sumdb AAAMZ6oRNswlEZ6ZZhxrCvgl1MBy+nusq4JU+TG6Fe2NihWLqOzb+y2c2kzRLoCr4tvw9o36ucQEnhc20e4nA4Qc/wc=
proof of misbehavior:
T7i+H/8ER4nXOiw4Bj0koZOkGjkxoNvlI34GpvhHhQg=
Nsuejv72de9hYNM5bqFv8rv3gm3zJQwv/DT/WNbLDLA=
mOmqqZ1aI/lzS94oq/JSbj7pD8Rv9S+xDyi12BtVSHo=
/7Aw5jVSMM9sFjQhaMg+iiDYPMk6decH7QLOGrL9Lx0=
*/
wants := []string{
"SECURITY ERROR",
"go.sum database server misbehavior detected!",
"old database:\n\tgo.sum database tree\n\t5\n",
"— localhost.localdev/sumdb AAAMZ5/2FVAd",
"new database:\n\tgo.sum database tree\n\t6\n",
"— localhost.localdev/sumdb AAAMZ6oRNswl",
"proof of misbehavior:\n\tT7i+H/8ER4nXOiw4Bj0k",
}
text := tc2.security.String()
for _, want := range wants {
if !strings.Contains(text, want) {
t.Fatalf("cannot find %q in security text:\n%s", want, text)
}
}
}
func TestClientGONOSUMDB(t *testing.T) {
tc := newTestClient(t)
tc.client.SetGONOSUMDB("p,*/q")
tc.client.Lookup("rsc.io/sampler", "v1.3.0") // initialize before we turn off network
tc.getOK = false
ok := []string{
"abc",
"a/p",
"pq",
"q",
"n/o/p/q",
}
skip := []string{
"p",
"p/x",
"x/q",
"x/q/z",
}
for _, path := range ok {
_, err := tc.client.Lookup(path, "v1.0.0")
if err == ErrGONOSUMDB {
t.Errorf("Lookup(%q): ErrGONOSUMDB, wanted failed actual lookup", path)
}
}
for _, path := range skip {
_, err := tc.client.Lookup(path, "v1.0.0")
if err != ErrGONOSUMDB {
t.Errorf("Lookup(%q): %v, wanted ErrGONOSUMDB", path, err)
}
}
}
// A testClient is a self-contained client-side testing environment.
type testClient struct {
t *testing.T // active test
client *Client // client being tested
tileHeight int // tile height to use (default 2)
getOK bool // should tc.GetURL succeed?
getTileOK bool // should tc.GetURL of tiles succeed?
treeSize int64
hashes []tlog.Hash
remote map[string][]byte
signer note.Signer
// mu protects config, cache, log, security
// during concurrent use of the exported methods
// by the client itself (testClient is the Client's ClientOps,
// and the Client methods can both read and write these fields).
// Unexported methods invoked directly by the test
// (for example, addRecord) need not hold the mutex:
// for proper test execution those methods should only
// be called when the Client is idle and not using its ClientOps.
// Not holding the mutex in those methods ensures
// that if a mistake is made, go test -race will report it.
// (Holding the mutex would eliminate the race report but
// not the underlying problem.)
// Similarly, the get map is not protected by the mutex,
// because the Client methods only read it.
mu sync.Mutex // prot
config map[string][]byte
cache map[string][]byte
security bytes.Buffer
}
// newTestClient returns a new testClient that will call t.Fatal on error
// and has a few records already available on the remote server.
func newTestClient(t *testing.T) *testClient {
tc := &testClient{
t: t,
tileHeight: 2,
getOK: true,
getTileOK: true,
config: make(map[string][]byte),
cache: make(map[string][]byte),
remote: make(map[string][]byte),
}
tc.config["key"] = []byte(testVerifierKey + "\n")
var err error
tc.signer, err = note.NewSigner(testSignerKey)
if err != nil {
t.Fatal(err)
}
tc.newClient()
tc.addRecord("rsc.io/quote@v1.5.2", `rsc.io/quote v1.5.2 h1:w5fcysjrx7yqtD/aO+QwRjYZOKnaM9Uh2b40tElTs3Y=
rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
rsc.io/quote v1.5.2 h2:xyzzy
`)
tc.addRecord("golang.org/x/text@v0.0.0-20170915032832-14c0d48ead0c", `golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:qgOY6WgZOaTkIIMiVjBQcw93ERBE4m30iBm00nkL0i8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
`)
tc.addRecord("rsc.io/sampler@v1.3.0", `rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
`)
tc.config[testName+"/latest"] = tc.signTree(1)
tc.addRecord("rsc.io/!quote@v1.5.2", `rsc.io/Quote v1.5.2 h1:uppercase!=
`)
return tc
}
// newClient resets the Client associated with tc.
// This clears any in-memory cache from the Client
// but not tc's on-disk cache.
func (tc *testClient) newClient() {
tc.client = NewClient(tc)
tc.client.SetTileHeight(tc.tileHeight)
}
// mustLookup does a lookup for path@vers and checks that the lines that come back match want.
func (tc *testClient) mustLookup(path, vers, want string) {
tc.t.Helper()
lines, err := tc.client.Lookup(path, vers)
if err != nil {
tc.t.Fatal(err)
}
if strings.Join(lines, "\n") != want {
tc.t.Fatalf("Lookup(%q, %q):\n\t%s\nwant:\n\t%s", path, vers, strings.Join(lines, "\n\t"), strings.Replace(want, "\n", "\n\t", -1))
}
}
// mustHaveLatest checks that the on-disk configuration
// for latest is a tree of size n.
func (tc *testClient) mustHaveLatest(n int64) {
tc.t.Helper()
latest := tc.config[testName+"/latest"]
lines := strings.Split(string(latest), "\n")
if len(lines) < 2 || lines[1] != fmt.Sprint(n) {
tc.t.Fatalf("/latest should have tree %d, but has:\n%s", n, latest)
}
}
// mustError checks that err's error string contains the text.
func (tc *testClient) mustError(err error, text string) {
tc.t.Helper()
if err == nil || !strings.Contains(err.Error(), text) {
tc.t.Fatalf("err = %v, want %q", err, text)
}
}
// fork returns a copy of tc.
// Changes made to the new copy or to tc are not reflected in the other.
func (tc *testClient) fork() *testClient {
tc2 := &testClient{
t: tc.t,
getOK: tc.getOK,
getTileOK: tc.getTileOK,
tileHeight: tc.tileHeight,
treeSize: tc.treeSize,
hashes: append([]tlog.Hash{}, tc.hashes...),
signer: tc.signer,
config: copyMap(tc.config),
cache: copyMap(tc.cache),
remote: copyMap(tc.remote),
}
tc2.newClient()
return tc2
}
func copyMap(m map[string][]byte) map[string][]byte {
m2 := make(map[string][]byte)
for k, v := range m {
m2[k] = v
}
return m2
}
// ReadHashes is tc's implementation of tlog.HashReader, for use with
// tlog.TreeHash and so on.
func (tc *testClient) ReadHashes(indexes []int64) ([]tlog.Hash, error) {
var list []tlog.Hash
for _, id := range indexes {
list = append(list, tc.hashes[id])
}
return list, nil
}
// addRecord adds a log record using the given (!-encoded) key and data.
func (tc *testClient) addRecord(key, data string) {
tc.t.Helper()
// Create record, add hashes to log tree.
id := tc.treeSize
tc.treeSize++
rec, err := tlog.FormatRecord(id, []byte(data))
if err != nil {
tc.t.Fatal(err)
}
hashes, err := tlog.StoredHashesForRecordHash(id, tlog.RecordHash([]byte(data)), tc)
if err != nil {
tc.t.Fatal(err)
}
tc.hashes = append(tc.hashes, hashes...)
// Create lookup result.
tc.remote["/lookup/"+key] = append(rec, tc.signTree(tc.treeSize)...)
// Create new tiles.
tiles := tlog.NewTiles(tc.tileHeight, id, tc.treeSize)
for _, tile := range tiles {
data, err := tlog.ReadTileData(tile, tc)
if err != nil {
tc.t.Fatal(err)
}
tc.remote["/"+tile.Path()] = data
// TODO delete old partial tiles
}
}
// signTree returns the signed head for the tree of the given size.
func (tc *testClient) signTree(size int64) []byte {
h, err := tlog.TreeHash(size, tc)
if err != nil {
tc.t.Fatal(err)
}
text := tlog.FormatTree(tlog.Tree{N: size, Hash: h})
data, err := note.Sign(&note.Note{Text: string(text)}, tc.signer)
if err != nil {
tc.t.Fatal(err)
}
return data
}
// ReadRemote is for tc's implementation of Client.
func (tc *testClient) ReadRemote(path string) ([]byte, error) {
// No mutex here because only the Client should be running
// and the Client cannot change tc.get.
if !tc.getOK {
return nil, fmt.Errorf("disallowed remote read %s", path)
}
if strings.Contains(path, "/tile/") && !tc.getTileOK {
return nil, fmt.Errorf("disallowed remote tile read %s", path)
}
data, ok := tc.remote[path]
if !ok {
return nil, fmt.Errorf("no remote path %s", path)
}
return data, nil
}
// ReadConfig is for tc's implementation of Client.
func (tc *testClient) ReadConfig(file string) ([]byte, error) {
tc.mu.Lock()
defer tc.mu.Unlock()
data, ok := tc.config[file]
if !ok {
return nil, fmt.Errorf("no config %s", file)
}
return data, nil
}
// WriteConfig is for tc's implementation of Client.
func (tc *testClient) WriteConfig(file string, old, new []byte) error {
tc.mu.Lock()
defer tc.mu.Unlock()
data := tc.config[file]
if !bytes.Equal(old, data) {
return ErrWriteConflict
}
tc.config[file] = new
return nil
}
// ReadCache is for tc's implementation of Client.
func (tc *testClient) ReadCache(file string) ([]byte, error) {
tc.mu.Lock()
defer tc.mu.Unlock()
data, ok := tc.cache[file]
if !ok {
return nil, fmt.Errorf("no cache %s", file)
}
return data, nil
}
// WriteCache is for tc's implementation of Client.
func (tc *testClient) WriteCache(file string, data []byte) {
tc.mu.Lock()
defer tc.mu.Unlock()
tc.cache[file] = data
}
// Log is for tc's implementation of Client.
func (tc *testClient) Log(msg string) {
tc.t.Log(msg)
}
// SecurityError is for tc's implementation of Client.
func (tc *testClient) SecurityError(msg string) {
tc.mu.Lock()
defer tc.mu.Unlock()
fmt.Fprintf(&tc.security, "%s\n", strings.TrimRight(msg, "\n"))
}

View File

@ -1,96 +0,0 @@
// 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 tlog
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"os"
"testing"
)
func TestCertificateTransparency(t *testing.T) {
// Test that we can verify actual Certificate Transparency proofs.
// (The other tests check that we can verify our own proofs;
// this is a test that the two are compatible.)
if testing.Short() {
t.Skip("skipping in -short mode")
}
var root ctTree
httpGET(t, "http://ct.googleapis.com/logs/argon2020/ct/v1/get-sth", &root)
var leaf ctEntries
httpGET(t, "http://ct.googleapis.com/logs/argon2020/ct/v1/get-entries?start=10000&end=10000", &leaf)
hash := RecordHash(leaf.Entries[0].Data)
var rp ctRecordProof
httpGET(t, "http://ct.googleapis.com/logs/argon2020/ct/v1/get-proof-by-hash?tree_size="+fmt.Sprint(root.Size)+"&hash="+url.QueryEscape(hash.String()), &rp)
err := CheckRecord(rp.Proof, root.Size, root.Hash, 10000, hash)
if err != nil {
t.Fatal(err)
}
var tp ctTreeProof
httpGET(t, "http://ct.googleapis.com/logs/argon2020/ct/v1/get-sth-consistency?first=3654490&second="+fmt.Sprint(root.Size), &tp)
oh, _ := ParseHash("AuIZ5V6sDUj1vn3Y1K85oOaQ7y+FJJKtyRTl1edIKBQ=")
err = CheckTree(tp.Proof, root.Size, root.Hash, 3654490, oh)
if err != nil {
t.Fatal(err)
}
}
type ctTree struct {
Size int64 `json:"tree_size"`
Hash Hash `json:"sha256_root_hash"`
}
type ctEntries struct {
Entries []*ctEntry
}
type ctEntry struct {
Data []byte `json:"leaf_input"`
}
type ctRecordProof struct {
Index int64 `json:"leaf_index"`
Proof RecordProof `json:"audit_path"`
}
type ctTreeProof struct {
Proof TreeProof `json:"consistency"`
}
func httpGET(t *testing.T, url string, targ interface{}) {
if testing.Verbose() {
println()
println(url)
}
resp, err := http.Get(url)
if err != nil {
t.Fatal(err)
}
defer resp.Body.Close()
data, err := ioutil.ReadAll(resp.Body)
if err != nil {
t.Fatal(err)
}
if testing.Verbose() {
os.Stdout.Write(data)
}
err = json.Unmarshal(data, targ)
if err != nil {
println(url)
os.Stdout.Write(data)
t.Fatal(err)
}
}

View File

@ -1,117 +0,0 @@
// 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 tlog
import (
"strings"
"testing"
)
func TestFormatTree(t *testing.T) {
n := int64(123456789012)
h := RecordHash([]byte("hello world"))
golden := "go.sum database tree\n123456789012\nTszzRgjTG6xce+z2AG31kAXYKBgQVtCSCE40HmuwBb0=\n"
b := FormatTree(Tree{n, h})
if string(b) != golden {
t.Errorf("FormatTree(...) = %q, want %q", b, golden)
}
}
func TestParseTree(t *testing.T) {
in := "go.sum database tree\n123456789012\nTszzRgjTG6xce+z2AG31kAXYKBgQVtCSCE40HmuwBb0=\n"
goldH := RecordHash([]byte("hello world"))
goldN := int64(123456789012)
tree, err := ParseTree([]byte(in))
if tree.N != goldN || tree.Hash != goldH || err != nil {
t.Fatalf("ParseTree(...) = Tree{%d, %v}, %v, want Tree{%d, %v}, nil", tree.N, tree.Hash, err, goldN, goldH)
}
// Check invalid trees.
var badTrees = []string{
"not-" + in,
"go.sum database tree\n0xabcdef\nTszzRgjTG6xce+z2AG31kAXYKBgQVtCSCE40HmuwBb0=\n",
"go.sum database tree\n123456789012\nTszzRgjTG6xce+z2AG31kAXYKBgQVtCSCE40HmuwBTOOBIG=\n",
}
for _, bad := range badTrees {
_, err := ParseTree([]byte(bad))
if err == nil {
t.Fatalf("ParseTree(%q) succeeded, want failure", in)
}
}
// Check junk on end is ignored.
var goodTrees = []string{
in + "JOE",
in + "JOE\n",
in + strings.Repeat("JOE\n", 1000),
}
for _, good := range goodTrees {
_, err := ParseTree([]byte(good))
if tree.N != goldN || tree.Hash != goldH || err != nil {
t.Fatalf("ParseTree(...+%q) = Tree{%d, %v}, %v, want Tree{%d, %v}, nil", good[len(in):], tree.N, tree.Hash, err, goldN, goldH)
}
}
}
func TestFormatRecord(t *testing.T) {
id := int64(123456789012)
text := "hello, world\n"
golden := "123456789012\nhello, world\n\n"
msg, err := FormatRecord(id, []byte(text))
if err != nil {
t.Fatalf("FormatRecord: %v", err)
}
if string(msg) != golden {
t.Fatalf("FormatRecord(...) = %q, want %q", msg, golden)
}
var badTexts = []string{
"",
"hello\nworld",
"hello\n\nworld\n",
"hello\x01world\n",
}
for _, bad := range badTexts {
msg, err := FormatRecord(id, []byte(bad))
if err == nil {
t.Errorf("FormatRecord(id, %q) = %q, want error", bad, msg)
}
}
}
func TestParseRecord(t *testing.T) {
in := "123456789012\nhello, world\n\njunk on end\x01\xff"
goldID := int64(123456789012)
goldText := "hello, world\n"
goldRest := "junk on end\x01\xff"
id, text, rest, err := ParseRecord([]byte(in))
if id != goldID || string(text) != goldText || string(rest) != goldRest || err != nil {
t.Fatalf("ParseRecord(%q) = %d, %q, %q, %v, want %d, %q, %q, nil", in, id, text, rest, err, goldID, goldText, goldRest)
}
in = "123456789012\nhello, world\n\n"
id, text, rest, err = ParseRecord([]byte(in))
if id != goldID || string(text) != goldText || len(rest) != 0 || err != nil {
t.Fatalf("ParseRecord(%q) = %d, %q, %q, %v, want %d, %q, %q, nil", in, id, text, rest, err, goldID, goldText, "")
}
if rest == nil {
t.Fatalf("ParseRecord(%q): rest = []byte(nil), want []byte{}", in)
}
// Check invalid records.
var badRecords = []string{
"not-" + in,
"123\nhello\x01world\n\n",
"123\nhello\xffworld\n\n",
"123\nhello world\n",
"0x123\nhello world\n\n",
}
for _, bad := range badRecords {
id, text, rest, err := ParseRecord([]byte(bad))
if err == nil {
t.Fatalf("ParseRecord(%q) = %d, %q, %q, nil, want error", in, id, text, rest)
}
}
}

View File

@ -1,269 +0,0 @@
// 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 tlog
import (
"bytes"
"fmt"
"testing"
)
type testHashStorage []Hash
func (t testHashStorage) ReadHash(level int, n int64) (Hash, error) {
return t[StoredHashIndex(level, n)], nil
}
func (t testHashStorage) ReadHashes(index []int64) ([]Hash, error) {
// It's not required by HashReader that indexes be in increasing order,
// but check that the functions we are testing only ever ask for
// indexes in increasing order.
for i := 1; i < len(index); i++ {
if index[i-1] >= index[i] {
panic("indexes out of order")
}
}
out := make([]Hash, len(index))
for i, x := range index {
out[i] = t[x]
}
return out, nil
}
type testTilesStorage struct {
unsaved int
m map[Tile][]byte
}
func (t testTilesStorage) Height() int {
return 2
}
func (t *testTilesStorage) SaveTiles(tiles []Tile, data [][]byte) {
t.unsaved -= len(tiles)
}
func (t *testTilesStorage) ReadTiles(tiles []Tile) ([][]byte, error) {
out := make([][]byte, len(tiles))
for i, tile := range tiles {
out[i] = t.m[tile]
}
t.unsaved += len(tiles)
return out, nil
}
func TestTree(t *testing.T) {
var trees []Hash
var leafhashes []Hash
var storage testHashStorage
tiles := make(map[Tile][]byte)
const testH = 2
for i := int64(0); i < 100; i++ {
data := []byte(fmt.Sprintf("leaf %d", i))
hashes, err := StoredHashes(i, data, storage)
if err != nil {
t.Fatal(err)
}
leafhashes = append(leafhashes, RecordHash(data))
oldStorage := len(storage)
storage = append(storage, hashes...)
if count := StoredHashCount(i + 1); count != int64(len(storage)) {
t.Errorf("StoredHashCount(%d) = %d, have %d StoredHashes", i+1, count, len(storage))
}
th, err := TreeHash(i+1, storage)
if err != nil {
t.Fatal(err)
}
for _, tile := range NewTiles(testH, i, i+1) {
data, err := ReadTileData(tile, storage)
if err != nil {
t.Fatal(err)
}
old := Tile{H: tile.H, L: tile.L, N: tile.N, W: tile.W - 1}
oldData := tiles[old]
if len(oldData) != len(data)-HashSize || !bytes.Equal(oldData, data[:len(oldData)]) {
t.Fatalf("tile %v not extending earlier tile %v", tile.Path(), old.Path())
}
tiles[tile] = data
}
for _, tile := range NewTiles(testH, 0, i+1) {
data, err := ReadTileData(tile, storage)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(tiles[tile], data) {
t.Fatalf("mismatch at %+v", tile)
}
}
for _, tile := range NewTiles(testH, i/2, i+1) {
data, err := ReadTileData(tile, storage)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(tiles[tile], data) {
t.Fatalf("mismatch at %+v", tile)
}
}
// Check that all the new hashes are readable from their tiles.
for j := oldStorage; j < len(storage); j++ {
tile := TileForIndex(testH, int64(j))
data, ok := tiles[tile]
if !ok {
t.Log(NewTiles(testH, 0, i+1))
t.Fatalf("TileForIndex(%d, %d) = %v, not yet stored (i=%d, stored %d)", testH, j, tile.Path(), i, len(storage))
continue
}
h, err := HashFromTile(tile, data, int64(j))
if err != nil {
t.Fatal(err)
}
if h != storage[j] {
t.Errorf("HashFromTile(%v, %d) = %v, want %v", tile.Path(), int64(j), h, storage[j])
}
}
trees = append(trees, th)
// Check that leaf proofs work, for all trees and leaves so far.
for j := int64(0); j <= i; j++ {
p, err := ProveRecord(i+1, j, storage)
if err != nil {
t.Fatalf("ProveRecord(%d, %d): %v", i+1, j, err)
}
if err := CheckRecord(p, i+1, th, j, leafhashes[j]); err != nil {
t.Fatalf("CheckRecord(%d, %d): %v", i+1, j, err)
}
for k := range p {
p[k][0] ^= 1
if err := CheckRecord(p, i+1, th, j, leafhashes[j]); err == nil {
t.Fatalf("CheckRecord(%d, %d) succeeded with corrupt proof hash #%d!", i+1, j, k)
}
p[k][0] ^= 1
}
}
// Check that leaf proofs work using TileReader.
// To prove a leaf that way, all you have to do is read and verify its hash.
storage := &testTilesStorage{m: tiles}
thr := TileHashReader(Tree{i + 1, th}, storage)
for j := int64(0); j <= i; j++ {
h, err := thr.ReadHashes([]int64{StoredHashIndex(0, j)})
if err != nil {
t.Fatalf("TileHashReader(%d).ReadHashes(%d): %v", i+1, j, err)
}
if h[0] != leafhashes[j] {
t.Fatalf("TileHashReader(%d).ReadHashes(%d) returned wrong hash", i+1, j)
}
// Even though reading the hash suffices,
// check we can generate the proof too.
p, err := ProveRecord(i+1, j, thr)
if err != nil {
t.Fatalf("ProveRecord(%d, %d, TileHashReader(%d)): %v", i+1, j, i+1, err)
}
if err := CheckRecord(p, i+1, th, j, leafhashes[j]); err != nil {
t.Fatalf("CheckRecord(%d, %d, TileHashReader(%d)): %v", i+1, j, i+1, err)
}
}
if storage.unsaved != 0 {
t.Fatalf("TileHashReader(%d) did not save %d tiles", i+1, storage.unsaved)
}
// Check that ReadHashes will give an error if the index is not in the tree.
if _, err := thr.ReadHashes([]int64{(i + 1) * 2}); err == nil {
t.Fatalf("TileHashReader(%d).ReadHashes(%d) for index not in tree <nil>, want err", i, i+1)
}
if storage.unsaved != 0 {
t.Fatalf("TileHashReader(%d) did not save %d tiles", i+1, storage.unsaved)
}
// Check that tree proofs work, for all trees so far, using TileReader.
// To prove a tree that way, all you have to do is compute and verify its hash.
for j := int64(0); j <= i; j++ {
h, err := TreeHash(j+1, thr)
if err != nil {
t.Fatalf("TreeHash(%d, TileHashReader(%d)): %v", j, i+1, err)
}
if h != trees[j] {
t.Fatalf("TreeHash(%d, TileHashReader(%d)) = %x, want %x (%v)", j, i+1, h[:], trees[j][:], trees[j])
}
// Even though computing the subtree hash suffices,
// check that we can generate the proof too.
p, err := ProveTree(i+1, j+1, thr)
if err != nil {
t.Fatalf("ProveTree(%d, %d): %v", i+1, j+1, err)
}
if err := CheckTree(p, i+1, th, j+1, trees[j]); err != nil {
t.Fatalf("CheckTree(%d, %d): %v [%v]", i+1, j+1, err, p)
}
for k := range p {
p[k][0] ^= 1
if err := CheckTree(p, i+1, th, j+1, trees[j]); err == nil {
t.Fatalf("CheckTree(%d, %d) succeeded with corrupt proof hash #%d!", i+1, j+1, k)
}
p[k][0] ^= 1
}
}
if storage.unsaved != 0 {
t.Fatalf("TileHashReader(%d) did not save %d tiles", i+1, storage.unsaved)
}
}
}
func TestSplitStoredHashIndex(t *testing.T) {
for l := 0; l < 10; l++ {
for n := int64(0); n < 100; n++ {
x := StoredHashIndex(l, n)
l1, n1 := SplitStoredHashIndex(x)
if l1 != l || n1 != n {
t.Fatalf("StoredHashIndex(%d, %d) = %d, but SplitStoredHashIndex(%d) = %d, %d", l, n, x, x, l1, n1)
}
}
}
}
// TODO(rsc): Test invalid paths too, like "tile/3/5/123/456/078".
var tilePaths = []struct {
path string
tile Tile
}{
{"tile/4/0/001", Tile{4, 0, 1, 16}},
{"tile/4/0/001.p/5", Tile{4, 0, 1, 5}},
{"tile/3/5/x123/x456/078", Tile{3, 5, 123456078, 8}},
{"tile/3/5/x123/x456/078.p/2", Tile{3, 5, 123456078, 2}},
{"tile/1/0/x003/x057/500", Tile{1, 0, 3057500, 2}},
{"tile/3/5/123/456/078", Tile{}},
{"tile/3/-1/123/456/078", Tile{}},
{"tile/1/data/x003/x057/500", Tile{1, -1, 3057500, 2}},
}
func TestTilePath(t *testing.T) {
for _, tt := range tilePaths {
if tt.tile.H > 0 {
p := tt.tile.Path()
if p != tt.path {
t.Errorf("%+v.Path() = %q, want %q", tt.tile, p, tt.path)
}
}
tile, err := ParseTilePath(tt.path)
if err != nil {
if tt.tile.H == 0 {
// Expected error.
continue
}
t.Errorf("ParseTilePath(%q): %v", tt.path, err)
} else if tile != tt.tile {
if tt.tile.H == 0 {
t.Errorf("ParseTilePath(%q): expected error, got %+v", tt.path, tt.tile)
continue
}
t.Errorf("ParseTilePath(%q) = %+v, want %+v", tt.path, tile, tt.tile)
}
}
}

View File

@ -23,14 +23,15 @@ import (
"sync"
"testing"
"cmd/go/internal/dirhash"
"cmd/go/internal/modfetch"
"cmd/go/internal/modfetch/codehost"
"cmd/go/internal/module"
"cmd/go/internal/par"
"cmd/go/internal/semver"
"cmd/go/internal/sumdb"
"cmd/go/internal/txtar"
"golang.org/x/mod/module"
"golang.org/x/mod/semver"
"golang.org/x/mod/sumdb"
"golang.org/x/mod/sumdb/dirhash"
)
var (

222
src/cmd/vendor/golang.org/x/crypto/ed25519/ed25519.go generated vendored Normal file
View File

@ -0,0 +1,222 @@
// Copyright 2016 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.
// In Go 1.13, the ed25519 package was promoted to the standard library as
// crypto/ed25519, and this package became a wrapper for the standard library one.
//
// +build !go1.13
// Package ed25519 implements the Ed25519 signature algorithm. See
// https://ed25519.cr.yp.to/.
//
// These functions are also compatible with the “Ed25519” function defined in
// RFC 8032. However, unlike RFC 8032's formulation, this package's private key
// representation includes a public key suffix to make multiple signing
// operations with the same key more efficient. This package refers to the RFC
// 8032 private key as the “seed”.
package ed25519
// This code is a port of the public domain, “ref10” implementation of ed25519
// from SUPERCOP.
import (
"bytes"
"crypto"
cryptorand "crypto/rand"
"crypto/sha512"
"errors"
"io"
"strconv"
"golang.org/x/crypto/ed25519/internal/edwards25519"
)
const (
// PublicKeySize is the size, in bytes, of public keys as used in this package.
PublicKeySize = 32
// PrivateKeySize is the size, in bytes, of private keys as used in this package.
PrivateKeySize = 64
// SignatureSize is the size, in bytes, of signatures generated and verified by this package.
SignatureSize = 64
// SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032.
SeedSize = 32
)
// PublicKey is the type of Ed25519 public keys.
type PublicKey []byte
// PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer.
type PrivateKey []byte
// Public returns the PublicKey corresponding to priv.
func (priv PrivateKey) Public() crypto.PublicKey {
publicKey := make([]byte, PublicKeySize)
copy(publicKey, priv[32:])
return PublicKey(publicKey)
}
// Seed returns the private key seed corresponding to priv. It is provided for
// interoperability with RFC 8032. RFC 8032's private keys correspond to seeds
// in this package.
func (priv PrivateKey) Seed() []byte {
seed := make([]byte, SeedSize)
copy(seed, priv[:32])
return seed
}
// Sign signs the given message with priv.
// Ed25519 performs two passes over messages to be signed and therefore cannot
// handle pre-hashed messages. Thus opts.HashFunc() must return zero to
// indicate the message hasn't been hashed. This can be achieved by passing
// crypto.Hash(0) as the value for opts.
func (priv PrivateKey) Sign(rand io.Reader, message []byte, opts crypto.SignerOpts) (signature []byte, err error) {
if opts.HashFunc() != crypto.Hash(0) {
return nil, errors.New("ed25519: cannot sign hashed message")
}
return Sign(priv, message), nil
}
// GenerateKey generates a public/private key pair using entropy from rand.
// If rand is nil, crypto/rand.Reader will be used.
func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) {
if rand == nil {
rand = cryptorand.Reader
}
seed := make([]byte, SeedSize)
if _, err := io.ReadFull(rand, seed); err != nil {
return nil, nil, err
}
privateKey := NewKeyFromSeed(seed)
publicKey := make([]byte, PublicKeySize)
copy(publicKey, privateKey[32:])
return publicKey, privateKey, nil
}
// NewKeyFromSeed calculates a private key from a seed. It will panic if
// len(seed) is not SeedSize. This function is provided for interoperability
// with RFC 8032. RFC 8032's private keys correspond to seeds in this
// package.
func NewKeyFromSeed(seed []byte) PrivateKey {
if l := len(seed); l != SeedSize {
panic("ed25519: bad seed length: " + strconv.Itoa(l))
}
digest := sha512.Sum512(seed)
digest[0] &= 248
digest[31] &= 127
digest[31] |= 64
var A edwards25519.ExtendedGroupElement
var hBytes [32]byte
copy(hBytes[:], digest[:])
edwards25519.GeScalarMultBase(&A, &hBytes)
var publicKeyBytes [32]byte
A.ToBytes(&publicKeyBytes)
privateKey := make([]byte, PrivateKeySize)
copy(privateKey, seed)
copy(privateKey[32:], publicKeyBytes[:])
return privateKey
}
// Sign signs the message with privateKey and returns a signature. It will
// panic if len(privateKey) is not PrivateKeySize.
func Sign(privateKey PrivateKey, message []byte) []byte {
if l := len(privateKey); l != PrivateKeySize {
panic("ed25519: bad private key length: " + strconv.Itoa(l))
}
h := sha512.New()
h.Write(privateKey[:32])
var digest1, messageDigest, hramDigest [64]byte
var expandedSecretKey [32]byte
h.Sum(digest1[:0])
copy(expandedSecretKey[:], digest1[:])
expandedSecretKey[0] &= 248
expandedSecretKey[31] &= 63
expandedSecretKey[31] |= 64
h.Reset()
h.Write(digest1[32:])
h.Write(message)
h.Sum(messageDigest[:0])
var messageDigestReduced [32]byte
edwards25519.ScReduce(&messageDigestReduced, &messageDigest)
var R edwards25519.ExtendedGroupElement
edwards25519.GeScalarMultBase(&R, &messageDigestReduced)
var encodedR [32]byte
R.ToBytes(&encodedR)
h.Reset()
h.Write(encodedR[:])
h.Write(privateKey[32:])
h.Write(message)
h.Sum(hramDigest[:0])
var hramDigestReduced [32]byte
edwards25519.ScReduce(&hramDigestReduced, &hramDigest)
var s [32]byte
edwards25519.ScMulAdd(&s, &hramDigestReduced, &expandedSecretKey, &messageDigestReduced)
signature := make([]byte, SignatureSize)
copy(signature[:], encodedR[:])
copy(signature[32:], s[:])
return signature
}
// Verify reports whether sig is a valid signature of message by publicKey. It
// will panic if len(publicKey) is not PublicKeySize.
func Verify(publicKey PublicKey, message, sig []byte) bool {
if l := len(publicKey); l != PublicKeySize {
panic("ed25519: bad public key length: " + strconv.Itoa(l))
}
if len(sig) != SignatureSize || sig[63]&224 != 0 {
return false
}
var A edwards25519.ExtendedGroupElement
var publicKeyBytes [32]byte
copy(publicKeyBytes[:], publicKey)
if !A.FromBytes(&publicKeyBytes) {
return false
}
edwards25519.FeNeg(&A.X, &A.X)
edwards25519.FeNeg(&A.T, &A.T)
h := sha512.New()
h.Write(sig[:32])
h.Write(publicKey[:])
h.Write(message)
var digest [64]byte
h.Sum(digest[:0])
var hReduced [32]byte
edwards25519.ScReduce(&hReduced, &digest)
var R edwards25519.ProjectiveGroupElement
var s [32]byte
copy(s[:], sig[32:])
// https://tools.ietf.org/html/rfc8032#section-5.1.7 requires that s be in
// the range [0, order) in order to prevent signature malleability.
if !edwards25519.ScMinimal(&s) {
return false
}
edwards25519.GeDoubleScalarMultVartime(&R, &hReduced, &A, &s)
var checkR [32]byte
R.ToBytes(&checkR)
return bytes.Equal(sig[:32], checkR[:])
}

View File

@ -0,0 +1,73 @@
// 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.
// +build go1.13
// Package ed25519 implements the Ed25519 signature algorithm. See
// https://ed25519.cr.yp.to/.
//
// These functions are also compatible with the “Ed25519” function defined in
// RFC 8032. However, unlike RFC 8032's formulation, this package's private key
// representation includes a public key suffix to make multiple signing
// operations with the same key more efficient. This package refers to the RFC
// 8032 private key as the “seed”.
//
// Beginning with Go 1.13, the functionality of this package was moved to the
// standard library as crypto/ed25519. This package only acts as a compatibility
// wrapper.
package ed25519
import (
"crypto/ed25519"
"io"
)
const (
// PublicKeySize is the size, in bytes, of public keys as used in this package.
PublicKeySize = 32
// PrivateKeySize is the size, in bytes, of private keys as used in this package.
PrivateKeySize = 64
// SignatureSize is the size, in bytes, of signatures generated and verified by this package.
SignatureSize = 64
// SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032.
SeedSize = 32
)
// PublicKey is the type of Ed25519 public keys.
//
// This type is an alias for crypto/ed25519's PublicKey type.
// See the crypto/ed25519 package for the methods on this type.
type PublicKey = ed25519.PublicKey
// PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer.
//
// This type is an alias for crypto/ed25519's PrivateKey type.
// See the crypto/ed25519 package for the methods on this type.
type PrivateKey = ed25519.PrivateKey
// GenerateKey generates a public/private key pair using entropy from rand.
// If rand is nil, crypto/rand.Reader will be used.
func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) {
return ed25519.GenerateKey(rand)
}
// NewKeyFromSeed calculates a private key from a seed. It will panic if
// len(seed) is not SeedSize. This function is provided for interoperability
// with RFC 8032. RFC 8032's private keys correspond to seeds in this
// package.
func NewKeyFromSeed(seed []byte) PrivateKey {
return ed25519.NewKeyFromSeed(seed)
}
// Sign signs the message with privateKey and returns a signature. It will
// panic if len(privateKey) is not PrivateKeySize.
func Sign(privateKey PrivateKey, message []byte) []byte {
return ed25519.Sign(privateKey, message)
}
// Verify reports whether sig is a valid signature of message by publicKey. It
// will panic if len(publicKey) is not PublicKeySize.
func Verify(publicKey PublicKey, message, sig []byte) bool {
return ed25519.Verify(publicKey, message, sig)
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

27
src/cmd/vendor/golang.org/x/mod/LICENSE generated vendored Normal file
View File

@ -0,0 +1,27 @@
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

22
src/cmd/vendor/golang.org/x/mod/PATENTS generated vendored Normal file
View File

@ -0,0 +1,22 @@
Additional IP Rights Grant (Patents)
"This implementation" means the copyrightable works distributed by
Google as part of the Go project.
Google hereby grants to You a perpetual, worldwide, non-exclusive,
no-charge, royalty-free, irrevocable (except as stated in this section)
patent license to make, have made, use, offer to sell, sell, import,
transfer and otherwise run, modify and propagate the contents of this
implementation of Go, where such license applies only to those patent
claims, both currently owned or controlled by Google and acquired in
the future, licensable by Google that are necessarily infringed by this
implementation of Go. This grant does not include claims that would be
infringed only as a consequence of further modification of this
implementation. If you or your agent or exclusive licensee institute or
order or agree to the institution of patent litigation against any
entity (including a cross-claim or counterclaim in a lawsuit) alleging
that this implementation of Go or any code incorporated within this
implementation of Go constitutes direct or contributory patent
infringement, or inducement of patent infringement, then any patent
rights granted to you under this License for this implementation of Go
shall terminate as of the date such litigation is filed.

View File

@ -0,0 +1,78 @@
// Copyright 2018 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 lazyregexp is a thin wrapper over regexp, allowing the use of global
// regexp variables without forcing them to be compiled at init.
package lazyregexp
import (
"os"
"regexp"
"strings"
"sync"
)
// Regexp is a wrapper around regexp.Regexp, where the underlying regexp will be
// compiled the first time it is needed.
type Regexp struct {
str string
once sync.Once
rx *regexp.Regexp
}
func (r *Regexp) re() *regexp.Regexp {
r.once.Do(r.build)
return r.rx
}
func (r *Regexp) build() {
r.rx = regexp.MustCompile(r.str)
r.str = ""
}
func (r *Regexp) FindSubmatch(s []byte) [][]byte {
return r.re().FindSubmatch(s)
}
func (r *Regexp) FindStringSubmatch(s string) []string {
return r.re().FindStringSubmatch(s)
}
func (r *Regexp) FindStringSubmatchIndex(s string) []int {
return r.re().FindStringSubmatchIndex(s)
}
func (r *Regexp) ReplaceAllString(src, repl string) string {
return r.re().ReplaceAllString(src, repl)
}
func (r *Regexp) FindString(s string) string {
return r.re().FindString(s)
}
func (r *Regexp) FindAllString(s string, n int) []string {
return r.re().FindAllString(s, n)
}
func (r *Regexp) MatchString(s string) bool {
return r.re().MatchString(s)
}
func (r *Regexp) SubexpNames() []string {
return r.re().SubexpNames()
}
var inTest = len(os.Args) > 0 && strings.HasSuffix(strings.TrimSuffix(os.Args[0], ".exe"), ".test")
// New creates a new lazy regexp, delaying the compiling work until it is first
// needed. If the code is being run as part of tests, the regexp compiling will
// happen immediately.
func New(str string) *Regexp {
lr := &Regexp{str: str}
if inTest {
// In tests, always compile the regexps early.
lr.re()
}
return lr
}

View File

@ -8,14 +8,14 @@ import (
"bytes"
"errors"
"fmt"
"internal/lazyregexp"
"path/filepath"
"sort"
"strconv"
"strings"
"unicode"
"cmd/go/internal/module"
"golang.org/x/mod/internal/lazyregexp"
"golang.org/x/mod/module"
)
// A File is the parsed, interpreted form of a go.mod file.

View File

@ -96,14 +96,14 @@ package module
// Changes to the semantics in this file require approval from rsc.
import (
"errors"
"fmt"
"sort"
"strings"
"unicode"
"unicode/utf8"
"cmd/go/internal/semver"
"golang.org/x/mod/semver"
errors "golang.org/x/xerrors"
)
// A Version (for clients, a module.Version) is defined by a module path and version pair.

View File

@ -13,9 +13,9 @@ import (
"sync"
"sync/atomic"
"cmd/go/internal/module"
"cmd/go/internal/note"
"cmd/go/internal/tlog"
"golang.org/x/mod/module"
"golang.org/x/mod/sumdb/note"
"golang.org/x/mod/sumdb/tlog"
)
// A ClientOps provides the external operations

View File

@ -183,7 +183,6 @@ package note
import (
"bytes"
"crypto/ed25519"
"crypto/sha256"
"encoding/base64"
"encoding/binary"
@ -194,6 +193,8 @@ import (
"strings"
"unicode"
"unicode/utf8"
"golang.org/x/crypto/ed25519"
)
// A Verifier verifies messages signed with a specific key.

View File

@ -7,13 +7,13 @@ package sumdb
import (
"context"
"internal/lazyregexp"
"net/http"
"os"
"strings"
"cmd/go/internal/module"
"cmd/go/internal/tlog"
"golang.org/x/mod/internal/lazyregexp"
"golang.org/x/mod/module"
"golang.org/x/mod/sumdb/tlog"
)
// A ServerOps provides the external operations

View File

@ -9,9 +9,9 @@ import (
"fmt"
"sync"
"cmd/go/internal/module"
"cmd/go/internal/note"
"cmd/go/internal/tlog"
"golang.org/x/mod/module"
"golang.org/x/mod/sumdb/note"
"golang.org/x/mod/sumdb/tlog"
)
// NewTestServer constructs a new TestServer

27
src/cmd/vendor/golang.org/x/xerrors/LICENSE generated vendored Normal file
View File

@ -0,0 +1,27 @@
Copyright (c) 2019 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

22
src/cmd/vendor/golang.org/x/xerrors/PATENTS generated vendored Normal file
View File

@ -0,0 +1,22 @@
Additional IP Rights Grant (Patents)
"This implementation" means the copyrightable works distributed by
Google as part of the Go project.
Google hereby grants to You a perpetual, worldwide, non-exclusive,
no-charge, royalty-free, irrevocable (except as stated in this section)
patent license to make, have made, use, offer to sell, sell, import,
transfer and otherwise run, modify and propagate the contents of this
implementation of Go, where such license applies only to those patent
claims, both currently owned or controlled by Google and acquired in
the future, licensable by Google that are necessarily infringed by this
implementation of Go. This grant does not include claims that would be
infringed only as a consequence of further modification of this
implementation. If you or your agent or exclusive licensee institute or
order or agree to the institution of patent litigation against any
entity (including a cross-claim or counterclaim in a lawsuit) alleging
that this implementation of Go or any code incorporated within this
implementation of Go constitutes direct or contributory patent
infringement, or inducement of patent infringement, then any patent
rights granted to you under this License for this implementation of Go
shall terminate as of the date such litigation is filed.

2
src/cmd/vendor/golang.org/x/xerrors/README generated vendored Normal file
View File

@ -0,0 +1,2 @@
This repository holds the transition packages for the new Go 1.13 error values.
See golang.org/design/29934-error-values.

193
src/cmd/vendor/golang.org/x/xerrors/adaptor.go generated vendored Normal file
View File

@ -0,0 +1,193 @@
// Copyright 2018 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 xerrors
import (
"bytes"
"fmt"
"io"
"reflect"
"strconv"
)
// FormatError calls the FormatError method of f with an errors.Printer
// configured according to s and verb, and writes the result to s.
func FormatError(f Formatter, s fmt.State, verb rune) {
// Assuming this function is only called from the Format method, and given
// that FormatError takes precedence over Format, it cannot be called from
// any package that supports errors.Formatter. It is therefore safe to
// disregard that State may be a specific printer implementation and use one
// of our choice instead.
// limitations: does not support printing error as Go struct.
var (
sep = " " // separator before next error
p = &state{State: s}
direct = true
)
var err error = f
switch verb {
// Note that this switch must match the preference order
// for ordinary string printing (%#v before %+v, and so on).
case 'v':
if s.Flag('#') {
if stringer, ok := err.(fmt.GoStringer); ok {
io.WriteString(&p.buf, stringer.GoString())
goto exit
}
// proceed as if it were %v
} else if s.Flag('+') {
p.printDetail = true
sep = "\n - "
}
case 's':
case 'q', 'x', 'X':
// Use an intermediate buffer in the rare cases that precision,
// truncation, or one of the alternative verbs (q, x, and X) are
// specified.
direct = false
default:
p.buf.WriteString("%!")
p.buf.WriteRune(verb)
p.buf.WriteByte('(')
switch {
case err != nil:
p.buf.WriteString(reflect.TypeOf(f).String())
default:
p.buf.WriteString("<nil>")
}
p.buf.WriteByte(')')
io.Copy(s, &p.buf)
return
}
loop:
for {
switch v := err.(type) {
case Formatter:
err = v.FormatError((*printer)(p))
case fmt.Formatter:
v.Format(p, 'v')
break loop
default:
io.WriteString(&p.buf, v.Error())
break loop
}
if err == nil {
break
}
if p.needColon || !p.printDetail {
p.buf.WriteByte(':')
p.needColon = false
}
p.buf.WriteString(sep)
p.inDetail = false
p.needNewline = false
}
exit:
width, okW := s.Width()
prec, okP := s.Precision()
if !direct || (okW && width > 0) || okP {
// Construct format string from State s.
format := []byte{'%'}
if s.Flag('-') {
format = append(format, '-')
}
if s.Flag('+') {
format = append(format, '+')
}
if s.Flag(' ') {
format = append(format, ' ')
}
if okW {
format = strconv.AppendInt(format, int64(width), 10)
}
if okP {
format = append(format, '.')
format = strconv.AppendInt(format, int64(prec), 10)
}
format = append(format, string(verb)...)
fmt.Fprintf(s, string(format), p.buf.String())
} else {
io.Copy(s, &p.buf)
}
}
var detailSep = []byte("\n ")
// state tracks error printing state. It implements fmt.State.
type state struct {
fmt.State
buf bytes.Buffer
printDetail bool
inDetail bool
needColon bool
needNewline bool
}
func (s *state) Write(b []byte) (n int, err error) {
if s.printDetail {
if len(b) == 0 {
return 0, nil
}
if s.inDetail && s.needColon {
s.needNewline = true
if b[0] == '\n' {
b = b[1:]
}
}
k := 0
for i, c := range b {
if s.needNewline {
if s.inDetail && s.needColon {
s.buf.WriteByte(':')
s.needColon = false
}
s.buf.Write(detailSep)
s.needNewline = false
}
if c == '\n' {
s.buf.Write(b[k:i])
k = i + 1
s.needNewline = true
}
}
s.buf.Write(b[k:])
if !s.inDetail {
s.needColon = true
}
} else if !s.inDetail {
s.buf.Write(b)
}
return len(b), nil
}
// printer wraps a state to implement an xerrors.Printer.
type printer state
func (s *printer) Print(args ...interface{}) {
if !s.inDetail || s.printDetail {
fmt.Fprint((*state)(s), args...)
}
}
func (s *printer) Printf(format string, args ...interface{}) {
if !s.inDetail || s.printDetail {
fmt.Fprintf((*state)(s), format, args...)
}
}
func (s *printer) Detail() bool {
s.inDetail = true
return s.printDetail
}

1
src/cmd/vendor/golang.org/x/xerrors/codereview.cfg generated vendored Normal file
View File

@ -0,0 +1 @@
issuerepo: golang/go

22
src/cmd/vendor/golang.org/x/xerrors/doc.go generated vendored Normal file
View File

@ -0,0 +1,22 @@
// 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 xerrors implements functions to manipulate errors.
//
// This package is based on the Go 2 proposal for error values:
// https://golang.org/design/29934-error-values
//
// These functions were incorporated into the standard library's errors package
// in Go 1.13:
// - Is
// - As
// - Unwrap
//
// Also, Errorf's %w verb was incorporated into fmt.Errorf.
//
// Use this package to get equivalent behavior in all supported Go versions.
//
// No other features of this package were included in Go 1.13, and at present
// there are no plans to include any of them.
package xerrors // import "golang.org/x/xerrors"

33
src/cmd/vendor/golang.org/x/xerrors/errors.go generated vendored Normal file
View File

@ -0,0 +1,33 @@
// Copyright 2011 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 xerrors
import "fmt"
// errorString is a trivial implementation of error.
type errorString struct {
s string
frame Frame
}
// New returns an error that formats as the given text.
//
// The returned error contains a Frame set to the caller's location and
// implements Formatter to show this information when printed with details.
func New(text string) error {
return &errorString{text, Caller(1)}
}
func (e *errorString) Error() string {
return e.s
}
func (e *errorString) Format(s fmt.State, v rune) { FormatError(e, s, v) }
func (e *errorString) FormatError(p Printer) (next error) {
p.Print(e.s)
e.frame.Format(p)
return nil
}

109
src/cmd/vendor/golang.org/x/xerrors/fmt.go generated vendored Normal file
View File

@ -0,0 +1,109 @@
// Copyright 2018 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 xerrors
import (
"fmt"
"strings"
"golang.org/x/xerrors/internal"
)
// Errorf formats according to a format specifier and returns the string as a
// value that satisfies error.
//
// The returned error includes the file and line number of the caller when
// formatted with additional detail enabled. If the last argument is an error
// the returned error's Format method will return it if the format string ends
// with ": %s", ": %v", or ": %w". If the last argument is an error and the
// format string ends with ": %w", the returned error implements Wrapper
// with an Unwrap method returning it.
func Errorf(format string, a ...interface{}) error {
err, wrap := lastError(format, a)
format = formatPlusW(format)
if err == nil {
return &noWrapError{fmt.Sprintf(format, a...), nil, Caller(1)}
}
// TODO: this is not entirely correct. The error value could be
// printed elsewhere in format if it mixes numbered with unnumbered
// substitutions. With relatively small changes to doPrintf we can
// have it optionally ignore extra arguments and pass the argument
// list in its entirety.
msg := fmt.Sprintf(format[:len(format)-len(": %s")], a[:len(a)-1]...)
frame := Frame{}
if internal.EnableTrace {
frame = Caller(1)
}
if wrap {
return &wrapError{msg, err, frame}
}
return &noWrapError{msg, err, frame}
}
// formatPlusW is used to avoid the vet check that will barf at %w.
func formatPlusW(s string) string {
return s
}
func lastError(format string, a []interface{}) (err error, wrap bool) {
wrap = strings.HasSuffix(format, ": %w")
if !wrap &&
!strings.HasSuffix(format, ": %s") &&
!strings.HasSuffix(format, ": %v") {
return nil, false
}
if len(a) == 0 {
return nil, false
}
err, ok := a[len(a)-1].(error)
if !ok {
return nil, false
}
return err, wrap
}
type noWrapError struct {
msg string
err error
frame Frame
}
func (e *noWrapError) Error() string {
return fmt.Sprint(e)
}
func (e *noWrapError) Format(s fmt.State, v rune) { FormatError(e, s, v) }
func (e *noWrapError) FormatError(p Printer) (next error) {
p.Print(e.msg)
e.frame.Format(p)
return e.err
}
type wrapError struct {
msg string
err error
frame Frame
}
func (e *wrapError) Error() string {
return fmt.Sprint(e)
}
func (e *wrapError) Format(s fmt.State, v rune) { FormatError(e, s, v) }
func (e *wrapError) FormatError(p Printer) (next error) {
p.Print(e.msg)
e.frame.Format(p)
return e.err
}
func (e *wrapError) Unwrap() error {
return e.err
}

34
src/cmd/vendor/golang.org/x/xerrors/format.go generated vendored Normal file
View File

@ -0,0 +1,34 @@
// Copyright 2018 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 xerrors
// A Formatter formats error messages.
type Formatter interface {
error
// FormatError prints the receiver's first error and returns the next error in
// the error chain, if any.
FormatError(p Printer) (next error)
}
// A Printer formats error messages.
//
// The most common implementation of Printer is the one provided by package fmt
// during Printf (as of Go 1.13). Localization packages such as golang.org/x/text/message
// typically provide their own implementations.
type Printer interface {
// Print appends args to the message output.
Print(args ...interface{})
// Printf writes a formatted string.
Printf(format string, args ...interface{})
// Detail reports whether error detail is requested.
// After the first call to Detail, all text written to the Printer
// is formatted as additional detail, or ignored when
// detail has not been requested.
// If Detail returns false, the caller can avoid printing the detail at all.
Detail() bool
}

56
src/cmd/vendor/golang.org/x/xerrors/frame.go generated vendored Normal file
View File

@ -0,0 +1,56 @@
// Copyright 2018 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 xerrors
import (
"runtime"
)
// A Frame contains part of a call stack.
type Frame struct {
// Make room for three PCs: the one we were asked for, what it called,
// and possibly a PC for skipPleaseUseCallersFrames. See:
// https://go.googlesource.com/go/+/032678e0fb/src/runtime/extern.go#169
frames [3]uintptr
}
// Caller returns a Frame that describes a frame on the caller's stack.
// The argument skip is the number of frames to skip over.
// Caller(0) returns the frame for the caller of Caller.
func Caller(skip int) Frame {
var s Frame
runtime.Callers(skip+1, s.frames[:])
return s
}
// location reports the file, line, and function of a frame.
//
// The returned function may be "" even if file and line are not.
func (f Frame) location() (function, file string, line int) {
frames := runtime.CallersFrames(f.frames[:])
if _, ok := frames.Next(); !ok {
return "", "", 0
}
fr, ok := frames.Next()
if !ok {
return "", "", 0
}
return fr.Function, fr.File, fr.Line
}
// Format prints the stack as error detail.
// It should be called from an error's Format implementation
// after printing any other error detail.
func (f Frame) Format(p Printer) {
if p.Detail() {
function, file, line := f.location()
if function != "" {
p.Printf("%s\n ", function)
}
if file != "" {
p.Printf("%s:%d\n", file, line)
}
}
}

Some files were not shown because too many files have changed in this diff Show More