github.com/eliastor/durgaform@v0.0.0-20220816172711-d0ab2d17673e/internal/getproviders/registry_source_test.go (about) 1 package getproviders 2 3 import ( 4 "context" 5 "fmt" 6 "regexp" 7 "strings" 8 "testing" 9 10 "github.com/apparentlymart/go-versions/versions" 11 "github.com/google/go-cmp/cmp" 12 svchost "github.com/hashicorp/terraform-svchost" 13 14 "github.com/eliastor/durgaform/internal/addrs" 15 ) 16 17 func TestSourceAvailableVersions(t *testing.T) { 18 source, baseURL, close := testRegistrySource(t) 19 defer close() 20 21 tests := []struct { 22 provider string 23 wantVersions []string 24 wantErr string 25 }{ 26 // These test cases are relying on behaviors of the fake provider 27 // registry server implemented in registry_client_test.go. 28 { 29 "example.com/awesomesauce/happycloud", 30 []string{"0.1.0", "1.0.0", "1.2.0", "2.0.0"}, 31 ``, 32 }, 33 { 34 "example.com/weaksauce/no-versions", 35 nil, 36 ``, // having no versions is not an error, it's just odd 37 }, 38 { 39 "example.com/nonexist/nonexist", 40 nil, 41 `provider registry example.com does not have a provider named example.com/nonexist/nonexist`, 42 }, 43 { 44 "not.example.com/foo/bar", 45 nil, 46 `host not.example.com does not offer a Durgaform provider registry`, 47 }, 48 { 49 "too-new.example.com/foo/bar", 50 nil, 51 `host too-new.example.com does not support the provider registry protocol required by this Durgaform version, but may be compatible with a different Terraform version`, 52 }, 53 { 54 "fails.example.com/foo/bar", 55 nil, 56 `could not query provider registry for fails.example.com/foo/bar: the request failed after 2 attempts, please try again later: Get "` + baseURL + `/fails-immediately/foo/bar/versions": EOF`, 57 }, 58 } 59 60 for _, test := range tests { 61 t.Run(test.provider, func(t *testing.T) { 62 provider := addrs.MustParseProviderSourceString(test.provider) 63 gotVersions, _, err := source.AvailableVersions(context.Background(), provider) 64 65 if err != nil { 66 if test.wantErr == "" { 67 t.Fatalf("wrong error\ngot: %s\nwant: <nil>", err.Error()) 68 } 69 if got, want := err.Error(), test.wantErr; got != want { 70 t.Fatalf("wrong error\ngot: %s\nwant: %s", got, want) 71 } 72 return 73 } 74 75 if test.wantErr != "" { 76 t.Fatalf("wrong error\ngot: <nil>\nwant: %s", test.wantErr) 77 } 78 79 var gotVersionsStr []string 80 if gotVersions != nil { 81 gotVersionsStr = make([]string, len(gotVersions)) 82 for i, v := range gotVersions { 83 gotVersionsStr[i] = v.String() 84 } 85 } 86 87 if diff := cmp.Diff(test.wantVersions, gotVersionsStr); diff != "" { 88 t.Errorf("wrong result\n%s", diff) 89 } 90 }) 91 } 92 } 93 94 func TestSourceAvailableVersions_warnings(t *testing.T) { 95 source, _, close := testRegistrySource(t) 96 defer close() 97 98 provider := addrs.MustParseProviderSourceString("example.com/weaksauce/no-versions") 99 _, warnings, err := source.AvailableVersions(context.Background(), provider) 100 if err != nil { 101 t.Fatalf("unexpected error: %s", err.Error()) 102 } 103 104 if len(warnings) != 1 { 105 t.Fatalf("wrong number of warnings. Expected 1, got %d", len(warnings)) 106 } 107 108 } 109 110 func TestSourcePackageMeta(t *testing.T) { 111 source, baseURL, close := testRegistrySource(t) 112 defer close() 113 114 tests := []struct { 115 provider string 116 version string 117 os, arch string 118 want PackageMeta 119 wantHashes []Hash 120 wantErr string 121 }{ 122 // These test cases are relying on behaviors of the fake provider 123 // registry server implemented in registry_client_test.go. 124 { 125 "example.com/awesomesauce/happycloud", 126 "1.2.0", 127 "linux", "amd64", 128 PackageMeta{ 129 Provider: addrs.NewProvider( 130 svchost.Hostname("example.com"), "awesomesauce", "happycloud", 131 ), 132 Version: versions.MustParseVersion("1.2.0"), 133 ProtocolVersions: VersionList{versions.MustParseVersion("5.0.0")}, 134 TargetPlatform: Platform{"linux", "amd64"}, 135 Filename: "happycloud_1.2.0.zip", 136 Location: PackageHTTPURL(baseURL + "/pkg/awesomesauce/happycloud_1.2.0.zip"), 137 Authentication: PackageAuthenticationAll( 138 NewMatchingChecksumAuthentication( 139 []byte("000000000000000000000000000000000000000000000000000000000000f00d happycloud_1.2.0.zip\n000000000000000000000000000000000000000000000000000000000000face happycloud_1.2.0_face.zip\n"), 140 "happycloud_1.2.0.zip", 141 [32]byte{30: 0xf0, 31: 0x0d}, 142 ), 143 NewArchiveChecksumAuthentication(Platform{"linux", "amd64"}, [32]byte{30: 0xf0, 31: 0x0d}), 144 NewSignatureAuthentication( 145 []byte("000000000000000000000000000000000000000000000000000000000000f00d happycloud_1.2.0.zip\n000000000000000000000000000000000000000000000000000000000000face happycloud_1.2.0_face.zip\n"), 146 []byte("GPG signature"), 147 []SigningKey{ 148 {ASCIIArmor: HashicorpPublicKey}, 149 }, 150 ), 151 ), 152 }, 153 []Hash{ 154 "zh:000000000000000000000000000000000000000000000000000000000000f00d", 155 "zh:000000000000000000000000000000000000000000000000000000000000face", 156 }, 157 ``, 158 }, 159 { 160 "example.com/awesomesauce/happycloud", 161 "1.2.0", 162 "nonexist", "amd64", 163 PackageMeta{}, 164 nil, 165 `provider example.com/awesomesauce/happycloud 1.2.0 is not available for nonexist_amd64`, 166 }, 167 { 168 "not.example.com/awesomesauce/happycloud", 169 "1.2.0", 170 "linux", "amd64", 171 PackageMeta{}, 172 nil, 173 `host not.example.com does not offer a Durgaform provider registry`, 174 }, 175 { 176 "too-new.example.com/awesomesauce/happycloud", 177 "1.2.0", 178 "linux", "amd64", 179 PackageMeta{}, 180 nil, 181 `host too-new.example.com does not support the provider registry protocol required by this Durgaform version, but may be compatible with a different Terraform version`, 182 }, 183 { 184 "fails.example.com/awesomesauce/happycloud", 185 "1.2.0", 186 "linux", "amd64", 187 PackageMeta{}, 188 nil, 189 `could not query provider registry for fails.example.com/awesomesauce/happycloud: the request failed after 2 attempts, please try again later: Get "http://placeholder-origin/fails-immediately/awesomesauce/happycloud/1.2.0/download/linux/amd64": EOF`, 190 }, 191 } 192 193 // Sometimes error messages contain specific HTTP endpoint URLs, but 194 // since our test server is on a random port we'd not be able to 195 // consistently match those. Instead, we'll normalize the URLs. 196 urlPattern := regexp.MustCompile(`http://[^/]+/`) 197 198 cmpOpts := cmp.Comparer(Version.Same) 199 200 for _, test := range tests { 201 t.Run(fmt.Sprintf("%s for %s_%s", test.provider, test.os, test.arch), func(t *testing.T) { 202 // TEMP: We don't yet have a function for parsing provider 203 // source addresses so we'll just fake it in here for now. 204 parts := strings.Split(test.provider, "/") 205 providerAddr := addrs.Provider{ 206 Hostname: svchost.Hostname(parts[0]), 207 Namespace: parts[1], 208 Type: parts[2], 209 } 210 211 version := versions.MustParseVersion(test.version) 212 213 got, err := source.PackageMeta(context.Background(), providerAddr, version, Platform{test.os, test.arch}) 214 215 if err != nil { 216 if test.wantErr == "" { 217 t.Fatalf("wrong error\ngot: %s\nwant: <nil>", err.Error()) 218 } 219 gotErr := urlPattern.ReplaceAllLiteralString(err.Error(), "http://placeholder-origin/") 220 if got, want := gotErr, test.wantErr; got != want { 221 t.Fatalf("wrong error\ngot: %s\nwant: %s", got, want) 222 } 223 return 224 } 225 226 if test.wantErr != "" { 227 t.Fatalf("wrong error\ngot: <nil>\nwant: %s", test.wantErr) 228 } 229 230 if diff := cmp.Diff(test.want, got, cmpOpts); diff != "" { 231 t.Errorf("wrong result\n%s", diff) 232 } 233 if diff := cmp.Diff(test.wantHashes, got.AcceptableHashes()); diff != "" { 234 t.Errorf("wrong AcceptableHashes result\n%s", diff) 235 } 236 }) 237 } 238 239 }