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  }