github.com/hairyhenderson/gomplate/v4@v4.0.0-pre-2.0.20240520121557-362f058f0c93/gomplate_test.go (about) 1 package gomplate 2 3 import ( 4 "bytes" 5 "context" 6 "os" 7 "path/filepath" 8 "testing" 9 "text/template" 10 11 "github.com/hairyhenderson/gomplate/v4/aws" 12 "github.com/hairyhenderson/gomplate/v4/conv" 13 "github.com/hairyhenderson/gomplate/v4/data" 14 "github.com/hairyhenderson/gomplate/v4/env" 15 "github.com/hairyhenderson/gomplate/v4/internal/parsers" 16 17 "github.com/stretchr/testify/assert" 18 "github.com/stretchr/testify/require" 19 ) 20 21 func testTemplate(t *testing.T, tr *Renderer, tmpl string) string { 22 t.Helper() 23 24 var out bytes.Buffer 25 err := tr.Render(context.Background(), "testtemplate", tmpl, &out) 26 require.NoError(t, err) 27 28 return out.String() 29 } 30 31 func TestGetenvTemplates(t *testing.T) { 32 tr := NewRenderer(Options{ 33 Funcs: template.FuncMap{ 34 "getenv": env.Getenv, 35 "bool": conv.ToBool, 36 }, 37 }) 38 assert.Empty(t, testTemplate(t, tr, `{{getenv "BLAHBLAHBLAH"}}`)) 39 assert.Equal(t, os.Getenv("USER"), testTemplate(t, tr, `{{getenv "USER"}}`)) 40 assert.Equal(t, "default value", testTemplate(t, tr, `{{getenv "BLAHBLAHBLAH" "default value"}}`)) 41 } 42 43 func TestBoolTemplates(t *testing.T) { 44 g := NewRenderer(Options{ 45 Funcs: template.FuncMap{ 46 "bool": conv.ToBool, 47 }, 48 }) 49 assert.Equal(t, "true", testTemplate(t, g, `{{bool "true"}}`)) 50 assert.Equal(t, "false", testTemplate(t, g, `{{bool "false"}}`)) 51 assert.Equal(t, "false", testTemplate(t, g, `{{bool "foo"}}`)) 52 assert.Equal(t, "false", testTemplate(t, g, `{{bool ""}}`)) 53 } 54 55 func TestEc2MetaTemplates(t *testing.T) { 56 createGomplate := func(data map[string]string, region string) *Renderer { 57 ec2meta := aws.MockEC2Meta(data, nil, region) 58 return NewRenderer(Options{Funcs: template.FuncMap{"ec2meta": ec2meta.Meta}}) 59 } 60 61 g := createGomplate(nil, "") 62 assert.Equal(t, "", testTemplate(t, g, `{{ec2meta "foo"}}`)) 63 assert.Equal(t, "default", testTemplate(t, g, `{{ec2meta "foo" "default"}}`)) 64 65 g = createGomplate(map[string]string{"instance-id": "i-1234"}, "") 66 assert.Equal(t, "i-1234", testTemplate(t, g, `{{ec2meta "instance-id"}}`)) 67 assert.Equal(t, "i-1234", testTemplate(t, g, `{{ec2meta "instance-id" "default"}}`)) 68 } 69 70 func TestEc2MetaTemplates_WithJSON(t *testing.T) { 71 ec2meta := aws.MockEC2Meta(map[string]string{"obj": `"foo": "bar"`}, map[string]string{"obj": `"foo": "baz"`}, "") 72 73 g := NewRenderer(Options{ 74 Funcs: template.FuncMap{ 75 "ec2meta": ec2meta.Meta, 76 "ec2dynamic": ec2meta.Dynamic, 77 "json": parsers.JSON, 78 }, 79 }) 80 81 assert.Equal(t, "bar", testTemplate(t, g, `{{ (ec2meta "obj" | json).foo }}`)) 82 assert.Equal(t, "baz", testTemplate(t, g, `{{ (ec2dynamic "obj" | json).foo }}`)) 83 } 84 85 func TestJSONArrayTemplates(t *testing.T) { 86 g := NewRenderer(Options{ 87 Funcs: template.FuncMap{ 88 "jsonArray": parsers.JSONArray, 89 }, 90 }) 91 92 assert.Equal(t, "[foo bar]", testTemplate(t, g, `{{jsonArray "[\"foo\",\"bar\"]"}}`)) 93 assert.Equal(t, "bar", testTemplate(t, g, `{{ index (jsonArray "[\"foo\",\"bar\"]") 1 }}`)) 94 } 95 96 func TestYAMLTemplates(t *testing.T) { 97 g := NewRenderer(Options{ 98 Funcs: template.FuncMap{ 99 "yaml": parsers.YAML, 100 "yamlArray": parsers.YAMLArray, 101 }, 102 }) 103 104 assert.Equal(t, "bar", testTemplate(t, g, `{{(yaml "foo: bar").foo}}`)) 105 assert.Equal(t, "[foo bar]", testTemplate(t, g, `{{yamlArray "- foo\n- bar\n"}}`)) 106 assert.Equal(t, "bar", testTemplate(t, g, `{{ index (yamlArray "[\"foo\",\"bar\"]") 1 }}`)) 107 } 108 109 func TestHasTemplate(t *testing.T) { 110 g := NewRenderer(Options{ 111 Funcs: template.FuncMap{ 112 "yaml": parsers.YAML, 113 "has": conv.Has, 114 }, 115 }) 116 assert.Equal(t, "true", testTemplate(t, g, `{{has ("foo:\n bar: true" | yaml) "foo"}}`)) 117 assert.Equal(t, "true", testTemplate(t, g, `{{has ("foo:\n bar: true" | yaml).foo "bar"}}`)) 118 assert.Equal(t, "false", testTemplate(t, g, `{{has ("foo: true" | yaml) "bah"}}`)) 119 tmpl := `{{- $data := yaml "foo: bar\nbaz: qux\n" }} 120 {{- if (has $data "baz") }} 121 {{- $data.baz }} 122 {{- end }}` 123 assert.Equal(t, "qux", testTemplate(t, g, tmpl)) 124 tmpl = `{{- $data := yaml "foo: bar\nbaz: qux\n" }} 125 {{- if (has $data "quux") }} 126 {{- $data.quux }} 127 {{- else }} 128 {{- $data.foo }} 129 {{- end }}` 130 assert.Equal(t, "bar", testTemplate(t, g, tmpl)) 131 } 132 133 func TestMissingKey(t *testing.T) { 134 tests := map[string]struct { 135 MissingKey string 136 ExpectedOut string 137 }{ 138 "missing-key = zero": {MissingKey: "zero", ExpectedOut: "<no value>"}, 139 "missing-key = invalid": {MissingKey: "invalid", ExpectedOut: "<no value>"}, 140 "missing-key = default": {MissingKey: "default", ExpectedOut: "<no value>"}, 141 } 142 for name, tt := range tests { 143 t.Run(name, func(t *testing.T) { 144 g := NewRenderer(Options{ 145 MissingKey: tt.MissingKey, 146 }) 147 tmpl := `{{ .name }}` 148 assert.Equal(t, tt.ExpectedOut, testTemplate(t, g, tmpl)) 149 }) 150 } 151 } 152 153 func TestCustomDelim(t *testing.T) { 154 g := NewRenderer(Options{ 155 LDelim: "[", 156 RDelim: "]", 157 }) 158 assert.Equal(t, "hi", testTemplate(t, g, `[print "hi"]`)) 159 } 160 161 func TestRunTemplates(t *testing.T) { 162 buf := &bytes.Buffer{} 163 config := &Config{Input: "foo", OutputFiles: []string{"-"}, Out: buf} 164 err := RunTemplates(config) 165 require.NoError(t, err) 166 assert.Equal(t, "foo", buf.String()) 167 assert.Equal(t, 1, Metrics.TemplatesGathered) 168 assert.Equal(t, 1, Metrics.TemplatesProcessed) 169 assert.Equal(t, 0, Metrics.Errors) 170 } 171 172 func TestSimpleNamer(t *testing.T) { 173 n := simpleNamer("out/") 174 out, err := n(context.Background(), "file") 175 require.NoError(t, err) 176 expected := filepath.FromSlash("out/file") 177 assert.Equal(t, expected, out) 178 } 179 180 func TestMappingNamer(t *testing.T) { 181 ctx := context.Background() 182 tr := &Renderer{ 183 //nolint:staticcheck 184 data: &data.Data{}, 185 funcs: map[string]interface{}{ 186 "foo": func() string { return "foo" }, 187 }, 188 } 189 n := mappingNamer("out/{{ .in }}", tr) 190 out, err := n(ctx, "file") 191 require.NoError(t, err) 192 expected := filepath.FromSlash("out/file") 193 assert.Equal(t, expected, out) 194 195 n = mappingNamer("out/{{ foo }}{{ .in }}", tr) 196 out, err = n(ctx, "file") 197 require.NoError(t, err) 198 expected = filepath.FromSlash("out/foofile") 199 assert.Equal(t, expected, out) 200 }