| package backend |
| |
| import ( |
| "strings" |
| "testing" |
| |
| "github.com/google/go-cmp/cmp" |
| "github.com/hashicorp/hcl/v2" |
| "github.com/zclconf/go-cty/cty" |
| |
| "github.com/hashicorp/terraform/internal/configs" |
| "github.com/hashicorp/terraform/internal/terraform" |
| "github.com/hashicorp/terraform/internal/tfdiags" |
| ) |
| |
| func TestUnparsedValue(t *testing.T) { |
| vv := map[string]UnparsedVariableValue{ |
| "undeclared0": testUnparsedVariableValue("0"), |
| "undeclared1": testUnparsedVariableValue("1"), |
| "undeclared2": testUnparsedVariableValue("2"), |
| "undeclared3": testUnparsedVariableValue("3"), |
| "undeclared4": testUnparsedVariableValue("4"), |
| "declared1": testUnparsedVariableValue("5"), |
| } |
| decls := map[string]*configs.Variable{ |
| "declared1": { |
| Name: "declared1", |
| Type: cty.String, |
| ConstraintType: cty.String, |
| ParsingMode: configs.VariableParseLiteral, |
| DeclRange: hcl.Range{ |
| Filename: "fake.tf", |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 0}, |
| }, |
| }, |
| "missing1": { |
| Name: "missing1", |
| Type: cty.String, |
| ConstraintType: cty.String, |
| ParsingMode: configs.VariableParseLiteral, |
| DeclRange: hcl.Range{ |
| Filename: "fake.tf", |
| Start: hcl.Pos{Line: 3, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 3, Column: 1, Byte: 0}, |
| }, |
| }, |
| "missing2": { |
| Name: "missing1", |
| Type: cty.String, |
| ConstraintType: cty.String, |
| ParsingMode: configs.VariableParseLiteral, |
| Default: cty.StringVal("default for missing2"), |
| DeclRange: hcl.Range{ |
| Filename: "fake.tf", |
| Start: hcl.Pos{Line: 4, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 4, Column: 1, Byte: 0}, |
| }, |
| }, |
| } |
| |
| const undeclSingular = `Value for undeclared variable` |
| const undeclPlural = `Values for undeclared variables` |
| |
| t.Run("ParseDeclaredVariableValues", func(t *testing.T) { |
| gotVals, diags := ParseDeclaredVariableValues(vv, decls) |
| |
| if got, want := len(diags), 0; got != want { |
| t.Fatalf("wrong number of diagnostics %d; want %d", got, want) |
| } |
| |
| wantVals := terraform.InputValues{ |
| "declared1": { |
| Value: cty.StringVal("5"), |
| SourceType: terraform.ValueFromNamedFile, |
| SourceRange: tfdiags.SourceRange{ |
| Filename: "fake.tfvars", |
| Start: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0}, |
| End: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0}, |
| }, |
| }, |
| } |
| |
| if diff := cmp.Diff(wantVals, gotVals, cmp.Comparer(cty.Value.RawEquals)); diff != "" { |
| t.Errorf("wrong result\n%s", diff) |
| } |
| }) |
| |
| t.Run("ParseUndeclaredVariableValues", func(t *testing.T) { |
| gotVals, diags := ParseUndeclaredVariableValues(vv, decls) |
| |
| if got, want := len(diags), 3; got != want { |
| t.Fatalf("wrong number of diagnostics %d; want %d", got, want) |
| } |
| |
| if got, want := diags[0].Description().Summary, undeclSingular; got != want { |
| t.Errorf("wrong summary for diagnostic 0\ngot: %s\nwant: %s", got, want) |
| } |
| |
| if got, want := diags[1].Description().Summary, undeclSingular; got != want { |
| t.Errorf("wrong summary for diagnostic 1\ngot: %s\nwant: %s", got, want) |
| } |
| |
| if got, want := diags[2].Description().Summary, undeclPlural; got != want { |
| t.Errorf("wrong summary for diagnostic 2\ngot: %s\nwant: %s", got, want) |
| } |
| |
| wantVals := terraform.InputValues{ |
| "undeclared0": { |
| Value: cty.StringVal("0"), |
| SourceType: terraform.ValueFromNamedFile, |
| SourceRange: tfdiags.SourceRange{ |
| Filename: "fake.tfvars", |
| Start: tfdiags.SourcePos{Line: 1, Column: 1}, |
| End: tfdiags.SourcePos{Line: 1, Column: 1}, |
| }, |
| }, |
| "undeclared1": { |
| Value: cty.StringVal("1"), |
| SourceType: terraform.ValueFromNamedFile, |
| SourceRange: tfdiags.SourceRange{ |
| Filename: "fake.tfvars", |
| Start: tfdiags.SourcePos{Line: 1, Column: 1}, |
| End: tfdiags.SourcePos{Line: 1, Column: 1}, |
| }, |
| }, |
| "undeclared2": { |
| Value: cty.StringVal("2"), |
| SourceType: terraform.ValueFromNamedFile, |
| SourceRange: tfdiags.SourceRange{ |
| Filename: "fake.tfvars", |
| Start: tfdiags.SourcePos{Line: 1, Column: 1}, |
| End: tfdiags.SourcePos{Line: 1, Column: 1}, |
| }, |
| }, |
| "undeclared3": { |
| Value: cty.StringVal("3"), |
| SourceType: terraform.ValueFromNamedFile, |
| SourceRange: tfdiags.SourceRange{ |
| Filename: "fake.tfvars", |
| Start: tfdiags.SourcePos{Line: 1, Column: 1}, |
| End: tfdiags.SourcePos{Line: 1, Column: 1}, |
| }, |
| }, |
| "undeclared4": { |
| Value: cty.StringVal("4"), |
| SourceType: terraform.ValueFromNamedFile, |
| SourceRange: tfdiags.SourceRange{ |
| Filename: "fake.tfvars", |
| Start: tfdiags.SourcePos{Line: 1, Column: 1}, |
| End: tfdiags.SourcePos{Line: 1, Column: 1}, |
| }, |
| }, |
| } |
| if diff := cmp.Diff(wantVals, gotVals, cmp.Comparer(cty.Value.RawEquals)); diff != "" { |
| t.Errorf("wrong result\n%s", diff) |
| } |
| }) |
| |
| t.Run("ParseVariableValues", func(t *testing.T) { |
| gotVals, diags := ParseVariableValues(vv, decls) |
| for _, diag := range diags { |
| t.Logf("%s: %s", diag.Description().Summary, diag.Description().Detail) |
| } |
| if got, want := len(diags), 4; got != want { |
| t.Fatalf("wrong number of diagnostics %d; want %d", got, want) |
| } |
| |
| const missingRequired = `No value for required variable` |
| |
| if got, want := diags[0].Description().Summary, undeclSingular; got != want { |
| t.Errorf("wrong summary for diagnostic 0\ngot: %s\nwant: %s", got, want) |
| } |
| if got, want := diags[1].Description().Summary, undeclSingular; got != want { |
| t.Errorf("wrong summary for diagnostic 1\ngot: %s\nwant: %s", got, want) |
| } |
| if got, want := diags[2].Description().Summary, undeclPlural; got != want { |
| t.Errorf("wrong summary for diagnostic 2\ngot: %s\nwant: %s", got, want) |
| } |
| if got, want := diags[2].Description().Detail, "3 other variable(s)"; !strings.Contains(got, want) { |
| t.Errorf("wrong detail for diagnostic 2\ngot: %s\nmust contain: %s", got, want) |
| } |
| if got, want := diags[3].Description().Summary, missingRequired; got != want { |
| t.Errorf("wrong summary for diagnostic 3\ngot: %s\nwant: %s", got, want) |
| } |
| |
| wantVals := terraform.InputValues{ |
| "declared1": { |
| Value: cty.StringVal("5"), |
| SourceType: terraform.ValueFromNamedFile, |
| SourceRange: tfdiags.SourceRange{ |
| Filename: "fake.tfvars", |
| Start: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0}, |
| End: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0}, |
| }, |
| }, |
| "missing1": { |
| Value: cty.DynamicVal, |
| SourceType: terraform.ValueFromConfig, |
| SourceRange: tfdiags.SourceRange{ |
| Filename: "fake.tf", |
| Start: tfdiags.SourcePos{Line: 3, Column: 1, Byte: 0}, |
| End: tfdiags.SourcePos{Line: 3, Column: 1, Byte: 0}, |
| }, |
| }, |
| "missing2": { |
| Value: cty.NilVal, // Terraform Core handles substituting the default |
| SourceType: terraform.ValueFromConfig, |
| SourceRange: tfdiags.SourceRange{ |
| Filename: "fake.tf", |
| Start: tfdiags.SourcePos{Line: 4, Column: 1, Byte: 0}, |
| End: tfdiags.SourcePos{Line: 4, Column: 1, Byte: 0}, |
| }, |
| }, |
| } |
| if diff := cmp.Diff(wantVals, gotVals, cmp.Comparer(cty.Value.RawEquals)); diff != "" { |
| t.Errorf("wrong result\n%s", diff) |
| } |
| }) |
| } |
| |
| type testUnparsedVariableValue string |
| |
| func (v testUnparsedVariableValue) ParseVariableValue(mode configs.VariableParsingMode) (*terraform.InputValue, tfdiags.Diagnostics) { |
| return &terraform.InputValue{ |
| Value: cty.StringVal(string(v)), |
| SourceType: terraform.ValueFromNamedFile, |
| SourceRange: tfdiags.SourceRange{ |
| Filename: "fake.tfvars", |
| Start: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0}, |
| End: tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0}, |
| }, |
| }, nil |
| } |