github.com/rstandt/terraform@v0.12.32-0.20230710220336-b1063613405c/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 = "./testdata"
    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  			"not a valid version constraint",
   221  		},
   222  		{
   223  			"invalid provider name in module block",
   224  			"validate-missing-provider",
   225  			true,
   226  			"cannot pass non-existent provider",
   227  		},
   228  	}
   229  
   230  	for i, tc := range cases {
   231  		t.Run(fmt.Sprintf("%d-%s", i, tc.Name), func(t *testing.T) {
   232  			c := testConfig(t, tc.Fixture)
   233  			diags := c.Validate()
   234  			if diags.HasErrors() != tc.Err {
   235  				t.Fatalf("err: %s", diags.Err().Error())
   236  			}
   237  			if diags.HasErrors() {
   238  				gotErr := diags.Err().Error()
   239  				if tc.ErrString != "" && !strings.Contains(gotErr, tc.ErrString) {
   240  					t.Fatalf("expected err to contain: %s\n\ngot: %s", tc.ErrString, gotErr)
   241  				}
   242  
   243  				return
   244  			}
   245  		})
   246  	}
   247  
   248  }
   249  
   250  func TestConfigValidate_tfVersion(t *testing.T) {
   251  	c := testConfig(t, "validate-tf-version")
   252  	if err := c.Validate(); err != nil {
   253  		t.Fatalf("err: %s", err)
   254  	}
   255  }
   256  
   257  func TestConfigValidate_tfVersionBad(t *testing.T) {
   258  	c := testConfig(t, "validate-bad-tf-version")
   259  	if err := c.Validate(); err == nil {
   260  		t.Fatal("should not be valid")
   261  	}
   262  }
   263  
   264  func TestConfigValidate_tfVersionInterpolations(t *testing.T) {
   265  	c := testConfig(t, "validate-tf-version-interp")
   266  	if err := c.Validate(); err == nil {
   267  		t.Fatal("should not be valid")
   268  	}
   269  }
   270  
   271  func TestConfigValidate_badDependsOn(t *testing.T) {
   272  	c := testConfig(t, "validate-bad-depends-on")
   273  	if err := c.Validate(); err == nil {
   274  		t.Fatal("should not be valid")
   275  	}
   276  }
   277  
   278  func TestConfigValidate_countInt(t *testing.T) {
   279  	c := testConfig(t, "validate-count-int")
   280  	if err := c.Validate(); err != nil {
   281  		t.Fatalf("err: %s", err)
   282  	}
   283  }
   284  
   285  func TestConfigValidate_countBadContext(t *testing.T) {
   286  	c := testConfig(t, "validate-count-bad-context")
   287  
   288  	diags := c.Validate()
   289  
   290  	expected := []string{
   291  		"output \"no_count_in_output\": count variables are only valid within resources",
   292  		"module \"no_count_in_module\": count variables are only valid within resources",
   293  	}
   294  	for _, exp := range expected {
   295  		errStr := diags.Err().Error()
   296  		if !strings.Contains(errStr, exp) {
   297  			t.Errorf("expected: %q,\nto contain: %q", errStr, exp)
   298  		}
   299  	}
   300  }
   301  
   302  func TestConfigValidate_countCountVar(t *testing.T) {
   303  	c := testConfig(t, "validate-count-count-var")
   304  	if err := c.Validate(); err == nil {
   305  		t.Fatal("should not be valid")
   306  	}
   307  }
   308  
   309  func TestConfigValidate_countNotInt(t *testing.T) {
   310  	c := testConfig(t, "validate-count-not-int")
   311  	if err := c.Validate(); err == nil {
   312  		t.Fatal("should not be valid")
   313  	}
   314  }
   315  
   316  func TestConfigValidate_countUserVar(t *testing.T) {
   317  	c := testConfig(t, "validate-count-user-var")
   318  	if err := c.Validate(); err != nil {
   319  		t.Fatalf("err: %s", err)
   320  	}
   321  }
   322  
   323  func TestConfigValidate_countLocalValue(t *testing.T) {
   324  	c := testConfig(t, "validate-local-value-count")
   325  	if err := c.Validate(); err != nil {
   326  		t.Fatalf("err: %s", err)
   327  	}
   328  }
   329  
   330  func TestConfigValidate_countVar(t *testing.T) {
   331  	c := testConfig(t, "validate-count-var")
   332  	if err := c.Validate(); err != nil {
   333  		t.Fatalf("err: %s", err)
   334  	}
   335  }
   336  
   337  func TestConfigValidate_countVarInvalid(t *testing.T) {
   338  	c := testConfig(t, "validate-count-var-invalid")
   339  	if err := c.Validate(); err == nil {
   340  		t.Fatal("should not be valid")
   341  	}
   342  }
   343  
   344  func TestConfigValidate_countVarUnknown(t *testing.T) {
   345  	c := testConfig(t, "validate-count-var-unknown")
   346  	if err := c.Validate(); err == nil {
   347  		t.Fatal("should not be valid")
   348  	}
   349  }
   350  
   351  func TestConfigValidate_dependsOnVar(t *testing.T) {
   352  	c := testConfig(t, "validate-depends-on-var")
   353  	if err := c.Validate(); err == nil {
   354  		t.Fatal("should not be valid")
   355  	}
   356  }
   357  
   358  func TestConfigValidate_dupModule(t *testing.T) {
   359  	c := testConfig(t, "validate-dup-module")
   360  	if err := c.Validate(); err == nil {
   361  		t.Fatal("should not be valid")
   362  	}
   363  }
   364  
   365  func TestConfigValidate_dupResource(t *testing.T) {
   366  	c := testConfig(t, "validate-dup-resource")
   367  	if err := c.Validate(); err == nil {
   368  		t.Fatal("should not be valid")
   369  	}
   370  }
   371  
   372  func TestConfigValidate_ignoreChanges(t *testing.T) {
   373  	c := testConfig(t, "validate-ignore-changes")
   374  	if err := c.Validate(); err != nil {
   375  		t.Fatalf("err: %s", err)
   376  	}
   377  }
   378  
   379  func TestConfigValidate_ignoreChangesBad(t *testing.T) {
   380  	c := testConfig(t, "validate-ignore-changes-bad")
   381  	if err := c.Validate(); err == nil {
   382  		t.Fatal("should not be valid")
   383  	}
   384  }
   385  
   386  func TestConfigValidate_ignoreChangesInterpolate(t *testing.T) {
   387  	c := testConfig(t, "validate-ignore-changes-interpolate")
   388  	if err := c.Validate(); err == nil {
   389  		t.Fatal("should not be valid")
   390  	}
   391  }
   392  
   393  func TestConfigValidate_moduleNameBad(t *testing.T) {
   394  	c := testConfig(t, "validate-module-name-bad")
   395  	if err := c.Validate(); err == nil {
   396  		t.Fatal("should not be valid")
   397  	}
   398  }
   399  
   400  func TestConfigValidate_moduleSourceVar(t *testing.T) {
   401  	c := testConfig(t, "validate-module-source-var")
   402  	if err := c.Validate(); err == nil {
   403  		t.Fatal("should not be valid")
   404  	}
   405  }
   406  
   407  func TestConfigValidate_moduleVarInt(t *testing.T) {
   408  	c := testConfig(t, "validate-module-var-int")
   409  	if err := c.Validate(); err != nil {
   410  		t.Fatalf("should be valid: %s", err)
   411  	}
   412  }
   413  
   414  func TestConfigValidate_moduleVarMap(t *testing.T) {
   415  	c := testConfig(t, "validate-module-var-map")
   416  	if err := c.Validate(); err != nil {
   417  		t.Fatalf("should be valid: %s", err)
   418  	}
   419  }
   420  
   421  func TestConfigValidate_moduleVarList(t *testing.T) {
   422  	c := testConfig(t, "validate-module-var-list")
   423  	if err := c.Validate(); err != nil {
   424  		t.Fatalf("should be valid: %s", err)
   425  	}
   426  }
   427  
   428  func TestConfigValidate_moduleVarSelf(t *testing.T) {
   429  	c := testConfig(t, "validate-module-var-self")
   430  	if err := c.Validate(); err == nil {
   431  		t.Fatal("should be invalid")
   432  	}
   433  }
   434  
   435  func TestConfigValidate_nil(t *testing.T) {
   436  	var c Config
   437  	if err := c.Validate(); err != nil {
   438  		t.Fatalf("err: %s", err)
   439  	}
   440  }
   441  
   442  func TestConfigValidate_outputBadField(t *testing.T) {
   443  	c := testConfig(t, "validate-output-bad-field")
   444  	if err := c.Validate(); err == nil {
   445  		t.Fatal("should not be valid")
   446  	}
   447  }
   448  
   449  func TestConfigValidate_outputDescription(t *testing.T) {
   450  	c := testConfig(t, "validate-output-description")
   451  	if err := c.Validate(); err != nil {
   452  		t.Fatalf("err: %s", err)
   453  	}
   454  	if len(c.Outputs) != 1 {
   455  		t.Fatalf("got %d outputs; want 1", len(c.Outputs))
   456  	}
   457  	if got, want := "Number 5", c.Outputs[0].Description; got != want {
   458  		t.Fatalf("got description %q; want %q", got, want)
   459  	}
   460  }
   461  
   462  func TestConfigValidate_outputDuplicate(t *testing.T) {
   463  	c := testConfig(t, "validate-output-dup")
   464  	if err := c.Validate(); err == nil {
   465  		t.Fatal("should not be valid")
   466  	}
   467  }
   468  
   469  func TestConfigValidate_pathVar(t *testing.T) {
   470  	c := testConfig(t, "validate-path-var")
   471  	if err := c.Validate(); err != nil {
   472  		t.Fatalf("err: %s", err)
   473  	}
   474  }
   475  
   476  func TestConfigValidate_pathVarInvalid(t *testing.T) {
   477  	c := testConfig(t, "validate-path-var-invalid")
   478  	if err := c.Validate(); err == nil {
   479  		t.Fatal("should not be valid")
   480  	}
   481  }
   482  
   483  func TestConfigValidate_providerMulti(t *testing.T) {
   484  	c := testConfig(t, "validate-provider-multi")
   485  	if err := c.Validate(); err == nil {
   486  		t.Fatal("should not be valid")
   487  	}
   488  }
   489  
   490  func TestConfigValidate_providerMultiGood(t *testing.T) {
   491  	c := testConfig(t, "validate-provider-multi-good")
   492  	if err := c.Validate(); err != nil {
   493  		t.Fatalf("should be valid: %s", err)
   494  	}
   495  }
   496  
   497  func TestConfigValidate_providerMultiRefGood(t *testing.T) {
   498  	c := testConfig(t, "validate-provider-multi-ref-good")
   499  	if err := c.Validate(); err != nil {
   500  		t.Fatalf("should be valid: %s", err)
   501  	}
   502  }
   503  
   504  func TestConfigValidate_provConnSplatOther(t *testing.T) {
   505  	c := testConfig(t, "validate-prov-conn-splat-other")
   506  	if err := c.Validate(); err != nil {
   507  		t.Fatalf("should be valid: %s", err)
   508  	}
   509  }
   510  
   511  func TestConfigValidate_provConnSplatSelf(t *testing.T) {
   512  	c := testConfig(t, "validate-prov-conn-splat-self")
   513  	if err := c.Validate(); err == nil {
   514  		t.Fatal("should not be valid")
   515  	}
   516  }
   517  
   518  func TestConfigValidate_provSplatOther(t *testing.T) {
   519  	c := testConfig(t, "validate-prov-splat-other")
   520  	if err := c.Validate(); err != nil {
   521  		t.Fatalf("should be valid: %s", err)
   522  	}
   523  }
   524  
   525  func TestConfigValidate_provSplatSelf(t *testing.T) {
   526  	c := testConfig(t, "validate-prov-splat-self")
   527  	if err := c.Validate(); err == nil {
   528  		t.Fatal("should not be valid")
   529  	}
   530  }
   531  
   532  func TestConfigValidate_resourceProvVarSelf(t *testing.T) {
   533  	c := testConfig(t, "validate-resource-prov-self")
   534  	if err := c.Validate(); err != nil {
   535  		t.Fatalf("should be valid: %s", err)
   536  	}
   537  }
   538  
   539  func TestConfigValidate_resourceVarSelf(t *testing.T) {
   540  	c := testConfig(t, "validate-resource-self")
   541  	if err := c.Validate(); err == nil {
   542  		t.Fatal("should not be valid")
   543  	}
   544  }
   545  
   546  func TestConfigValidate_unknownThing(t *testing.T) {
   547  	c := testConfig(t, "validate-unknownthing")
   548  	if err := c.Validate(); err == nil {
   549  		t.Fatal("should not be valid")
   550  	}
   551  }
   552  
   553  func TestConfigValidate_unknownResourceVar(t *testing.T) {
   554  	c := testConfig(t, "validate-unknown-resource-var")
   555  	if err := c.Validate(); err == nil {
   556  		t.Fatal("should not be valid")
   557  	}
   558  }
   559  
   560  func TestConfigValidate_unknownResourceVar_output(t *testing.T) {
   561  	c := testConfig(t, "validate-unknown-resource-var-output")
   562  	if err := c.Validate(); err == nil {
   563  		t.Fatal("should not be valid")
   564  	}
   565  }
   566  
   567  func TestConfigValidate_unknownVar(t *testing.T) {
   568  	c := testConfig(t, "validate-unknownvar")
   569  	if err := c.Validate(); err == nil {
   570  		t.Fatal("should not be valid")
   571  	}
   572  }
   573  
   574  func TestConfigValidate_unknownVarCount(t *testing.T) {
   575  	c := testConfig(t, "validate-unknownvar-count")
   576  	if err := c.Validate(); err == nil {
   577  		t.Fatal("should not be valid")
   578  	}
   579  }
   580  
   581  func TestConfigValidate_varDefault(t *testing.T) {
   582  	c := testConfig(t, "validate-var-default")
   583  	if err := c.Validate(); err != nil {
   584  		t.Fatalf("should be valid: %s", err)
   585  	}
   586  }
   587  
   588  func TestConfigValidate_varDefaultListType(t *testing.T) {
   589  	c := testConfig(t, "validate-var-default-list-type")
   590  	if err := c.Validate(); err != nil {
   591  		t.Fatalf("should be valid: %s", err)
   592  	}
   593  }
   594  
   595  func TestConfigValidate_varDefaultInterpolate(t *testing.T) {
   596  	c := testConfig(t, "validate-var-default-interpolate")
   597  	if err := c.Validate(); err == nil {
   598  		t.Fatal("should not be valid")
   599  	}
   600  }
   601  
   602  func TestConfigValidate_varDefaultInterpolateEscaped(t *testing.T) {
   603  	c := testConfig(t, "validate-var-default-interpolate-escaped")
   604  	if err := c.Validate(); err != nil {
   605  		t.Fatalf("should be valid, but got err: %s", err)
   606  	}
   607  }
   608  
   609  func TestConfigValidate_varDup(t *testing.T) {
   610  	c := testConfig(t, "validate-var-dup")
   611  	if err := c.Validate(); err == nil {
   612  		t.Fatal("should not be valid")
   613  	}
   614  }
   615  
   616  func TestConfigValidate_varMultiExactNonSlice(t *testing.T) {
   617  	c := testConfig(t, "validate-var-multi-exact-non-slice")
   618  	if err := c.Validate(); err != nil {
   619  		t.Fatalf("should be valid: %s", err)
   620  	}
   621  }
   622  
   623  func TestConfigValidate_varMultiFunctionCall(t *testing.T) {
   624  	c := testConfig(t, "validate-var-multi-func")
   625  	if err := c.Validate(); err != nil {
   626  		t.Fatalf("should be valid: %s", err)
   627  	}
   628  }
   629  
   630  func TestConfigValidate_varModule(t *testing.T) {
   631  	c := testConfig(t, "validate-var-module")
   632  	if err := c.Validate(); err != nil {
   633  		t.Fatalf("err: %s", err)
   634  	}
   635  }
   636  
   637  func TestConfigValidate_varModuleInvalid(t *testing.T) {
   638  	c := testConfig(t, "validate-var-module-invalid")
   639  	if err := c.Validate(); err == nil {
   640  		t.Fatal("should not be valid")
   641  	}
   642  }
   643  
   644  func TestConfigValidate_varProviderVersionInvalid(t *testing.T) {
   645  	c := testConfig(t, "validate-provider-version-invalid")
   646  	if err := c.Validate(); err == nil {
   647  		t.Fatal("should not be valid")
   648  	}
   649  }
   650  
   651  func TestNameRegexp(t *testing.T) {
   652  	cases := []struct {
   653  		Input string
   654  		Match bool
   655  	}{
   656  		{"hello", true},
   657  		{"foo-bar", true},
   658  		{"foo_bar", true},
   659  		{"_hello", true},
   660  		{"foo bar", false},
   661  		{"foo.bar", false},
   662  	}
   663  
   664  	for _, tc := range cases {
   665  		if NameRegexp.Match([]byte(tc.Input)) != tc.Match {
   666  			t.Fatalf("Input: %s\n\nExpected: %#v", tc.Input, tc.Match)
   667  		}
   668  	}
   669  }
   670  
   671  func TestConfigValidate_localValuesMultiFile(t *testing.T) {
   672  	c, err := LoadDir(filepath.Join(fixtureDir, "validate-local-multi-file"))
   673  	if err != nil {
   674  		t.Fatalf("unexpected error during load: %s", err)
   675  	}
   676  	if err := c.Validate(); err != nil {
   677  		t.Fatalf("unexpected error from validate: %s", err)
   678  	}
   679  	if len(c.Locals) != 1 {
   680  		t.Fatalf("got 0 locals; want 1")
   681  	}
   682  	if got, want := c.Locals[0].Name, "test"; got != want {
   683  		t.Errorf("wrong local name\ngot:  %#v\nwant: %#v", got, want)
   684  	}
   685  }
   686  
   687  func TestProviderConfigName(t *testing.T) {
   688  	pcs := []*ProviderConfig{
   689  		&ProviderConfig{Name: "aw"},
   690  		&ProviderConfig{Name: "aws"},
   691  		&ProviderConfig{Name: "a"},
   692  		&ProviderConfig{Name: "gce_"},
   693  	}
   694  
   695  	n := ProviderConfigName("aws_instance", pcs)
   696  	if n != "aws" {
   697  		t.Fatalf("bad: %s", n)
   698  	}
   699  }
   700  
   701  func testConfig(t *testing.T, name string) *Config {
   702  	c, err := LoadFile(filepath.Join(fixtureDir, name, "main.tf"))
   703  	if err != nil {
   704  		t.Fatalf("file: %s\n\nerr: %s", name, err)
   705  	}
   706  
   707  	return c
   708  }
   709  
   710  func TestConfigDataCount(t *testing.T) {
   711  	c := testConfig(t, "data-count")
   712  	actual, err := c.Resources[0].Count()
   713  	if err != nil {
   714  		t.Fatalf("err: %s", err)
   715  	}
   716  	if actual != 5 {
   717  		t.Fatalf("bad: %#v", actual)
   718  	}
   719  
   720  	// we need to make sure "count" has been removed from the RawConfig, since
   721  	// it's not a real key and won't validate.
   722  	if _, ok := c.Resources[0].RawConfig.Raw["count"]; ok {
   723  		t.Fatal("count key still exists in RawConfig")
   724  	}
   725  }
   726  
   727  func TestConfigProviderVersion(t *testing.T) {
   728  	c := testConfig(t, "provider-version")
   729  
   730  	if len(c.ProviderConfigs) != 1 {
   731  		t.Fatal("expected 1 provider")
   732  	}
   733  
   734  	p := c.ProviderConfigs[0]
   735  	if p.Name != "aws" {
   736  		t.Fatalf("expected provider name 'aws', got %q", p.Name)
   737  	}
   738  
   739  	if p.Version != "0.0.1" {
   740  		t.Fatalf("expected providers version '0.0.1', got %q", p.Version)
   741  	}
   742  
   743  	if _, ok := p.RawConfig.Raw["version"]; ok {
   744  		t.Fatal("'version' should not exist in raw config")
   745  	}
   746  }
   747  
   748  func TestConfigModuleProviders(t *testing.T) {
   749  	c := testConfig(t, "module-providers")
   750  
   751  	if len(c.Modules) != 1 {
   752  		t.Fatalf("expected 1 module, got %d", len(c.Modules))
   753  	}
   754  
   755  	expected := map[string]string{
   756  		"aws": "aws.foo",
   757  	}
   758  
   759  	got := c.Modules[0].Providers
   760  
   761  	if !reflect.DeepEqual(expected, got) {
   762  		t.Fatalf("exptected providers %#v, got providers %#v", expected, got)
   763  	}
   764  }
   765  
   766  func TestValidateOutputErrorWarnings(t *testing.T) {
   767  	// TODO: remove this in 0.12
   768  	c := testConfig(t, "output-warnings")
   769  
   770  	diags := c.Validate()
   771  	if diags.HasErrors() {
   772  		t.Fatal("config should not have errors:", diags)
   773  	}
   774  	if len(diags) != 2 {
   775  		t.Fatalf("should have 2 warnings, got %d:\n%s", len(diags), diags)
   776  	}
   777  
   778  	// this fixture has no explicit count, and should have no warning
   779  	c = testConfig(t, "output-no-warnings")
   780  	if err := c.Validate(); err != nil {
   781  		t.Fatal("config should have no warnings or errors")
   782  	}
   783  }