github.com/terramate-io/tf@v0.0.0-20230830114523-fce866b4dfcd/addrs/provider_test.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package addrs
     5  
     6  import (
     7  	"testing"
     8  
     9  	"github.com/go-test/deep"
    10  	svchost "github.com/hashicorp/terraform-svchost"
    11  )
    12  
    13  func TestProviderString(t *testing.T) {
    14  	tests := []struct {
    15  		Input Provider
    16  		Want  string
    17  	}{
    18  		{
    19  			Provider{
    20  				Type:      "test",
    21  				Hostname:  DefaultProviderRegistryHost,
    22  				Namespace: "hashicorp",
    23  			},
    24  			NewDefaultProvider("test").String(),
    25  		},
    26  		{
    27  			Provider{
    28  				Type:      "test-beta",
    29  				Hostname:  DefaultProviderRegistryHost,
    30  				Namespace: "hashicorp",
    31  			},
    32  			NewDefaultProvider("test-beta").String(),
    33  		},
    34  		{
    35  			Provider{
    36  				Type:      "test",
    37  				Hostname:  "registry.terraform.com",
    38  				Namespace: "hashicorp",
    39  			},
    40  			"registry.terraform.com/hashicorp/test",
    41  		},
    42  		{
    43  			Provider{
    44  				Type:      "test",
    45  				Hostname:  DefaultProviderRegistryHost,
    46  				Namespace: "othercorp",
    47  			},
    48  			DefaultProviderRegistryHost.ForDisplay() + "/othercorp/test",
    49  		},
    50  	}
    51  
    52  	for _, test := range tests {
    53  		got := test.Input.String()
    54  		if got != test.Want {
    55  			t.Errorf("wrong result for %s\n", test.Input.String())
    56  		}
    57  	}
    58  }
    59  
    60  func TestProviderLegacyString(t *testing.T) {
    61  	tests := []struct {
    62  		Input Provider
    63  		Want  string
    64  	}{
    65  		{
    66  			Provider{
    67  				Type:      "test",
    68  				Hostname:  DefaultProviderRegistryHost,
    69  				Namespace: LegacyProviderNamespace,
    70  			},
    71  			"test",
    72  		},
    73  		{
    74  			Provider{
    75  				Type:      "terraform",
    76  				Hostname:  BuiltInProviderHost,
    77  				Namespace: BuiltInProviderNamespace,
    78  			},
    79  			"terraform",
    80  		},
    81  	}
    82  
    83  	for _, test := range tests {
    84  		got := test.Input.LegacyString()
    85  		if got != test.Want {
    86  			t.Errorf("wrong result for %s\ngot:  %s\nwant: %s", test.Input.String(), got, test.Want)
    87  		}
    88  	}
    89  }
    90  
    91  func TestProviderDisplay(t *testing.T) {
    92  	tests := []struct {
    93  		Input Provider
    94  		Want  string
    95  	}{
    96  		{
    97  			Provider{
    98  				Type:      "test",
    99  				Hostname:  DefaultProviderRegistryHost,
   100  				Namespace: "hashicorp",
   101  			},
   102  			"hashicorp/test",
   103  		},
   104  		{
   105  			Provider{
   106  				Type:      "test",
   107  				Hostname:  "registry.terraform.com",
   108  				Namespace: "hashicorp",
   109  			},
   110  			"registry.terraform.com/hashicorp/test",
   111  		},
   112  		{
   113  			Provider{
   114  				Type:      "test",
   115  				Hostname:  DefaultProviderRegistryHost,
   116  				Namespace: "othercorp",
   117  			},
   118  			"othercorp/test",
   119  		},
   120  	}
   121  
   122  	for _, test := range tests {
   123  		got := test.Input.ForDisplay()
   124  		if got != test.Want {
   125  			t.Errorf("wrong result for %s\n", test.Input.String())
   126  		}
   127  	}
   128  }
   129  
   130  func TestProviderIsDefaultProvider(t *testing.T) {
   131  	tests := []struct {
   132  		Input Provider
   133  		Want  bool
   134  	}{
   135  		{
   136  			Provider{
   137  				Type:      "test",
   138  				Hostname:  DefaultProviderRegistryHost,
   139  				Namespace: "hashicorp",
   140  			},
   141  			true,
   142  		},
   143  		{
   144  			Provider{
   145  				Type:      "test",
   146  				Hostname:  "registry.terraform.com",
   147  				Namespace: "hashicorp",
   148  			},
   149  			false,
   150  		},
   151  		{
   152  			Provider{
   153  				Type:      "test",
   154  				Hostname:  DefaultProviderRegistryHost,
   155  				Namespace: "othercorp",
   156  			},
   157  			false,
   158  		},
   159  	}
   160  
   161  	for _, test := range tests {
   162  		got := IsDefaultProvider(test.Input)
   163  		if got != test.Want {
   164  			t.Errorf("wrong result for %s\n", test.Input.String())
   165  		}
   166  	}
   167  }
   168  
   169  func TestProviderIsBuiltIn(t *testing.T) {
   170  	tests := []struct {
   171  		Input Provider
   172  		Want  bool
   173  	}{
   174  		{
   175  			Provider{
   176  				Type:      "test",
   177  				Hostname:  BuiltInProviderHost,
   178  				Namespace: BuiltInProviderNamespace,
   179  			},
   180  			true,
   181  		},
   182  		{
   183  			Provider{
   184  				Type:      "terraform",
   185  				Hostname:  BuiltInProviderHost,
   186  				Namespace: BuiltInProviderNamespace,
   187  			},
   188  			true,
   189  		},
   190  		{
   191  			Provider{
   192  				Type:      "test",
   193  				Hostname:  BuiltInProviderHost,
   194  				Namespace: "boop",
   195  			},
   196  			false,
   197  		},
   198  		{
   199  			Provider{
   200  				Type:      "test",
   201  				Hostname:  DefaultProviderRegistryHost,
   202  				Namespace: BuiltInProviderNamespace,
   203  			},
   204  			false,
   205  		},
   206  		{
   207  			Provider{
   208  				Type:      "test",
   209  				Hostname:  DefaultProviderRegistryHost,
   210  				Namespace: "hashicorp",
   211  			},
   212  			false,
   213  		},
   214  		{
   215  			Provider{
   216  				Type:      "test",
   217  				Hostname:  "registry.terraform.com",
   218  				Namespace: "hashicorp",
   219  			},
   220  			false,
   221  		},
   222  		{
   223  			Provider{
   224  				Type:      "test",
   225  				Hostname:  DefaultProviderRegistryHost,
   226  				Namespace: "othercorp",
   227  			},
   228  			false,
   229  		},
   230  	}
   231  
   232  	for _, test := range tests {
   233  		got := test.Input.IsBuiltIn()
   234  		if got != test.Want {
   235  			t.Errorf("wrong result for %s\ngot:  %#v\nwant: %#v", test.Input.String(), got, test.Want)
   236  		}
   237  	}
   238  }
   239  
   240  func TestProviderIsLegacy(t *testing.T) {
   241  	tests := []struct {
   242  		Input Provider
   243  		Want  bool
   244  	}{
   245  		{
   246  			Provider{
   247  				Type:      "test",
   248  				Hostname:  DefaultProviderRegistryHost,
   249  				Namespace: LegacyProviderNamespace,
   250  			},
   251  			true,
   252  		},
   253  		{
   254  			Provider{
   255  				Type:      "test",
   256  				Hostname:  "registry.terraform.com",
   257  				Namespace: LegacyProviderNamespace,
   258  			},
   259  			false,
   260  		},
   261  		{
   262  			Provider{
   263  				Type:      "test",
   264  				Hostname:  DefaultProviderRegistryHost,
   265  				Namespace: "hashicorp",
   266  			},
   267  			false,
   268  		},
   269  	}
   270  
   271  	for _, test := range tests {
   272  		got := test.Input.IsLegacy()
   273  		if got != test.Want {
   274  			t.Errorf("wrong result for %s\n", test.Input.String())
   275  		}
   276  	}
   277  }
   278  
   279  func TestParseProviderSourceStr(t *testing.T) {
   280  	tests := map[string]struct {
   281  		Want Provider
   282  		Err  bool
   283  	}{
   284  		"registry.terraform.io/hashicorp/aws": {
   285  			Provider{
   286  				Type:      "aws",
   287  				Namespace: "hashicorp",
   288  				Hostname:  DefaultProviderRegistryHost,
   289  			},
   290  			false,
   291  		},
   292  		"registry.Terraform.io/HashiCorp/AWS": {
   293  			Provider{
   294  				Type:      "aws",
   295  				Namespace: "hashicorp",
   296  				Hostname:  DefaultProviderRegistryHost,
   297  			},
   298  			false,
   299  		},
   300  		"hashicorp/aws": {
   301  			Provider{
   302  				Type:      "aws",
   303  				Namespace: "hashicorp",
   304  				Hostname:  DefaultProviderRegistryHost,
   305  			},
   306  			false,
   307  		},
   308  		"HashiCorp/AWS": {
   309  			Provider{
   310  				Type:      "aws",
   311  				Namespace: "hashicorp",
   312  				Hostname:  DefaultProviderRegistryHost,
   313  			},
   314  			false,
   315  		},
   316  		"aws": {
   317  			Provider{
   318  				Type:      "aws",
   319  				Namespace: "hashicorp",
   320  				Hostname:  DefaultProviderRegistryHost,
   321  			},
   322  			false,
   323  		},
   324  		"AWS": {
   325  			Provider{
   326  				Type:      "aws",
   327  				Namespace: "hashicorp",
   328  				Hostname:  DefaultProviderRegistryHost,
   329  			},
   330  			false,
   331  		},
   332  		"example.com/foo-bar/baz-boop": {
   333  			Provider{
   334  				Type:      "baz-boop",
   335  				Namespace: "foo-bar",
   336  				Hostname:  svchost.Hostname("example.com"),
   337  			},
   338  			false,
   339  		},
   340  		"foo-bar/baz-boop": {
   341  			Provider{
   342  				Type:      "baz-boop",
   343  				Namespace: "foo-bar",
   344  				Hostname:  DefaultProviderRegistryHost,
   345  			},
   346  			false,
   347  		},
   348  		"localhost:8080/foo/bar": {
   349  			Provider{
   350  				Type:      "bar",
   351  				Namespace: "foo",
   352  				Hostname:  svchost.Hostname("localhost:8080"),
   353  			},
   354  			false,
   355  		},
   356  		"example.com/too/many/parts/here": {
   357  			Provider{},
   358  			true,
   359  		},
   360  		"/too///many//slashes": {
   361  			Provider{},
   362  			true,
   363  		},
   364  		"///": {
   365  			Provider{},
   366  			true,
   367  		},
   368  		"/ / /": { // empty strings
   369  			Provider{},
   370  			true,
   371  		},
   372  		"badhost!/hashicorp/aws": {
   373  			Provider{},
   374  			true,
   375  		},
   376  		"example.com/badnamespace!/aws": {
   377  			Provider{},
   378  			true,
   379  		},
   380  		"example.com/bad--namespace/aws": {
   381  			Provider{},
   382  			true,
   383  		},
   384  		"example.com/-badnamespace/aws": {
   385  			Provider{},
   386  			true,
   387  		},
   388  		"example.com/badnamespace-/aws": {
   389  			Provider{},
   390  			true,
   391  		},
   392  		"example.com/bad.namespace/aws": {
   393  			Provider{},
   394  			true,
   395  		},
   396  		"example.com/hashicorp/badtype!": {
   397  			Provider{},
   398  			true,
   399  		},
   400  		"example.com/hashicorp/bad--type": {
   401  			Provider{},
   402  			true,
   403  		},
   404  		"example.com/hashicorp/-badtype": {
   405  			Provider{},
   406  			true,
   407  		},
   408  		"example.com/hashicorp/badtype-": {
   409  			Provider{},
   410  			true,
   411  		},
   412  		"example.com/hashicorp/bad.type": {
   413  			Provider{},
   414  			true,
   415  		},
   416  
   417  		// We forbid the terraform- prefix both because it's redundant to
   418  		// include "terraform" in a Terraform provider name and because we use
   419  		// the longer prefix terraform-provider- to hint for users who might be
   420  		// accidentally using the git repository name or executable file name
   421  		// instead of the provider type.
   422  		"example.com/hashicorp/terraform-provider-bad": {
   423  			Provider{},
   424  			true,
   425  		},
   426  		"example.com/hashicorp/terraform-bad": {
   427  			Provider{},
   428  			true,
   429  		},
   430  	}
   431  
   432  	for name, test := range tests {
   433  		got, diags := ParseProviderSourceString(name)
   434  		for _, problem := range deep.Equal(got, test.Want) {
   435  			t.Errorf(problem)
   436  		}
   437  		if len(diags) > 0 {
   438  			if test.Err == false {
   439  				t.Errorf("got error, expected success")
   440  			}
   441  		} else {
   442  			if test.Err {
   443  				t.Errorf("got success, expected error")
   444  			}
   445  		}
   446  	}
   447  }
   448  
   449  func TestParseProviderPart(t *testing.T) {
   450  	tests := map[string]struct {
   451  		Want  string
   452  		Error string
   453  	}{
   454  		`foo`: {
   455  			`foo`,
   456  			``,
   457  		},
   458  		`FOO`: {
   459  			`foo`,
   460  			``,
   461  		},
   462  		`Foo`: {
   463  			`foo`,
   464  			``,
   465  		},
   466  		`abc-123`: {
   467  			`abc-123`,
   468  			``,
   469  		},
   470  		`Испытание`: {
   471  			`испытание`,
   472  			``,
   473  		},
   474  		`münchen`: { // this is a precomposed u with diaeresis
   475  			`münchen`, // this is a precomposed u with diaeresis
   476  			``,
   477  		},
   478  		`münchen`: { // this is a separate u and combining diaeresis
   479  			`münchen`, // this is a precomposed u with diaeresis
   480  			``,
   481  		},
   482  		`abc--123`: {
   483  			``,
   484  			`cannot use multiple consecutive dashes`,
   485  		},
   486  		`xn--80akhbyknj4f`: { // this is the punycode form of "испытание", but we don't accept punycode here
   487  			``,
   488  			`cannot use multiple consecutive dashes`,
   489  		},
   490  		`abc.123`: {
   491  			``,
   492  			`dots are not allowed`,
   493  		},
   494  		`-abc123`: {
   495  			``,
   496  			`must contain only letters, digits, and dashes, and may not use leading or trailing dashes`,
   497  		},
   498  		`abc123-`: {
   499  			``,
   500  			`must contain only letters, digits, and dashes, and may not use leading or trailing dashes`,
   501  		},
   502  		``: {
   503  			``,
   504  			`must have at least one character`,
   505  		},
   506  	}
   507  
   508  	for given, test := range tests {
   509  		t.Run(given, func(t *testing.T) {
   510  			got, err := ParseProviderPart(given)
   511  			if test.Error != "" {
   512  				if err == nil {
   513  					t.Errorf("unexpected success\ngot:  %s\nwant: %s", err, test.Error)
   514  				} else if got := err.Error(); got != test.Error {
   515  					t.Errorf("wrong error\ngot:  %s\nwant: %s", got, test.Error)
   516  				}
   517  			} else {
   518  				if err != nil {
   519  					t.Errorf("unexpected error\ngot:  %s\nwant: <nil>", err)
   520  				} else if got != test.Want {
   521  					t.Errorf("wrong result\ngot:  %s\nwant: %s", got, test.Want)
   522  				}
   523  			}
   524  		})
   525  	}
   526  }
   527  
   528  func TestProviderEquals(t *testing.T) {
   529  	tests := []struct {
   530  		InputP Provider
   531  		OtherP Provider
   532  		Want   bool
   533  	}{
   534  		{
   535  			NewProvider(DefaultProviderRegistryHost, "foo", "test"),
   536  			NewProvider(DefaultProviderRegistryHost, "foo", "test"),
   537  			true,
   538  		},
   539  		{
   540  			NewProvider(DefaultProviderRegistryHost, "foo", "test"),
   541  			NewProvider(DefaultProviderRegistryHost, "bar", "test"),
   542  			false,
   543  		},
   544  		{
   545  			NewProvider(DefaultProviderRegistryHost, "foo", "test"),
   546  			NewProvider(DefaultProviderRegistryHost, "foo", "my-test"),
   547  			false,
   548  		},
   549  		{
   550  			NewProvider(DefaultProviderRegistryHost, "foo", "test"),
   551  			NewProvider("example.com", "foo", "test"),
   552  			false,
   553  		},
   554  	}
   555  	for _, test := range tests {
   556  		t.Run(test.InputP.String(), func(t *testing.T) {
   557  			got := test.InputP.Equals(test.OtherP)
   558  			if got != test.Want {
   559  				t.Errorf("wrong result\ngot:  %v\nwant: %v", got, test.Want)
   560  			}
   561  		})
   562  	}
   563  }