golang.org/x/tools@v0.21.0/internal/versions/versions_test.go (about)

     1  // Copyright 2023 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 versions_test
     6  
     7  import (
     8  	"go/ast"
     9  	"go/parser"
    10  	"go/token"
    11  	"go/types"
    12  	"testing"
    13  
    14  	"golang.org/x/tools/internal/testenv"
    15  	"golang.org/x/tools/internal/versions"
    16  )
    17  
    18  func TestIsValid(t *testing.T) {
    19  	// valid versions
    20  	for _, x := range []string{
    21  		"go1.21",
    22  		"go1.21.2",
    23  		"go1.21rc",
    24  		"go1.21rc2",
    25  		"go0.0", // ??
    26  		"go1",
    27  		"go2",
    28  		"go1.20.0-bigcorp",
    29  	} {
    30  		if !versions.IsValid(x) {
    31  			t.Errorf("expected versions.IsValid(%q) to hold", x)
    32  		}
    33  	}
    34  
    35  	// invalid versions
    36  	for _, x := range []string{
    37  		"",
    38  		"bad",
    39  		"1.21",
    40  		"v1.21",
    41  		"go",
    42  		"goAA",
    43  		"go2_3",
    44  		"go1.BB",
    45  		"go1.21.",
    46  		"go1.21.2_2",
    47  		"go1.21rc_2",
    48  		"go1.21rc2_",
    49  		"go1.600+auto",
    50  	} {
    51  		if versions.IsValid(x) {
    52  			t.Errorf("expected versions.IsValid(%q) to not hold", x)
    53  		}
    54  	}
    55  }
    56  
    57  func TestVersionComparisons(t *testing.T) {
    58  	for _, item := range []struct {
    59  		x, y string
    60  		want int
    61  	}{
    62  		// All comparisons of go2, go1.21.2, go1.21rc2, go1.21rc2, go1, go0.0, "", bad
    63  		{"go2", "go2", 0},
    64  		{"go2", "go1.21.2", +1},
    65  		{"go2", "go1.21rc2", +1},
    66  		{"go2", "go1.21rc", +1},
    67  		{"go2", "go1.21", +1},
    68  		{"go2", "go1", +1},
    69  		{"go2", "go0.0", +1},
    70  		{"go2", "", +1},
    71  		{"go2", "bad", +1},
    72  		{"go1.21.2", "go1.21.2", 0},
    73  		{"go1.21.2", "go1.21rc2", +1},
    74  		{"go1.21.2", "go1.21rc", +1},
    75  		{"go1.21.2", "go1.21", +1},
    76  		{"go1.21.2", "go1", +1},
    77  		{"go1.21.2", "go0.0", +1},
    78  		{"go1.21.2", "", +1},
    79  		{"go1.21.2", "bad", +1},
    80  		{"go1.21rc2", "go1.21rc2", 0},
    81  		{"go1.21rc2", "go1.21rc", +1},
    82  		{"go1.21rc2", "go1.21", +1},
    83  		{"go1.21rc2", "go1", +1},
    84  		{"go1.21rc2", "go0.0", +1},
    85  		{"go1.21rc2", "", +1},
    86  		{"go1.21rc2", "bad", +1},
    87  		{"go1.21rc", "go1.21rc", 0},
    88  		{"go1.21rc", "go1.21", +1},
    89  		{"go1.21rc", "go1", +1},
    90  		{"go1.21rc", "go0.0", +1},
    91  		{"go1.21rc", "", +1},
    92  		{"go1.21rc", "bad", +1},
    93  		{"go1.21", "go1.21", 0},
    94  		{"go1.21", "go1", +1},
    95  		{"go1.21", "go0.0", +1},
    96  		{"go1.21", "", +1},
    97  		{"go1.21", "bad", +1},
    98  		{"go1", "go1", 0},
    99  		{"go1", "go0.0", +1},
   100  		{"go1", "", +1},
   101  		{"go1", "bad", +1},
   102  		{"go0.0", "go0.0", 0},
   103  		{"go0.0", "", +1},
   104  		{"go0.0", "bad", +1},
   105  		{"", "", 0},
   106  		{"", "bad", 0},
   107  		{"bad", "bad", 0},
   108  		// Other tests.
   109  		{"go1.20", "go1.20.0-bigcorp", 0},
   110  		{"go1.21", "go1.21.0-bigcorp", -1},  // Starting in Go 1.21, patch missing is different from explicit .0.
   111  		{"go1.21.0", "go1.21.0-bigcorp", 0}, // Starting in Go 1.21, patch missing is different from explicit .0.
   112  		{"go1.19rc1", "go1.19", -1},
   113  	} {
   114  		got := versions.Compare(item.x, item.y)
   115  		if got != item.want {
   116  			t.Errorf("versions.Compare(%q, %q)=%d. expected %d", item.x, item.y, got, item.want)
   117  		}
   118  		reverse := versions.Compare(item.y, item.x)
   119  		if reverse != -got {
   120  			t.Errorf("versions.Compare(%q, %q)=%d. expected %d", item.y, item.x, reverse, -got)
   121  		}
   122  	}
   123  }
   124  
   125  func TestLang(t *testing.T) {
   126  	for _, item := range []struct {
   127  		x    string
   128  		want string
   129  	}{
   130  		// valid
   131  		{"go1.21rc2", "go1.21"},
   132  		{"go1.21.2", "go1.21"},
   133  		{"go1.21", "go1.21"},
   134  		{"go1", "go1"},
   135  		// invalid
   136  		{"bad", ""},
   137  		{"1.21", ""},
   138  	} {
   139  		if got := versions.Lang(item.x); got != item.want {
   140  			t.Errorf("versions.Lang(%q)=%q. expected %q", item.x, got, item.want)
   141  		}
   142  	}
   143  
   144  }
   145  
   146  func TestKnown(t *testing.T) {
   147  	for _, v := range [...]string{
   148  		versions.Go1_18,
   149  		versions.Go1_19,
   150  		versions.Go1_20,
   151  		versions.Go1_21,
   152  		versions.Go1_22,
   153  	} {
   154  		if !versions.IsValid(v) {
   155  			t.Errorf("Expected known version %q to be valid.", v)
   156  		}
   157  		if v != versions.Lang(v) {
   158  			t.Errorf("Expected known version %q == Lang(%q).", v, versions.Lang(v))
   159  		}
   160  	}
   161  }
   162  
   163  func TestAtLeast(t *testing.T) {
   164  	for _, item := range [...]struct {
   165  		v, release string
   166  		want       bool
   167  	}{
   168  		{versions.Future, versions.Go1_22, true},
   169  		{versions.Go1_22, versions.Go1_22, true},
   170  		{"go1.21", versions.Go1_22, false},
   171  		{"invalid", versions.Go1_22, false},
   172  	} {
   173  		if got := versions.AtLeast(item.v, item.release); got != item.want {
   174  			t.Errorf("AtLeast(%q, %q)=%v. wanted %v", item.v, item.release, got, item.want)
   175  		}
   176  	}
   177  }
   178  
   179  func TestBefore(t *testing.T) {
   180  	for _, item := range [...]struct {
   181  		v, release string
   182  		want       bool
   183  	}{
   184  		{versions.Future, versions.Go1_22, false},
   185  		{versions.Go1_22, versions.Go1_22, false},
   186  		{"go1.21", versions.Go1_22, true},
   187  		{"invalid", versions.Go1_22, true}, // invalid < Go1_22
   188  	} {
   189  		if got := versions.Before(item.v, item.release); got != item.want {
   190  			t.Errorf("Before(%q, %q)=%v. wanted %v", item.v, item.release, got, item.want)
   191  		}
   192  	}
   193  }
   194  
   195  func TestFileVersions122(t *testing.T) {
   196  	testenv.NeedsGo1Point(t, 22)
   197  
   198  	const source = `
   199  	package P
   200  	`
   201  	fset := token.NewFileSet()
   202  	f, err := parser.ParseFile(fset, "hello.go", source, 0)
   203  	if err != nil {
   204  		t.Fatal(err)
   205  	}
   206  
   207  	for _, conf := range []types.Config{
   208  		{GoVersion: versions.Go1_22},
   209  		{}, // GoVersion is unset.
   210  	} {
   211  		info := &types.Info{}
   212  		versions.InitFileVersions(info)
   213  
   214  		_, err = conf.Check("P", fset, []*ast.File{f}, info)
   215  		if err != nil {
   216  			t.Fatal(err)
   217  		}
   218  
   219  		v := versions.FileVersion(info, f)
   220  		if !versions.AtLeast(v, versions.Go1_22) {
   221  			t.Errorf("versions.AtLeast(%q, %q) expected to hold", v, versions.Go1_22)
   222  		}
   223  
   224  		if versions.Before(v, versions.Go1_22) {
   225  			t.Errorf("versions.AtLeast(%q, %q) expected to be false", v, versions.Go1_22)
   226  		}
   227  
   228  		if conf.GoVersion == "" && v != versions.Future {
   229  			t.Error("Expected the FileVersion to be the Future when conf.GoVersion is unset")
   230  		}
   231  	}
   232  }
   233  
   234  func TestFileVersions121(t *testing.T) {
   235  	testenv.SkipAfterGo1Point(t, 21)
   236  
   237  	// If <1.22, info and file are ignored.
   238  	v := versions.FileVersion(nil, nil)
   239  	oneof := map[string]bool{
   240  		versions.Go1_18: true,
   241  		versions.Go1_19: true,
   242  		versions.Go1_20: true,
   243  		versions.Go1_21: true,
   244  	}
   245  	if !oneof[v] {
   246  		t.Errorf("FileVersion(...)=%q expected to be a known go version <1.22", v)
   247  	}
   248  
   249  	if versions.AtLeast(v, versions.Go1_22) {
   250  		t.Errorf("versions.AtLeast(%q, %q) expected to be false", v, versions.Go1_22)
   251  	}
   252  
   253  	if !versions.Before(v, versions.Go1_22) {
   254  		t.Errorf("versions.Before(%q, %q) expected to hold", v, versions.Go1_22)
   255  	}
   256  }