github.com/trawler/terraform@v0.10.8-0.20171106022149-4b1c7a1d9b48/config/config_test.go (about)

     1  package config
     2  
     3  import (
     4  	"flag"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"log"
     8  	"os"
     9  	"path/filepath"
    10  	"reflect"
    11  	"strings"
    12  	"testing"
    13  
    14  	"github.com/hashicorp/hil/ast"
    15  	"github.com/hashicorp/terraform/helper/logging"
    16  )
    17  
    18  // This is the directory where our test fixtures are.
    19  const fixtureDir = "./test-fixtures"
    20  
    21  func TestMain(m *testing.M) {
    22  	flag.Parse()
    23  	if testing.Verbose() {
    24  		// if we're verbose, use the logging requested by TF_LOG
    25  		logging.SetOutput()
    26  	} else {
    27  		// otherwise silence all logs
    28  		log.SetOutput(ioutil.Discard)
    29  	}
    30  
    31  	os.Exit(m.Run())
    32  }
    33  
    34  func TestConfigCopy(t *testing.T) {
    35  	c := testConfig(t, "copy-basic")
    36  	rOrig := c.Resources[0]
    37  	rCopy := rOrig.Copy()
    38  
    39  	if rCopy.Name != rOrig.Name {
    40  		t.Fatalf("Expected names to equal: %q <=> %q", rCopy.Name, rOrig.Name)
    41  	}
    42  
    43  	if rCopy.Type != rOrig.Type {
    44  		t.Fatalf("Expected types to equal: %q <=> %q", rCopy.Type, rOrig.Type)
    45  	}
    46  
    47  	origCount := rOrig.RawCount.Config()["count"]
    48  	rCopy.RawCount.Config()["count"] = "5"
    49  	if rOrig.RawCount.Config()["count"] != origCount {
    50  		t.Fatalf("Expected RawCount to be copied, but it behaves like a ref!")
    51  	}
    52  
    53  	rCopy.RawConfig.Config()["newfield"] = "hello"
    54  	if rOrig.RawConfig.Config()["newfield"] == "hello" {
    55  		t.Fatalf("Expected RawConfig to be copied, but it behaves like a ref!")
    56  	}
    57  
    58  	rCopy.Provisioners = append(rCopy.Provisioners, &Provisioner{})
    59  	if len(rOrig.Provisioners) == len(rCopy.Provisioners) {
    60  		t.Fatalf("Expected Provisioners to be copied, but it behaves like a ref!")
    61  	}
    62  
    63  	if rCopy.Provider != rOrig.Provider {
    64  		t.Fatalf("Expected providers to equal: %q <=> %q",
    65  			rCopy.Provider, rOrig.Provider)
    66  	}
    67  
    68  	rCopy.DependsOn[0] = "gotchya"
    69  	if rOrig.DependsOn[0] == rCopy.DependsOn[0] {
    70  		t.Fatalf("Expected DependsOn to be copied, but it behaves like a ref!")
    71  	}
    72  
    73  	rCopy.Lifecycle.IgnoreChanges[0] = "gotchya"
    74  	if rOrig.Lifecycle.IgnoreChanges[0] == rCopy.Lifecycle.IgnoreChanges[0] {
    75  		t.Fatalf("Expected Lifecycle to be copied, but it behaves like a ref!")
    76  	}
    77  
    78  }
    79  
    80  func TestConfigCount(t *testing.T) {
    81  	c := testConfig(t, "count-int")
    82  	actual, err := c.Resources[0].Count()
    83  	if err != nil {
    84  		t.Fatalf("err: %s", err)
    85  	}
    86  	if actual != 5 {
    87  		t.Fatalf("bad: %#v", actual)
    88  	}
    89  }
    90  
    91  func TestConfigCount_string(t *testing.T) {
    92  	c := testConfig(t, "count-string")
    93  	actual, err := c.Resources[0].Count()
    94  	if err != nil {
    95  		t.Fatalf("err: %s", err)
    96  	}
    97  	if actual != 5 {
    98  		t.Fatalf("bad: %#v", actual)
    99  	}
   100  }
   101  
   102  // Terraform GH-11800
   103  func TestConfigCount_list(t *testing.T) {
   104  	c := testConfig(t, "count-list")
   105  
   106  	// The key is to interpolate so it doesn't fail parsing
   107  	c.Resources[0].RawCount.Interpolate(map[string]ast.Variable{
   108  		"var.list": ast.Variable{
   109  			Value: []ast.Variable{},
   110  			Type:  ast.TypeList,
   111  		},
   112  	})
   113  
   114  	_, err := c.Resources[0].Count()
   115  	if err == nil {
   116  		t.Fatal("should error")
   117  	}
   118  }
   119  
   120  func TestConfigCount_var(t *testing.T) {
   121  	c := testConfig(t, "count-var")
   122  	_, err := c.Resources[0].Count()
   123  	if err == nil {
   124  		t.Fatalf("should error")
   125  	}
   126  }
   127  
   128  func TestConfig_emptyCollections(t *testing.T) {
   129  	c := testConfig(t, "empty-collections")
   130  	if len(c.Variables) != 3 {
   131  		t.Fatalf("bad: expected 3 variables, got %d", len(c.Variables))
   132  	}
   133  	for _, variable := range c.Variables {
   134  		switch variable.Name {
   135  		case "empty_string":
   136  			if variable.Default != "" {
   137  				t.Fatalf("bad: wrong default %q for variable empty_string", variable.Default)
   138  			}
   139  		case "empty_map":
   140  			if !reflect.DeepEqual(variable.Default, map[string]interface{}{}) {
   141  				t.Fatalf("bad: wrong default %#v for variable empty_map", variable.Default)
   142  			}
   143  		case "empty_list":
   144  			if !reflect.DeepEqual(variable.Default, []interface{}{}) {
   145  				t.Fatalf("bad: wrong default %#v for variable empty_list", variable.Default)
   146  			}
   147  		default:
   148  			t.Fatalf("Unexpected variable: %s", variable.Name)
   149  		}
   150  	}
   151  }
   152  
   153  // This table test is the preferred way to test validation of configuration.
   154  // There are dozens of functions below which do not follow this that are
   155  // there mostly historically. They should be converted at some point.
   156  func TestConfigValidate_table(t *testing.T) {
   157  	cases := []struct {
   158  		Name      string
   159  		Fixture   string
   160  		Err       bool
   161  		ErrString string
   162  	}{
   163  		{
   164  			"basic good",
   165  			"validate-good",
   166  			false,
   167  			"",
   168  		},
   169  
   170  		{
   171  			"depends on module",
   172  			"validate-depends-on-module",
   173  			false,
   174  			"",
   175  		},
   176  
   177  		{
   178  			"depends on non-existent module",
   179  			"validate-depends-on-bad-module",
   180  			true,
   181  			"non-existent module 'foo'",
   182  		},
   183  
   184  		{
   185  			"data source with provisioners",
   186  			"validate-data-provisioner",
   187  			true,
   188  			"data sources cannot have",
   189  		},
   190  
   191  		{
   192  			"basic provisioners",
   193  			"validate-basic-provisioners",
   194  			false,
   195  			"",
   196  		},
   197  
   198  		{
   199  			"backend config with interpolations",
   200  			"validate-backend-interpolate",
   201  			true,
   202  			"cannot contain interp",
   203  		},
   204  		{
   205  			"nested types in variable default",
   206  			"validate-var-nested",
   207  			false,
   208  			"",
   209  		},
   210  		{
   211  			"provider with valid version constraint",
   212  			"provider-version",
   213  			false,
   214  			"",
   215  		},
   216  		{
   217  			"provider with invalid version constraint",
   218  			"provider-version-invalid",
   219  			true,
   220  			"invalid version constraint",
   221  		},
   222  	}
   223  
   224  	for i, tc := range cases {
   225  		t.Run(fmt.Sprintf("%d-%s", i, tc.Name), func(t *testing.T) {
   226  			c := testConfig(t, tc.Fixture)
   227  			err := c.Validate()
   228  			if (err != nil) != tc.Err {
   229  				t.Fatalf("err: %s", err)
   230  			}
   231  			if err != nil {
   232  				if tc.ErrString != "" && !strings.Contains(err.Error(), tc.ErrString) {
   233  					t.Fatalf("expected err to contain: %s\n\ngot: %s", tc.ErrString, err)
   234  				}
   235  
   236  				return
   237  			}
   238  		})
   239  	}
   240  
   241  }
   242  
   243  func TestConfigValidate_tfVersion(t *testing.T) {
   244  	c := testConfig(t, "validate-tf-version")
   245  	if err := c.Validate(); err != nil {
   246  		t.Fatalf("err: %s", err)
   247  	}
   248  }
   249  
   250  func TestConfigValidate_tfVersionBad(t *testing.T) {
   251  	c := testConfig(t, "validate-bad-tf-version")
   252  	if err := c.Validate(); err == nil {
   253  		t.Fatal("should not be valid")
   254  	}
   255  }
   256  
   257  func TestConfigValidate_tfVersionInterpolations(t *testing.T) {
   258  	c := testConfig(t, "validate-tf-version-interp")
   259  	if err := c.Validate(); err == nil {
   260  		t.Fatal("should not be valid")
   261  	}
   262  }
   263  
   264  func TestConfigValidate_badDependsOn(t *testing.T) {
   265  	c := testConfig(t, "validate-bad-depends-on")
   266  	if err := c.Validate(); err == nil {
   267  		t.Fatal("should not be valid")
   268  	}
   269  }
   270  
   271  func TestConfigValidate_countInt(t *testing.T) {
   272  	c := testConfig(t, "validate-count-int")
   273  	if err := c.Validate(); err != nil {
   274  		t.Fatalf("err: %s", err)
   275  	}
   276  }
   277  
   278  func TestConfigValidate_countInt_HCL2(t *testing.T) {
   279  	c := testConfigHCL2(t, "validate-count-int")
   280  	if err := c.Validate(); err != nil {
   281  		t.Fatalf("unexpected error: %s", err)
   282  	}
   283  }
   284  
   285  func TestConfigValidate_countBadContext(t *testing.T) {
   286  	c := testConfig(t, "validate-count-bad-context")
   287  
   288  	err := c.Validate()
   289  
   290  	expected := []string{
   291  		"no_count_in_output: count variables are only valid within resources",
   292  		"no_count_in_module: count variables are only valid within resources",
   293  	}
   294  	for _, exp := range expected {
   295  		if !strings.Contains(err.Error(), exp) {
   296  			t.Fatalf("expected: %q,\nto contain: %q", err, exp)
   297  		}
   298  	}
   299  }
   300  
   301  func TestConfigValidate_countCountVar(t *testing.T) {
   302  	c := testConfig(t, "validate-count-count-var")
   303  	if err := c.Validate(); err == nil {
   304  		t.Fatal("should not be valid")
   305  	}
   306  }
   307  
   308  func TestConfigValidate_countNotInt(t *testing.T) {
   309  	c := testConfig(t, "validate-count-not-int")
   310  	if err := c.Validate(); err == nil {
   311  		t.Fatal("should not be valid")
   312  	}
   313  }
   314  
   315  func TestConfigValidate_countNotInt_HCL2(t *testing.T) {
   316  	c := testConfigHCL2(t, "validate-count-not-int-const")
   317  	if err := c.Validate(); err == nil {
   318  		t.Fatal("should not be valid")
   319  	}
   320  }
   321  
   322  func TestConfigValidate_countNotIntUnknown_HCL2(t *testing.T) {
   323  	c := testConfigHCL2(t, "validate-count-not-int")
   324  	// In HCL2 this is not an error because the unknown variable interpolates
   325  	// to produce an unknown string, which we assume (incorrectly, it turns out)
   326  	// will become a string containing only digits. This is okay because
   327  	// the config validation is only a "best effort" and we'll get a definitive
   328  	// result during the validation graph walk.
   329  	if err := c.Validate(); err != nil {
   330  		t.Fatalf("unexpected error: %s", err)
   331  	}
   332  }
   333  
   334  func TestConfigValidate_countUserVar(t *testing.T) {
   335  	c := testConfig(t, "validate-count-user-var")
   336  	if err := c.Validate(); err != nil {
   337  		t.Fatalf("err: %s", err)
   338  	}
   339  }
   340  
   341  func TestConfigValidate_countUserVar_HCL2(t *testing.T) {
   342  	c := testConfigHCL2(t, "validate-count-user-var")
   343  	if err := c.Validate(); err != nil {
   344  		t.Fatalf("err: %s", err)
   345  	}
   346  }
   347  
   348  func TestConfigValidate_countLocalValue(t *testing.T) {
   349  	c := testConfig(t, "validate-local-value-count")
   350  	if err := c.Validate(); err != nil {
   351  		t.Fatalf("err: %s", err)
   352  	}
   353  }
   354  
   355  func TestConfigValidate_countVar(t *testing.T) {
   356  	c := testConfig(t, "validate-count-var")
   357  	if err := c.Validate(); err != nil {
   358  		t.Fatalf("err: %s", err)
   359  	}
   360  }
   361  
   362  func TestConfigValidate_countVarInvalid(t *testing.T) {
   363  	c := testConfig(t, "validate-count-var-invalid")
   364  	if err := c.Validate(); err == nil {
   365  		t.Fatal("should not be valid")
   366  	}
   367  }
   368  
   369  func TestConfigValidate_countVarUnknown(t *testing.T) {
   370  	c := testConfig(t, "validate-count-var-unknown")
   371  	if err := c.Validate(); err == nil {
   372  		t.Fatal("should not be valid")
   373  	}
   374  }
   375  
   376  func TestConfigValidate_dependsOnVar(t *testing.T) {
   377  	c := testConfig(t, "validate-depends-on-var")
   378  	if err := c.Validate(); err == nil {
   379  		t.Fatal("should not be valid")
   380  	}
   381  }
   382  
   383  func TestConfigValidate_dupModule(t *testing.T) {
   384  	c := testConfig(t, "validate-dup-module")
   385  	if err := c.Validate(); err == nil {
   386  		t.Fatal("should not be valid")
   387  	}
   388  }
   389  
   390  func TestConfigValidate_dupResource(t *testing.T) {
   391  	c := testConfig(t, "validate-dup-resource")
   392  	if err := c.Validate(); err == nil {
   393  		t.Fatal("should not be valid")
   394  	}
   395  }
   396  
   397  func TestConfigValidate_ignoreChanges(t *testing.T) {
   398  	c := testConfig(t, "validate-ignore-changes")
   399  	if err := c.Validate(); err != nil {
   400  		t.Fatalf("err: %s", err)
   401  	}
   402  }
   403  
   404  func TestConfigValidate_ignoreChangesBad(t *testing.T) {
   405  	c := testConfig(t, "validate-ignore-changes-bad")
   406  	if err := c.Validate(); err == nil {
   407  		t.Fatal("should not be valid")
   408  	}
   409  }
   410  
   411  func TestConfigValidate_ignoreChangesInterpolate(t *testing.T) {
   412  	c := testConfig(t, "validate-ignore-changes-interpolate")
   413  	if err := c.Validate(); err == nil {
   414  		t.Fatal("should not be valid")
   415  	}
   416  }
   417  
   418  func TestConfigValidate_moduleNameBad(t *testing.T) {
   419  	c := testConfig(t, "validate-module-name-bad")
   420  	if err := c.Validate(); err == nil {
   421  		t.Fatal("should not be valid")
   422  	}
   423  }
   424  
   425  func TestConfigValidate_moduleSourceVar(t *testing.T) {
   426  	c := testConfig(t, "validate-module-source-var")
   427  	if err := c.Validate(); err == nil {
   428  		t.Fatal("should not be valid")
   429  	}
   430  }
   431  
   432  func TestConfigValidate_moduleVarInt(t *testing.T) {
   433  	c := testConfig(t, "validate-module-var-int")
   434  	if err := c.Validate(); err != nil {
   435  		t.Fatalf("should be valid: %s", err)
   436  	}
   437  }
   438  
   439  func TestConfigValidate_moduleVarMap(t *testing.T) {
   440  	c := testConfig(t, "validate-module-var-map")
   441  	if err := c.Validate(); err != nil {
   442  		t.Fatalf("should be valid: %s", err)
   443  	}
   444  }
   445  
   446  func TestConfigValidate_moduleVarList(t *testing.T) {
   447  	c := testConfig(t, "validate-module-var-list")
   448  	if err := c.Validate(); err != nil {
   449  		t.Fatalf("should be valid: %s", err)
   450  	}
   451  }
   452  
   453  func TestConfigValidate_moduleVarSelf(t *testing.T) {
   454  	c := testConfig(t, "validate-module-var-self")
   455  	if err := c.Validate(); err == nil {
   456  		t.Fatal("should be invalid")
   457  	}
   458  }
   459  
   460  func TestConfigValidate_nil(t *testing.T) {
   461  	var c Config
   462  	if err := c.Validate(); err != nil {
   463  		t.Fatalf("err: %s", err)
   464  	}
   465  }
   466  
   467  func TestConfigValidate_outputBadField(t *testing.T) {
   468  	c := testConfig(t, "validate-output-bad-field")
   469  	if err := c.Validate(); err == nil {
   470  		t.Fatal("should not be valid")
   471  	}
   472  }
   473  
   474  func TestConfigValidate_outputDescription(t *testing.T) {
   475  	c := testConfig(t, "validate-output-description")
   476  	if err := c.Validate(); err != nil {
   477  		t.Fatalf("err: %s", err)
   478  	}
   479  	if len(c.Outputs) != 1 {
   480  		t.Fatalf("got %d outputs; want 1", len(c.Outputs))
   481  	}
   482  	if got, want := "Number 5", c.Outputs[0].Description; got != want {
   483  		t.Fatalf("got description %q; want %q", got, want)
   484  	}
   485  }
   486  
   487  func TestConfigValidate_outputDuplicate(t *testing.T) {
   488  	c := testConfig(t, "validate-output-dup")
   489  	if err := c.Validate(); err == nil {
   490  		t.Fatal("should not be valid")
   491  	}
   492  }
   493  
   494  func TestConfigValidate_pathVar(t *testing.T) {
   495  	c := testConfig(t, "validate-path-var")
   496  	if err := c.Validate(); err != nil {
   497  		t.Fatalf("err: %s", err)
   498  	}
   499  }
   500  
   501  func TestConfigValidate_pathVarInvalid(t *testing.T) {
   502  	c := testConfig(t, "validate-path-var-invalid")
   503  	if err := c.Validate(); err == nil {
   504  		t.Fatal("should not be valid")
   505  	}
   506  }
   507  
   508  func TestConfigValidate_providerMulti(t *testing.T) {
   509  	c := testConfig(t, "validate-provider-multi")
   510  	if err := c.Validate(); err == nil {
   511  		t.Fatal("should not be valid")
   512  	}
   513  }
   514  
   515  func TestConfigValidate_providerMultiGood(t *testing.T) {
   516  	c := testConfig(t, "validate-provider-multi-good")
   517  	if err := c.Validate(); err != nil {
   518  		t.Fatalf("should be valid: %s", err)
   519  	}
   520  }
   521  
   522  func TestConfigValidate_providerMultiRefGood(t *testing.T) {
   523  	c := testConfig(t, "validate-provider-multi-ref-good")
   524  	if err := c.Validate(); err != nil {
   525  		t.Fatalf("should be valid: %s", err)
   526  	}
   527  }
   528  
   529  func TestConfigValidate_provConnSplatOther(t *testing.T) {
   530  	c := testConfig(t, "validate-prov-conn-splat-other")
   531  	if err := c.Validate(); err != nil {
   532  		t.Fatalf("should be valid: %s", err)
   533  	}
   534  }
   535  
   536  func TestConfigValidate_provConnSplatSelf(t *testing.T) {
   537  	c := testConfig(t, "validate-prov-conn-splat-self")
   538  	if err := c.Validate(); err == nil {
   539  		t.Fatal("should not be valid")
   540  	}
   541  }
   542  
   543  func TestConfigValidate_provSplatOther(t *testing.T) {
   544  	c := testConfig(t, "validate-prov-splat-other")
   545  	if err := c.Validate(); err != nil {
   546  		t.Fatalf("should be valid: %s", err)
   547  	}
   548  }
   549  
   550  func TestConfigValidate_provSplatSelf(t *testing.T) {
   551  	c := testConfig(t, "validate-prov-splat-self")
   552  	if err := c.Validate(); err == nil {
   553  		t.Fatal("should not be valid")
   554  	}
   555  }
   556  
   557  func TestConfigValidate_resourceProvVarSelf(t *testing.T) {
   558  	c := testConfig(t, "validate-resource-prov-self")
   559  	if err := c.Validate(); err != nil {
   560  		t.Fatalf("should be valid: %s", err)
   561  	}
   562  }
   563  
   564  func TestConfigValidate_resourceVarSelf(t *testing.T) {
   565  	c := testConfig(t, "validate-resource-self")
   566  	if err := c.Validate(); err == nil {
   567  		t.Fatal("should not be valid")
   568  	}
   569  }
   570  
   571  func TestConfigValidate_unknownThing(t *testing.T) {
   572  	c := testConfig(t, "validate-unknownthing")
   573  	if err := c.Validate(); err == nil {
   574  		t.Fatal("should not be valid")
   575  	}
   576  }
   577  
   578  func TestConfigValidate_unknownResourceVar(t *testing.T) {
   579  	c := testConfig(t, "validate-unknown-resource-var")
   580  	if err := c.Validate(); err == nil {
   581  		t.Fatal("should not be valid")
   582  	}
   583  }
   584  
   585  func TestConfigValidate_unknownResourceVar_output(t *testing.T) {
   586  	c := testConfig(t, "validate-unknown-resource-var-output")
   587  	if err := c.Validate(); err == nil {
   588  		t.Fatal("should not be valid")
   589  	}
   590  }
   591  
   592  func TestConfigValidate_unknownVar(t *testing.T) {
   593  	c := testConfig(t, "validate-unknownvar")
   594  	if err := c.Validate(); err == nil {
   595  		t.Fatal("should not be valid")
   596  	}
   597  }
   598  
   599  func TestConfigValidate_unknownVarCount(t *testing.T) {
   600  	c := testConfig(t, "validate-unknownvar-count")
   601  	if err := c.Validate(); err == nil {
   602  		t.Fatal("should not be valid")
   603  	}
   604  }
   605  
   606  func TestConfigValidate_varDefault(t *testing.T) {
   607  	c := testConfig(t, "validate-var-default")
   608  	if err := c.Validate(); err != nil {
   609  		t.Fatalf("should be valid: %s", err)
   610  	}
   611  }
   612  
   613  func TestConfigValidate_varDefaultListType(t *testing.T) {
   614  	c := testConfig(t, "validate-var-default-list-type")
   615  	if err := c.Validate(); err != nil {
   616  		t.Fatalf("should be valid: %s", err)
   617  	}
   618  }
   619  
   620  func TestConfigValidate_varDefaultInterpolate(t *testing.T) {
   621  	c := testConfig(t, "validate-var-default-interpolate")
   622  	if err := c.Validate(); err == nil {
   623  		t.Fatal("should not be valid")
   624  	}
   625  }
   626  
   627  func TestConfigValidate_varDefaultInterpolateEscaped(t *testing.T) {
   628  	c := testConfig(t, "validate-var-default-interpolate-escaped")
   629  	if err := c.Validate(); err != nil {
   630  		t.Fatalf("should be valid, but got err: %s", err)
   631  	}
   632  }
   633  
   634  func TestConfigValidate_varDup(t *testing.T) {
   635  	c := testConfig(t, "validate-var-dup")
   636  	if err := c.Validate(); err == nil {
   637  		t.Fatal("should not be valid")
   638  	}
   639  }
   640  
   641  func TestConfigValidate_varMultiExactNonSlice(t *testing.T) {
   642  	c := testConfig(t, "validate-var-multi-exact-non-slice")
   643  	if err := c.Validate(); err != nil {
   644  		t.Fatalf("should be valid: %s", err)
   645  	}
   646  }
   647  
   648  func TestConfigValidate_varMultiFunctionCall(t *testing.T) {
   649  	c := testConfig(t, "validate-var-multi-func")
   650  	if err := c.Validate(); err != nil {
   651  		t.Fatalf("should be valid: %s", err)
   652  	}
   653  }
   654  
   655  func TestConfigValidate_varModule(t *testing.T) {
   656  	c := testConfig(t, "validate-var-module")
   657  	if err := c.Validate(); err != nil {
   658  		t.Fatalf("err: %s", err)
   659  	}
   660  }
   661  
   662  func TestConfigValidate_varModuleInvalid(t *testing.T) {
   663  	c := testConfig(t, "validate-var-module-invalid")
   664  	if err := c.Validate(); err == nil {
   665  		t.Fatal("should not be valid")
   666  	}
   667  }
   668  
   669  func TestConfigValidate_varProviderVersionInvalid(t *testing.T) {
   670  	c := testConfig(t, "validate-provider-version-invalid")
   671  	if err := c.Validate(); err == nil {
   672  		t.Fatal("should not be valid")
   673  	}
   674  }
   675  
   676  func TestNameRegexp(t *testing.T) {
   677  	cases := []struct {
   678  		Input string
   679  		Match bool
   680  	}{
   681  		{"hello", true},
   682  		{"foo-bar", true},
   683  		{"foo_bar", true},
   684  		{"_hello", true},
   685  		{"foo bar", false},
   686  		{"foo.bar", false},
   687  	}
   688  
   689  	for _, tc := range cases {
   690  		if NameRegexp.Match([]byte(tc.Input)) != tc.Match {
   691  			t.Fatalf("Input: %s\n\nExpected: %#v", tc.Input, tc.Match)
   692  		}
   693  	}
   694  }
   695  
   696  func TestConfigValidate_localValuesMultiFile(t *testing.T) {
   697  	c, err := LoadDir(filepath.Join(fixtureDir, "validate-local-multi-file"))
   698  	if err != nil {
   699  		t.Fatalf("unexpected error during load: %s", err)
   700  	}
   701  	if err := c.Validate(); err != nil {
   702  		t.Fatalf("unexpected error from validate: %s", err)
   703  	}
   704  	if len(c.Locals) != 1 {
   705  		t.Fatalf("got 0 locals; want 1")
   706  	}
   707  	if got, want := c.Locals[0].Name, "test"; got != want {
   708  		t.Errorf("wrong local name\ngot:  %#v\nwant: %#v", got, want)
   709  	}
   710  }
   711  
   712  func TestProviderConfigName(t *testing.T) {
   713  	pcs := []*ProviderConfig{
   714  		&ProviderConfig{Name: "aw"},
   715  		&ProviderConfig{Name: "aws"},
   716  		&ProviderConfig{Name: "a"},
   717  		&ProviderConfig{Name: "gce_"},
   718  	}
   719  
   720  	n := ProviderConfigName("aws_instance", pcs)
   721  	if n != "aws" {
   722  		t.Fatalf("bad: %s", n)
   723  	}
   724  }
   725  
   726  func testConfig(t *testing.T, name string) *Config {
   727  	c, err := LoadFile(filepath.Join(fixtureDir, name, "main.tf"))
   728  	if err != nil {
   729  		t.Fatalf("file: %s\n\nerr: %s", name, err)
   730  	}
   731  
   732  	return c
   733  }
   734  
   735  // testConfigHCL loads a config, forcing it to be processed with the HCL2
   736  // loader even if it doesn't explicitly opt in to the HCL2 experiment.
   737  func testConfigHCL2(t *testing.T, name string) *Config {
   738  	t.Helper()
   739  	cer, _, err := globalHCL2Loader.loadFile(filepath.Join(fixtureDir, name, "main.tf"))
   740  	if err != nil {
   741  		t.Fatalf("failed to load %s: %s", name, err)
   742  	}
   743  
   744  	cfg, err := cer.Config()
   745  	if err != nil {
   746  		t.Fatalf("failed to decode %s: %s", name, err)
   747  	}
   748  
   749  	return cfg
   750  }
   751  
   752  func TestConfigDataCount(t *testing.T) {
   753  	c := testConfig(t, "data-count")
   754  	actual, err := c.Resources[0].Count()
   755  	if err != nil {
   756  		t.Fatalf("err: %s", err)
   757  	}
   758  	if actual != 5 {
   759  		t.Fatalf("bad: %#v", actual)
   760  	}
   761  
   762  	// we need to make sure "count" has been removed from the RawConfig, since
   763  	// it's not a real key and won't validate.
   764  	if _, ok := c.Resources[0].RawConfig.Raw["count"]; ok {
   765  		t.Fatal("count key still exists in RawConfig")
   766  	}
   767  }
   768  
   769  func TestConfigProviderVersion(t *testing.T) {
   770  	c := testConfig(t, "provider-version")
   771  
   772  	if len(c.ProviderConfigs) != 1 {
   773  		t.Fatal("expected 1 provider")
   774  	}
   775  
   776  	p := c.ProviderConfigs[0]
   777  	if p.Name != "aws" {
   778  		t.Fatalf("expected provider name 'aws', got %q", p.Name)
   779  	}
   780  
   781  	if p.Version != "0.0.1" {
   782  		t.Fatalf("expected providers version '0.0.1', got %q", p.Version)
   783  	}
   784  
   785  	if _, ok := p.RawConfig.Raw["version"]; ok {
   786  		t.Fatal("'version' should not exist in raw config")
   787  	}
   788  }
   789  
   790  func TestResourceProviderFullName(t *testing.T) {
   791  	type testCase struct {
   792  		ResourceName string
   793  		Alias        string
   794  		Expected     string
   795  	}
   796  
   797  	tests := []testCase{
   798  		{
   799  			// If no alias is provided, the first underscore-separated segment
   800  			// is assumed to be the provider name.
   801  			ResourceName: "aws_thing",
   802  			Alias:        "",
   803  			Expected:     "aws",
   804  		},
   805  		{
   806  			// If we have more than one underscore then it's the first one that we'll use.
   807  			ResourceName: "aws_thingy_thing",
   808  			Alias:        "",
   809  			Expected:     "aws",
   810  		},
   811  		{
   812  			// A provider can export a resource whose name is just the bare provider name,
   813  			// e.g. because the provider only has one resource and so any additional
   814  			// parts would be redundant.
   815  			ResourceName: "external",
   816  			Alias:        "",
   817  			Expected:     "external",
   818  		},
   819  		{
   820  			// Alias always overrides the default extraction of the name
   821  			ResourceName: "aws_thing",
   822  			Alias:        "tls.baz",
   823  			Expected:     "tls.baz",
   824  		},
   825  	}
   826  
   827  	for _, test := range tests {
   828  		got := ResourceProviderFullName(test.ResourceName, test.Alias)
   829  		if got != test.Expected {
   830  			t.Errorf(
   831  				"(%q, %q) produced %q; want %q",
   832  				test.ResourceName, test.Alias,
   833  				got,
   834  				test.Expected,
   835  			)
   836  		}
   837  	}
   838  }
   839  
   840  func TestConfigModuleProviders(t *testing.T) {
   841  	c := testConfig(t, "module-providers")
   842  
   843  	if len(c.Modules) != 1 {
   844  		t.Fatalf("expected 1 module, got %d", len(c.Modules))
   845  	}
   846  
   847  	expected := map[string]string{
   848  		"aws": "aws.foo",
   849  	}
   850  
   851  	got := c.Modules[0].Providers
   852  
   853  	if !reflect.DeepEqual(expected, got) {
   854  		t.Fatalf("exptected providers %#v, got providers %#v", expected, got)
   855  	}
   856  }