Example #1
0
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)
	}
}
Example #2
0
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)
		}
	}
}
Example #3
0
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)
		}
	}
}