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 }