func TestRunDiff(t *testing.T) { path, err := renderFixtures("") if err != nil { t.Errorf("unexpected error: %s", err) } defer os.RemoveAll(path) var expectedOut bytes.Buffer for _, fixture := range fixtures { if len(fixture.diff) > 0 { expectedOut.WriteString( regexp.QuoteMeta( fmt.Sprintf("diff a/%s/%s b/%s/%s\n", path, fixture.filename, path, fixture.filename), ), ) // Need to use regex to ignore datetimes in diff. expectedOut.WriteString(`--- .+?\n`) expectedOut.WriteString(`\+\+\+ .+?\n`) expectedOut.WriteString(regexp.QuoteMeta(string(fixture.diff))) } } expectedOutString := testhelper.Unix2dos(expectedOut.String()) _, stdout := mockIO() err = Run( []string{path}, fixtureExtensions, nil, stdout, Options{ Diff: true, }, ) if err != nil { t.Errorf("unexpected error: %s", err) } if !regexp.MustCompile(expectedOutString).Match(stdout.Bytes()) { t.Errorf("stdout want match:\n%s\ngot:\n%q", expectedOutString, stdout) } }
func TestDecode_interface(t *testing.T) { cases := []struct { File string Err bool Out interface{} }{ { "basic.hcl", false, map[string]interface{}{ "foo": "bar", "bar": "${file(\"bing/bong.txt\")}", }, }, { "basic_squish.hcl", false, map[string]interface{}{ "foo": "bar", "bar": "${file(\"bing/bong.txt\")}", "foo-bar": "baz", }, }, { "empty.hcl", false, map[string]interface{}{ "resource": []map[string]interface{}{ map[string]interface{}{ "foo": []map[string]interface{}{ map[string]interface{}{}, }, }, }, }, }, { "tfvars.hcl", false, map[string]interface{}{ "regularvar": "Should work", "map.key1": "Value", "map.key2": "Other value", }, }, { "escape.hcl", false, map[string]interface{}{ "foo": "bar\"baz\\n", "qux": "back\\slash", "bar": "new\nline", "qax": `slash\:colon`, "nested": `${HH\:mm\:ss}`, "nestedquotes": `${"\"stringwrappedinquotes\""}`, }, }, { "float.hcl", false, map[string]interface{}{ "a": 1.02, }, }, { "multiline_bad.hcl", true, nil, }, { "multiline_no_marker.hcl", true, nil, }, { "multiline.hcl", false, map[string]interface{}{"foo": testhelper.Unix2dos("bar\nbaz\n")}, }, { "multiline_indented.hcl", false, map[string]interface{}{"foo": testhelper.Unix2dos(" bar\n baz\n")}, }, { "multiline_no_hanging_indent.hcl", false, map[string]interface{}{"foo": testhelper.Unix2dos(" baz\n bar\n foo\n")}, }, { "multiline_no_eof.hcl", false, map[string]interface{}{"foo": testhelper.Unix2dos("bar\nbaz\n"), "key": "value"}, }, { "multiline.json", false, map[string]interface{}{"foo": "bar\nbaz"}, }, { "null_strings.json", false, map[string]interface{}{ "module": []map[string]interface{}{ map[string]interface{}{ "app": []map[string]interface{}{ map[string]interface{}{"foo": ""}, }, }, }, }, }, { "scientific.json", false, map[string]interface{}{ "a": 1e-10, "b": 1e+10, "c": 1e10, "d": 1.2e-10, "e": 1.2e+10, "f": 1.2e10, }, }, { "scientific.hcl", false, map[string]interface{}{ "a": 1e-10, "b": 1e+10, "c": 1e10, "d": 1.2e-10, "e": 1.2e+10, "f": 1.2e10, }, }, { "terraform_heroku.hcl", false, map[string]interface{}{ "name": "terraform-test-app", "config_vars": []map[string]interface{}{ map[string]interface{}{ "FOO": "bar", }, }, }, }, { "structure_multi.hcl", false, map[string]interface{}{ "foo": []map[string]interface{}{ map[string]interface{}{ "baz": []map[string]interface{}{ map[string]interface{}{"key": 7}, }, }, map[string]interface{}{ "bar": []map[string]interface{}{ map[string]interface{}{"key": 12}, }, }, }, }, }, { "structure_multi.json", false, map[string]interface{}{ "foo": []map[string]interface{}{ map[string]interface{}{ "baz": []map[string]interface{}{ map[string]interface{}{"key": 7}, }, }, map[string]interface{}{ "bar": []map[string]interface{}{ map[string]interface{}{"key": 12}, }, }, }, }, }, { "structure_list.hcl", false, map[string]interface{}{ "foo": []map[string]interface{}{ map[string]interface{}{ "key": 7, }, map[string]interface{}{ "key": 12, }, }, }, }, { "structure_list.json", false, map[string]interface{}{ "foo": []map[string]interface{}{ map[string]interface{}{ "key": 7, }, map[string]interface{}{ "key": 12, }, }, }, }, { "structure_list_deep.json", false, map[string]interface{}{ "bar": []map[string]interface{}{ map[string]interface{}{ "foo": []map[string]interface{}{ map[string]interface{}{ "name": "terraform_example", "ingress": []map[string]interface{}{ map[string]interface{}{ "from_port": 22, }, map[string]interface{}{ "from_port": 80, }, }, }, }, }, }, }, }, { "nested_block_comment.hcl", false, map[string]interface{}{ "bar": "value", }, }, { "unterminated_block_comment.hcl", true, nil, }, { "unterminated_brace.hcl", true, nil, }, { "nested_provider_bad.hcl", true, // This is not ideal but without significant rework of the decoder // we get a partial result back as well as an error. map[string]interface{}{}, }, { "object_list.json", false, map[string]interface{}{ "resource": []map[string]interface{}{ map[string]interface{}{ "aws_instance": []map[string]interface{}{ map[string]interface{}{ "db": []map[string]interface{}{ map[string]interface{}{ "vpc": "foo", "provisioner": []map[string]interface{}{ map[string]interface{}{ "file": []map[string]interface{}{ map[string]interface{}{ "source": "foo", "destination": "bar", }, }, }, }, }, }, }, }, }, }, }, }, } for _, tc := range cases { t.Logf("Testing: %s", tc.File) d, err := ioutil.ReadFile(filepath.Join(fixtureDir, tc.File)) if err != nil { t.Fatalf("err: %s", err) } var out interface{} err = Decode(&out, string(d)) if (err != nil) != tc.Err { t.Fatalf("Input: %s\n\nError: %s", tc.File, err) } if !reflect.DeepEqual(out, tc.Out) { t.Fatalf("Input: %s. Actual, Expected.\n\n%#v\n\n%#v", tc.File, out, tc.Out) } var v interface{} err = Unmarshal(d, &v) if (err != nil) != tc.Err { t.Fatalf("Input: %s\n\nError: %s", tc.File, err) } if !reflect.DeepEqual(v, tc.Out) { t.Fatalf("Input: %s. Actual, Expected.\n\n%#v\n\n%#v", tc.File, out, tc.Out) } } }
func TestDecode_interface(t *testing.T) { cases := []struct { File string Err bool Out interface{} }{ { "basic.hcl", false, map[string]interface{}{ "foo": "bar", "bar": "${file(\"bing/bong.txt\")}", }, }, { "basic_squish.hcl", false, map[string]interface{}{ "foo": "bar", "bar": "${file(\"bing/bong.txt\")}", "foo-bar": "baz", }, }, { "empty.hcl", false, map[string]interface{}{ "resource": []map[string]interface{}{ map[string]interface{}{ "foo": []map[string]interface{}{ map[string]interface{}{}, }, }, }, }, }, { "tfvars.hcl", false, map[string]interface{}{ "regularvar": "Should work", "map.key1": "Value", "map.key2": "Other value", }, }, { "escape.hcl", false, map[string]interface{}{ "foo": "bar\"baz\\n", "qux": "back\\slash", "bar": "new\nline", "qax": `slash\:colon`, "nested": `${HH\\:mm\\:ss}`, "nestedquotes": `${"\"stringwrappedinquotes\""}`, }, }, { "float.hcl", false, map[string]interface{}{ "a": 1.02, }, }, { "multiline_bad.hcl", true, nil, }, { "multiline_literal.hcl", true, nil, }, { "multiline_literal_with_hil.hcl", false, map[string]interface{}{"multiline_literal_with_hil": testhelper.Unix2dos(`${hello world}`)}, }, { "multiline_no_marker.hcl", true, nil, }, { "multiline.hcl", false, map[string]interface{}{"foo": testhelper.Unix2dos("bar\nbaz\n")}, }, { "multiline_indented.hcl", false, map[string]interface{}{"foo": testhelper.Unix2dos(" bar\n baz\n")}, }, { "multiline_no_hanging_indent.hcl", false, map[string]interface{}{"foo": testhelper.Unix2dos(" baz\n bar\n foo\n")}, }, { "multiline_no_eof.hcl", false, map[string]interface{}{"foo": testhelper.Unix2dos("bar\nbaz\n"), "key": "value"}, }, { "multiline.json", false, map[string]interface{}{"foo": "bar\nbaz"}, }, { "null_strings.json", false, map[string]interface{}{ "module": []map[string]interface{}{ map[string]interface{}{ "app": []map[string]interface{}{ map[string]interface{}{"foo": ""}, }, }, }, }, }, { "scientific.json", false, map[string]interface{}{ "a": 1e-10, "b": 1e+10, "c": 1e10, "d": 1.2e-10, "e": 1.2e+10, "f": 1.2e10, }, }, { "scientific.hcl", false, map[string]interface{}{ "a": 1e-10, "b": 1e+10, "c": 1e10, "d": 1.2e-10, "e": 1.2e+10, "f": 1.2e10, }, }, { "terraform_heroku.hcl", false, map[string]interface{}{ "name": "terraform-test-app", "config_vars": []map[string]interface{}{ map[string]interface{}{ "FOO": "bar", }, }, }, }, { "structure_multi.hcl", false, map[string]interface{}{ "foo": []map[string]interface{}{ map[string]interface{}{ "baz": []map[string]interface{}{ map[string]interface{}{"key": 7}, }, }, map[string]interface{}{ "bar": []map[string]interface{}{ map[string]interface{}{"key": 12}, }, }, }, }, }, { "structure_multi.json", false, map[string]interface{}{ "foo": []map[string]interface{}{ map[string]interface{}{ "baz": []map[string]interface{}{ map[string]interface{}{"key": 7}, }, }, map[string]interface{}{ "bar": []map[string]interface{}{ map[string]interface{}{"key": 12}, }, }, }, }, }, { "list_of_maps.hcl", false, map[string]interface{}{ "foo": []interface{}{ map[string]interface{}{"somekey1": "someval1"}, map[string]interface{}{"somekey2": "someval2", "someextrakey": "someextraval"}, }, }, }, { "assign_deep.hcl", false, map[string]interface{}{ "resource": []interface{}{ map[string]interface{}{ "foo": []interface{}{ map[string]interface{}{ "bar": []map[string]interface{}{ map[string]interface{}{}}}}}}}, }, { "structure_list.hcl", false, map[string]interface{}{ "foo": []map[string]interface{}{ map[string]interface{}{ "key": 7, }, map[string]interface{}{ "key": 12, }, }, }, }, { "structure_list.json", false, map[string]interface{}{ "foo": []map[string]interface{}{ map[string]interface{}{ "key": 7, }, map[string]interface{}{ "key": 12, }, }, }, }, { "structure_list_deep.json", false, map[string]interface{}{ "bar": []map[string]interface{}{ map[string]interface{}{ "foo": []map[string]interface{}{ map[string]interface{}{ "name": "terraform_example", "ingress": []map[string]interface{}{ map[string]interface{}{ "from_port": 22, }, map[string]interface{}{ "from_port": 80, }, }, }, }, }, }, }, }, { "structure_list_empty.json", false, map[string]interface{}{ "foo": []interface{}{}, }, }, { "nested_block_comment.hcl", false, map[string]interface{}{ "bar": "value", }, }, { "unterminated_block_comment.hcl", true, nil, }, { "unterminated_brace.hcl", true, nil, }, { "nested_provider_bad.hcl", true, nil, }, { "object_list.json", false, map[string]interface{}{ "resource": []map[string]interface{}{ map[string]interface{}{ "aws_instance": []map[string]interface{}{ map[string]interface{}{ "db": []map[string]interface{}{ map[string]interface{}{ "vpc": "foo", "provisioner": []map[string]interface{}{ map[string]interface{}{ "file": []map[string]interface{}{ map[string]interface{}{ "source": "foo", "destination": "bar", }, }, }, }, }, }, }, }, }, }, }, }, // Terraform GH-8295 sanity test that basic decoding into // interface{} works. { "terraform_variable_invalid.json", false, map[string]interface{}{ "variable": []map[string]interface{}{ map[string]interface{}{ "whatever": "abc123", }, }, }, }, { "interpolate.json", false, map[string]interface{}{ "default": `${replace("europe-west", "-", " ")}`, }, }, { "block_assign.hcl", true, nil, }, { "escape_backslash.hcl", false, map[string]interface{}{ "output": []map[string]interface{}{ map[string]interface{}{ "one": `${replace(var.sub_domain, ".", "\\.")}`, "two": `${replace(var.sub_domain, ".", "\\\\.")}`, "many": `${replace(var.sub_domain, ".", "\\\\\\\\.")}`, }, }, }, }, { "git_crypt.hcl", true, nil, }, } for _, tc := range cases { t.Logf("Testing: %s", tc.File) d, err := ioutil.ReadFile(filepath.Join(fixtureDir, tc.File)) if err != nil { t.Fatalf("err: %s", err) } var out interface{} err = Decode(&out, string(d)) if (err != nil) != tc.Err { t.Fatalf("Input: %s\n\nError: %s", tc.File, err) } if !reflect.DeepEqual(out, tc.Out) { t.Fatalf("Input: %s. Actual, Expected.\n\n%#v\n\n%#v", tc.File, out, tc.Out) } var v interface{} err = Unmarshal(d, &v) if (err != nil) != tc.Err { t.Fatalf("Input: %s\n\nError: %s", tc.File, err) } if !reflect.DeepEqual(v, tc.Out) { t.Fatalf("Input: %s. Actual, Expected.\n\n%#v\n\n%#v", tc.File, out, tc.Out) } } }