github.com/opentofu/opentofu@v1.7.1/internal/plugin/discovery/meta_set_test.go (about) 1 // Copyright (c) The OpenTofu Authors 2 // SPDX-License-Identifier: MPL-2.0 3 // Copyright (c) 2023 HashiCorp, Inc. 4 // SPDX-License-Identifier: MPL-2.0 5 6 package discovery 7 8 import ( 9 "fmt" 10 "strings" 11 "testing" 12 ) 13 14 func TestPluginMetaSetManipulation(t *testing.T) { 15 metas := []PluginMeta{ 16 { 17 Name: "foo", 18 Version: "1.0.0", 19 Path: "test-foo", 20 }, 21 { 22 Name: "bar", 23 Version: "2.0.0", 24 Path: "test-bar", 25 }, 26 { 27 Name: "baz", 28 Version: "2.0.0", 29 Path: "test-bar", 30 }, 31 } 32 s := make(PluginMetaSet) 33 34 if count := s.Count(); count != 0 { 35 t.Fatalf("set has Count %d before any items added", count) 36 } 37 38 // Can we add metas? 39 for _, p := range metas { 40 s.Add(p) 41 if !s.Has(p) { 42 t.Fatalf("%q not in set after adding it", p.Name) 43 } 44 } 45 46 if got, want := s.Count(), len(metas); got != want { 47 t.Fatalf("set has Count %d after all items added; want %d", got, want) 48 } 49 50 // Can we still retrieve earlier ones after we added later ones? 51 for _, p := range metas { 52 if !s.Has(p) { 53 t.Fatalf("%q not in set after all adds", p.Name) 54 } 55 } 56 57 // Can we remove metas? 58 for _, p := range metas { 59 s.Remove(p) 60 if s.Has(p) { 61 t.Fatalf("%q still in set after removing it", p.Name) 62 } 63 } 64 65 if count := s.Count(); count != 0 { 66 t.Fatalf("set has Count %d after all items removed", count) 67 } 68 } 69 70 func TestPluginMetaSetValidateVersions(t *testing.T) { 71 metas := []PluginMeta{ 72 { 73 Name: "foo", 74 Version: "1.0.0", 75 Path: "test-foo", 76 }, 77 { 78 Name: "bar", 79 Version: "0.0.1", 80 Path: "test-bar", 81 }, 82 { 83 Name: "baz", 84 Version: "bananas", 85 Path: "test-bar", 86 }, 87 } 88 s := make(PluginMetaSet) 89 90 for _, p := range metas { 91 s.Add(p) 92 } 93 94 valid, invalid := s.ValidateVersions() 95 if count := valid.Count(); count != 2 { 96 t.Errorf("valid set has %d metas; want 2", count) 97 } 98 if count := invalid.Count(); count != 1 { 99 t.Errorf("valid set has %d metas; want 1", count) 100 } 101 102 if !valid.Has(metas[0]) { 103 t.Errorf("'foo' not in valid set") 104 } 105 if !valid.Has(metas[1]) { 106 t.Errorf("'bar' not in valid set") 107 } 108 if !invalid.Has(metas[2]) { 109 t.Errorf("'baz' not in invalid set") 110 } 111 112 if invalid.Has(metas[0]) { 113 t.Errorf("'foo' in invalid set") 114 } 115 if invalid.Has(metas[1]) { 116 t.Errorf("'bar' in invalid set") 117 } 118 if valid.Has(metas[2]) { 119 t.Errorf("'baz' in valid set") 120 } 121 122 } 123 124 func TestPluginMetaSetWithName(t *testing.T) { 125 tests := []struct { 126 metas []PluginMeta 127 name string 128 wantCount int 129 }{ 130 { 131 []PluginMeta{}, 132 "foo", 133 0, 134 }, 135 { 136 []PluginMeta{ 137 { 138 Name: "foo", 139 Version: "0.0.1", 140 Path: "foo", 141 }, 142 }, 143 "foo", 144 1, 145 }, 146 { 147 []PluginMeta{ 148 { 149 Name: "foo", 150 Version: "0.0.1", 151 Path: "foo", 152 }, 153 }, 154 "bar", 155 0, 156 }, 157 } 158 159 for i, test := range tests { 160 t.Run(fmt.Sprintf("Test%02d", i), func(t *testing.T) { 161 s := make(PluginMetaSet) 162 for _, p := range test.metas { 163 s.Add(p) 164 } 165 filtered := s.WithName(test.name) 166 if gotCount := filtered.Count(); gotCount != test.wantCount { 167 t.Errorf("got count %d in %#v; want %d", gotCount, filtered, test.wantCount) 168 } 169 }) 170 } 171 } 172 173 func TestPluginMetaSetByName(t *testing.T) { 174 metas := []PluginMeta{ 175 { 176 Name: "foo", 177 Version: "1.0.0", 178 Path: "test-foo", 179 }, 180 { 181 Name: "foo", 182 Version: "2.0.0", 183 Path: "test-foo-2", 184 }, 185 { 186 Name: "bar", 187 Version: "0.0.1", 188 Path: "test-bar", 189 }, 190 { 191 Name: "baz", 192 Version: "1.2.0", 193 Path: "test-bar", 194 }, 195 } 196 s := make(PluginMetaSet) 197 198 for _, p := range metas { 199 s.Add(p) 200 } 201 202 byName := s.ByName() 203 if got, want := len(byName), 3; got != want { 204 t.Errorf("%d keys in ByName map; want %d", got, want) 205 } 206 if got, want := len(byName["foo"]), 2; got != want { 207 t.Errorf("%d metas for 'foo'; want %d", got, want) 208 } 209 if got, want := len(byName["bar"]), 1; got != want { 210 t.Errorf("%d metas for 'bar'; want %d", got, want) 211 } 212 if got, want := len(byName["baz"]), 1; got != want { 213 t.Errorf("%d metas for 'baz'; want %d", got, want) 214 } 215 216 if !byName["foo"].Has(metas[0]) { 217 t.Errorf("%#v missing from 'foo' set", metas[0]) 218 } 219 if !byName["foo"].Has(metas[1]) { 220 t.Errorf("%#v missing from 'foo' set", metas[1]) 221 } 222 if !byName["bar"].Has(metas[2]) { 223 t.Errorf("%#v missing from 'bar' set", metas[2]) 224 } 225 if !byName["baz"].Has(metas[3]) { 226 t.Errorf("%#v missing from 'baz' set", metas[3]) 227 } 228 } 229 230 func TestPluginMetaSetNewest(t *testing.T) { 231 tests := []struct { 232 versions []string 233 want string 234 }{ 235 { 236 []string{ 237 "0.0.1", 238 }, 239 "0.0.1", 240 }, 241 { 242 []string{ 243 "0.0.1", 244 "0.0.2", 245 }, 246 "0.0.2", 247 }, 248 { 249 []string{ 250 "1.0.0", 251 "1.0.0-beta1", 252 }, 253 "1.0.0", 254 }, 255 { 256 []string{ 257 "0.0.1", 258 "1.0.0", 259 }, 260 "1.0.0", 261 }, 262 } 263 264 for _, test := range tests { 265 t.Run(strings.Join(test.versions, "|"), func(t *testing.T) { 266 s := make(PluginMetaSet) 267 for _, version := range test.versions { 268 s.Add(PluginMeta{ 269 Name: "foo", 270 Version: VersionStr(version), 271 Path: "foo-V" + version, 272 }) 273 } 274 275 newest := s.Newest() 276 if newest.Version != VersionStr(test.want) { 277 t.Errorf("version is %q; want %q", newest.Version, test.want) 278 } 279 }) 280 } 281 } 282 283 func TestPluginMetaSetConstrainVersions(t *testing.T) { 284 metas := []PluginMeta{ 285 { 286 Name: "foo", 287 Version: "1.0.0", 288 Path: "test-foo", 289 }, 290 { 291 Name: "foo", 292 Version: "2.0.0", 293 Path: "test-foo-2", 294 }, 295 { 296 Name: "foo", 297 Version: "3.0.0", 298 Path: "test-foo-2", 299 }, 300 { 301 Name: "bar", 302 Version: "0.0.5", 303 Path: "test-bar", 304 }, 305 { 306 Name: "baz", 307 Version: "0.0.1", 308 Path: "test-bar", 309 }, 310 } 311 s := make(PluginMetaSet) 312 313 for _, p := range metas { 314 s.Add(p) 315 } 316 317 byName := s.ConstrainVersions(PluginRequirements{ 318 "foo": &PluginConstraints{Versions: ConstraintStr(">=2.0.0").MustParse()}, 319 "bar": &PluginConstraints{Versions: ConstraintStr(">=0.0.0").MustParse()}, 320 "baz": &PluginConstraints{Versions: ConstraintStr(">=1.0.0").MustParse()}, 321 "fun": &PluginConstraints{Versions: ConstraintStr(">5.0.0").MustParse()}, 322 }) 323 if got, want := len(byName), 3; got != want { 324 t.Errorf("%d keys in map; want %d", got, want) 325 } 326 327 if got, want := len(byName["foo"]), 2; got != want { 328 t.Errorf("%d metas for 'foo'; want %d", got, want) 329 } 330 if got, want := len(byName["bar"]), 1; got != want { 331 t.Errorf("%d metas for 'bar'; want %d", got, want) 332 } 333 if got, want := len(byName["baz"]), 0; got != want { 334 t.Errorf("%d metas for 'baz'; want %d", got, want) 335 } 336 // "fun" is not in the map at all, because we have no metas for that name 337 338 if !byName["foo"].Has(metas[1]) { 339 t.Errorf("%#v missing from 'foo' set", metas[1]) 340 } 341 if !byName["foo"].Has(metas[2]) { 342 t.Errorf("%#v missing from 'foo' set", metas[2]) 343 } 344 if !byName["bar"].Has(metas[3]) { 345 t.Errorf("%#v missing from 'bar' set", metas[3]) 346 } 347 348 } 349 350 func TestPluginMetaSetOverridePaths(t *testing.T) { 351 352 metas := []PluginMeta{ 353 { 354 Name: "foo", 355 Version: "1.0.0", 356 Path: "test-foo-1", 357 }, 358 { 359 Name: "foo", 360 Version: "2.0.0", 361 Path: "test-foo-2", 362 }, 363 { 364 Name: "foo", 365 Version: "3.0.0", 366 Path: "test-foo-3", 367 }, 368 { 369 Name: "bar", 370 Version: "0.0.5", 371 Path: "test-bar-5", 372 }, 373 { 374 Name: "bar", 375 Version: "0.0.6", 376 Path: "test-bar-6", 377 }, 378 { 379 Name: "baz", 380 Version: "0.0.1", 381 Path: "test-bar", 382 }, 383 } 384 s := make(PluginMetaSet) 385 386 for _, p := range metas { 387 s.Add(p) 388 } 389 390 ns := s.OverridePaths(map[string]string{ 391 "foo": "override-foo", 392 "fun": "override-fun", 393 }) 394 395 if got, want := ns.Count(), 5; got != want { 396 t.Errorf("got %d metas; want %d", got, want) 397 } 398 399 if !ns.Has(metas[3]) { 400 t.Errorf("new set is missing %#v", metas[3]) 401 } 402 if !ns.Has(metas[4]) { 403 t.Errorf("new set is missing %#v", metas[4]) 404 } 405 if !ns.Has(metas[5]) { 406 t.Errorf("new set is missing %#v", metas[5]) 407 } 408 if !ns.Has(PluginMeta{ 409 Name: "foo", 410 Version: VersionZero, 411 Path: "override-foo", 412 }) { 413 t.Errorf("new set is missing 'foo' override") 414 } 415 if !ns.Has(PluginMeta{ 416 Name: "fun", 417 Version: VersionZero, 418 Path: "override-fun", 419 }) { 420 t.Errorf("new set is missing 'fun' override") 421 } 422 }