github.com/go-asm/go@v1.21.1-0.20240213172139-40c5ead50c48/cmd/go/modload/query_test.go (about)

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