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

View as plain text