Source file src/cmd/go/internal/modload/query_test.go

     1  // Copyright 2018 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package modload
     6  
     7  import (
     8  	"context"
     9  	"internal/testenv"
    10  	"log"
    11  	"os"
    12  	"path"
    13  	"path/filepath"
    14  	"strings"
    15  	"testing"
    16  
    17  	"cmd/go/internal/cfg"
    18  
    19  	"golang.org/x/mod/module"
    20  )
    21  
    22  func TestMain(m *testing.M) {
    23  	os.Exit(testMain(m))
    24  }
    25  
    26  func testMain(m *testing.M) int {
    27  	cfg.GOPROXY = "direct"
    28  
    29  	dir, err := os.MkdirTemp("", "modload-test-")
    30  	if err != nil {
    31  		log.Fatal(err)
    32  	}
    33  	defer os.RemoveAll(dir)
    34  
    35  	os.Setenv("GOPATH", dir)
    36  	cfg.BuildContext.GOPATH = dir
    37  	cfg.GOMODCACHE = filepath.Join(dir, "pkg/mod")
    38  	return m.Run()
    39  }
    40  
    41  var (
    42  	queryRepo   = "vcs-test.golang.org/git/querytest.git"
    43  	queryRepoV2 = queryRepo + "/v2"
    44  	queryRepoV3 = queryRepo + "/v3"
    45  
    46  	// Empty version list (no semver tags), not actually empty.
    47  	emptyRepoPath = "vcs-test.golang.org/git/emptytest.git"
    48  )
    49  
    50  var queryTests = []struct {
    51  	path    string
    52  	query   string
    53  	current string
    54  	allow   string
    55  	vers    string
    56  	err     string
    57  }{
    58  	/*
    59  		git init
    60  		echo module vcs-test.golang.org/git/querytest.git >go.mod
    61  		git add go.mod
    62  		git commit -m v1 go.mod
    63  		git tag start
    64  		for i in v0.0.0-pre1 v0.0.0 v0.0.1 v0.0.2 v0.0.3 v0.1.0 v0.1.1 v0.1.2 v0.3.0 v1.0.0 v1.1.0 v1.9.0 v1.9.9 v1.9.10-pre1 v1.9.10-pre2+metadata unversioned; do
    65  			echo before $i >status
    66  			git add status
    67  			git commit -m "before $i" status
    68  			echo at $i >status
    69  			git commit -m "at $i" status
    70  			git tag $i
    71  		done
    72  		git tag favorite v0.0.3
    73  
    74  		git branch v2 start
    75  		git checkout v2
    76  		echo module vcs-test.golang.org/git/querytest.git/v2 >go.mod
    77  		git commit -m v2 go.mod
    78  		for i in v2.0.0 v2.1.0 v2.2.0 v2.5.5 v2.6.0-pre1; do
    79  			echo before $i >status
    80  			git add status
    81  			git commit -m "before $i" status
    82  			echo at $i >status
    83  			git commit -m "at $i" status
    84  			git tag $i
    85  		done
    86  		git checkout v2.5.5
    87  		echo after v2.5.5 >status
    88  		git commit -m 'after v2.5.5' status
    89  		git checkout master
    90  		zip -r ../querytest.zip
    91  		gsutil cp ../querytest.zip gs://vcs-test/git/querytest.zip
    92  		curl 'https://vcs-test.golang.org/git/querytest?go-get=1'
    93  	*/
    94  	{path: queryRepo, query: "<v0.0.0", vers: "v0.0.0-pre1"},
    95  	{path: queryRepo, query: "<v0.0.0-pre1", err: `no matching versions for query "<v0.0.0-pre1"`},
    96  	{path: queryRepo, query: "<=v0.0.0", vers: "v0.0.0"},
    97  	{path: queryRepo, query: ">v0.0.0", vers: "v0.0.1"},
    98  	{path: queryRepo, query: ">=v0.0.0", vers: "v0.0.0"},
    99  	{path: queryRepo, query: "v0.0.1", vers: "v0.0.1"},
   100  	{path: queryRepo, query: "v0.0.1+foo", vers: "v0.0.1"},
   101  	{path: queryRepo, query: "v0.0.99", err: `vcs-test.golang.org/git/querytest.git@v0.0.99: invalid version: unknown revision v0.0.99`},
   102  	{path: queryRepo, query: "v0", vers: "v0.3.0"},
   103  	{path: queryRepo, query: "v0.1", vers: "v0.1.2"},
   104  	{path: queryRepo, query: "v0.2", err: `no matching versions for query "v0.2"`},
   105  	{path: queryRepo, query: "v0.0", vers: "v0.0.3"},
   106  	{path: queryRepo, query: "v1.9.10-pre2+metadata", vers: "v1.9.10-pre2.0.20190513201126-42abcb6df8ee"},
   107  	{path: queryRepo, query: "ed5ffdaa", vers: "v1.9.10-pre2.0.20191220134614-ed5ffdaa1f5e"},
   108  
   109  	// golang.org/issue/29262: The major version for a module without a suffix
   110  	// should be based on the most recent tag (v1 as appropriate, not v0
   111  	// unconditionally).
   112  	{path: queryRepo, query: "42abcb6df8ee", vers: "v1.9.10-pre2.0.20190513201126-42abcb6df8ee"},
   113  
   114  	{path: queryRepo, query: "v1.9.10-pre2+wrongmetadata", err: `vcs-test.golang.org/git/querytest.git@v1.9.10-pre2+wrongmetadata: invalid version: unknown revision v1.9.10-pre2+wrongmetadata`},
   115  	{path: queryRepo, query: "v1.9.10-pre2", err: `vcs-test.golang.org/git/querytest.git@v1.9.10-pre2: invalid version: unknown revision v1.9.10-pre2`},
   116  	{path: queryRepo, query: "latest", vers: "v1.9.9"},
   117  	{path: queryRepo, query: "latest", current: "v1.9.10-pre1", vers: "v1.9.9"},
   118  	{path: queryRepo, query: "upgrade", vers: "v1.9.9"},
   119  	{path: queryRepo, query: "upgrade", current: "v1.9.10-pre1", vers: "v1.9.10-pre1"},
   120  	{path: queryRepo, query: "upgrade", current: "v1.9.10-pre2+metadata", vers: "v1.9.10-pre2.0.20190513201126-42abcb6df8ee"},
   121  	{path: queryRepo, query: "upgrade", current: "v0.0.0-20190513201126-42abcb6df8ee", vers: "v0.0.0-20190513201126-42abcb6df8ee"},
   122  	{path: queryRepo, query: "upgrade", allow: "NOMATCH", err: `no matching versions for query "upgrade"`},
   123  	{path: queryRepo, query: "upgrade", current: "v1.9.9", allow: "NOMATCH", err: `vcs-test.golang.org/git/querytest.git@v1.9.9: disallowed module version`},
   124  	{path: queryRepo, query: "upgrade", current: "v1.99.99", err: `vcs-test.golang.org/git/querytest.git@v1.99.99: invalid version: unknown revision v1.99.99`},
   125  	{path: queryRepo, query: "patch", current: "", err: `can't query version "patch" of module vcs-test.golang.org/git/querytest.git: no existing version is required`},
   126  	{path: queryRepo, query: "patch", current: "v0.1.0", vers: "v0.1.2"},
   127  	{path: queryRepo, query: "patch", current: "v1.9.0", vers: "v1.9.9"},
   128  	{path: queryRepo, query: "patch", current: "v1.9.10-pre1", vers: "v1.9.10-pre1"},
   129  	{path: queryRepo, query: "patch", current: "v1.9.10-pre2+metadata", vers: "v1.9.10-pre2.0.20190513201126-42abcb6df8ee"},
   130  	{path: queryRepo, query: "patch", current: "v1.99.99", err: `vcs-test.golang.org/git/querytest.git@v1.99.99: invalid version: unknown revision v1.99.99`},
   131  	{path: queryRepo, query: ">v1.9.9", vers: "v1.9.10-pre1"},
   132  	{path: queryRepo, query: ">v1.10.0", err: `no matching versions for query ">v1.10.0"`},
   133  	{path: queryRepo, query: ">=v1.10.0", err: `no matching versions for query ">=v1.10.0"`},
   134  	{path: queryRepo, query: "6cf84eb", vers: "v0.0.2-0.20180704023347-6cf84ebaea54"},
   135  
   136  	// golang.org/issue/27173: A pseudo-version may be based on the highest tag on
   137  	// any parent commit, or any existing semantically-lower tag: a given commit
   138  	// could have been a pre-release for a backport tag at any point.
   139  	{path: queryRepo, query: "3ef0cec634e0", vers: "v0.1.2-0.20180704023347-3ef0cec634e0"},
   140  	{path: queryRepo, query: "v0.1.2-0.20180704023347-3ef0cec634e0", vers: "v0.1.2-0.20180704023347-3ef0cec634e0"},
   141  	{path: queryRepo, query: "v0.1.1-0.20180704023347-3ef0cec634e0", vers: "v0.1.1-0.20180704023347-3ef0cec634e0"},
   142  	{path: queryRepo, query: "v0.0.4-0.20180704023347-3ef0cec634e0", vers: "v0.0.4-0.20180704023347-3ef0cec634e0"},
   143  
   144  	// Invalid tags are tested in cmd/go/testdata/script/mod_pseudo_invalid.txt.
   145  
   146  	{path: queryRepo, query: "start", vers: "v0.0.0-20180704023101-5e9e31667ddf"},
   147  	{path: queryRepo, query: "5e9e31667ddf", vers: "v0.0.0-20180704023101-5e9e31667ddf"},
   148  	{path: queryRepo, query: "v0.0.0-20180704023101-5e9e31667ddf", vers: "v0.0.0-20180704023101-5e9e31667ddf"},
   149  
   150  	{path: queryRepo, query: "7a1b6bf", vers: "v0.1.0"},
   151  
   152  	{path: queryRepoV2, query: "<v0.0.0", err: `no matching versions for query "<v0.0.0"`},
   153  	{path: queryRepoV2, query: "<=v0.0.0", err: `no matching versions for query "<=v0.0.0"`},
   154  	{path: queryRepoV2, query: ">v0.0.0", vers: "v2.0.0"},
   155  	{path: queryRepoV2, query: ">=v0.0.0", vers: "v2.0.0"},
   156  
   157  	{path: queryRepoV2, query: "v2", vers: "v2.5.5"},
   158  	{path: queryRepoV2, query: "v2.5", vers: "v2.5.5"},
   159  	{path: queryRepoV2, query: "v2.6", err: `no matching versions for query "v2.6"`},
   160  	{path: queryRepoV2, query: "v2.6.0-pre1", vers: "v2.6.0-pre1"},
   161  	{path: queryRepoV2, query: "latest", vers: "v2.5.5"},
   162  
   163  	// Commit e0cf3de987e6 is actually v1.19.10-pre1, not anything resembling v3,
   164  	// and it has a go.mod file with a non-v3 module path. Attempting to query it
   165  	// as the v3 module should fail.
   166  	{path: queryRepoV3, query: "e0cf3de987e6", err: `vcs-test.golang.org/git/querytest.git/v3@v3.0.0-20180704024501-e0cf3de987e6: invalid version: go.mod has non-.../v3 module path "vcs-test.golang.org/git/querytest.git" (and .../v3/go.mod does not exist) at revision e0cf3de987e6`},
   167  
   168  	// The querytest repo does not have any commits tagged with major version 3,
   169  	// and the latest commit in the repo has a go.mod file specifying a non-v3 path.
   170  	// That should prevent us from resolving any version for the /v3 path.
   171  	{path: queryRepoV3, query: "latest", err: `no matching versions for query "latest"`},
   172  
   173  	{path: emptyRepoPath, query: "latest", vers: "v0.0.0-20180704023549-7bb914627242"},
   174  	{path: emptyRepoPath, query: ">v0.0.0", err: `no matching versions for query ">v0.0.0"`},
   175  	{path: emptyRepoPath, query: "<v10.0.0", err: `no matching versions for query "<v10.0.0"`},
   176  }
   177  
   178  func TestQuery(t *testing.T) {
   179  	testenv.MustHaveExternalNetwork(t)
   180  	testenv.MustHaveExecPath(t, "git")
   181  
   182  	ctx := context.Background()
   183  
   184  	for _, tt := range queryTests {
   185  		allow := tt.allow
   186  		if allow == "" {
   187  			allow = "*"
   188  		}
   189  		allowed := func(ctx context.Context, m module.Version) error {
   190  			if ok, _ := path.Match(allow, m.Version); !ok {
   191  				return module.VersionError(m, ErrDisallowed)
   192  			}
   193  			return nil
   194  		}
   195  		tt := tt
   196  		t.Run(strings.ReplaceAll(tt.path, "/", "_")+"/"+tt.query+"/"+tt.current+"/"+allow, func(t *testing.T) {
   197  			t.Parallel()
   198  
   199  			info, err := Query(ctx, tt.path, tt.query, tt.current, allowed)
   200  			if tt.err != "" {
   201  				if err == nil {
   202  					t.Errorf("Query(_, %q, %q, %q, %v) = %v, want error %q", tt.path, tt.query, tt.current, allow, info.Version, tt.err)
   203  				} else if err.Error() != tt.err {
   204  					t.Errorf("Query(_, %q, %q, %q, %v): %v\nwant error %q", tt.path, tt.query, tt.current, allow, err, tt.err)
   205  				}
   206  				return
   207  			}
   208  			if err != nil {
   209  				t.Fatalf("Query(_, %q, %q, %q, %v): %v\nwant %v", tt.path, tt.query, tt.current, allow, err, tt.vers)
   210  			}
   211  			if info.Version != tt.vers {
   212  				t.Errorf("Query(_, %q, %q, %q, %v) = %v, want %v", tt.path, tt.query, tt.current, allow, info.Version, tt.vers)
   213  			}
   214  		})
   215  	}
   216  }
   217  

View as plain text