github.com/wuhuizuo/gomplate@v3.5.0+incompatible/gomplate_test.go (about) 1 package gomplate 2 3 import ( 4 "bytes" 5 "io" 6 "net/http/httptest" 7 "os" 8 "path/filepath" 9 "testing" 10 11 "github.com/spf13/afero" 12 13 "text/template" 14 15 "github.com/hairyhenderson/gomplate/aws" 16 "github.com/hairyhenderson/gomplate/conv" 17 "github.com/hairyhenderson/gomplate/data" 18 "github.com/hairyhenderson/gomplate/env" 19 "github.com/stretchr/testify/assert" 20 ) 21 22 // like ioutil.NopCloser(), except for io.WriteClosers... 23 type nopWCloser struct { 24 io.Writer 25 } 26 27 func (n *nopWCloser) Close() error { 28 return nil 29 } 30 31 func testTemplate(g *gomplate, tmpl string) string { 32 var out bytes.Buffer 33 err := g.runTemplate(&tplate{name: "testtemplate", contents: tmpl, target: &out}) 34 if err != nil { 35 panic(err) 36 } 37 return out.String() 38 } 39 40 func TestGetenvTemplates(t *testing.T) { 41 g := &gomplate{ 42 funcMap: template.FuncMap{ 43 "getenv": env.Getenv, 44 "bool": conv.Bool, 45 }, 46 } 47 assert.Empty(t, testTemplate(g, `{{getenv "BLAHBLAHBLAH"}}`)) 48 assert.Equal(t, os.Getenv("USER"), testTemplate(g, `{{getenv "USER"}}`)) 49 assert.Equal(t, "default value", testTemplate(g, `{{getenv "BLAHBLAHBLAH" "default value"}}`)) 50 } 51 52 func TestBoolTemplates(t *testing.T) { 53 g := &gomplate{ 54 funcMap: template.FuncMap{ 55 "bool": conv.Bool, 56 }, 57 } 58 assert.Equal(t, "true", testTemplate(g, `{{bool "true"}}`)) 59 assert.Equal(t, "false", testTemplate(g, `{{bool "false"}}`)) 60 assert.Equal(t, "false", testTemplate(g, `{{bool "foo"}}`)) 61 assert.Equal(t, "false", testTemplate(g, `{{bool ""}}`)) 62 } 63 64 func TestEc2MetaTemplates(t *testing.T) { 65 createGomplate := func(status int, body string) (*gomplate, *httptest.Server) { 66 server, ec2meta := aws.MockServer(status, body) 67 return &gomplate{funcMap: template.FuncMap{"ec2meta": ec2meta.Meta}}, server 68 } 69 70 g, s := createGomplate(404, "") 71 defer s.Close() 72 assert.Equal(t, "", testTemplate(g, `{{ec2meta "foo"}}`)) 73 assert.Equal(t, "default", testTemplate(g, `{{ec2meta "foo" "default"}}`)) 74 75 s.Close() 76 g, s = createGomplate(200, "i-1234") 77 defer s.Close() 78 assert.Equal(t, "i-1234", testTemplate(g, `{{ec2meta "instance-id"}}`)) 79 assert.Equal(t, "i-1234", testTemplate(g, `{{ec2meta "instance-id" "default"}}`)) 80 } 81 82 func TestEc2MetaTemplates_WithJSON(t *testing.T) { 83 server, ec2meta := aws.MockServer(200, `{"foo":"bar"}`) 84 defer server.Close() 85 g := &gomplate{ 86 funcMap: template.FuncMap{ 87 "ec2meta": ec2meta.Meta, 88 "ec2dynamic": ec2meta.Dynamic, 89 "json": data.JSON, 90 }, 91 } 92 93 assert.Equal(t, "bar", testTemplate(g, `{{ (ec2meta "obj" | json).foo }}`)) 94 assert.Equal(t, "bar", testTemplate(g, `{{ (ec2dynamic "obj" | json).foo }}`)) 95 } 96 97 func TestJSONArrayTemplates(t *testing.T) { 98 g := &gomplate{ 99 funcMap: template.FuncMap{ 100 "jsonArray": data.JSONArray, 101 }, 102 } 103 104 assert.Equal(t, "[foo bar]", testTemplate(g, `{{jsonArray "[\"foo\",\"bar\"]"}}`)) 105 assert.Equal(t, "bar", testTemplate(g, `{{ index (jsonArray "[\"foo\",\"bar\"]") 1 }}`)) 106 } 107 108 func TestYAMLTemplates(t *testing.T) { 109 g := &gomplate{ 110 funcMap: template.FuncMap{ 111 "yaml": data.YAML, 112 "yamlArray": data.YAMLArray, 113 }, 114 } 115 116 assert.Equal(t, "bar", testTemplate(g, `{{(yaml "foo: bar").foo}}`)) 117 assert.Equal(t, "[foo bar]", testTemplate(g, `{{yamlArray "- foo\n- bar\n"}}`)) 118 assert.Equal(t, "bar", testTemplate(g, `{{ index (yamlArray "[\"foo\",\"bar\"]") 1 }}`)) 119 } 120 121 func TestSliceTemplates(t *testing.T) { 122 g := &gomplate{ 123 funcMap: template.FuncMap{ 124 "slice": conv.Slice, 125 }, 126 } 127 assert.Equal(t, "foo", testTemplate(g, `{{index (slice "foo") 0}}`)) 128 assert.Equal(t, `[foo bar 42]`, testTemplate(g, `{{slice "foo" "bar" 42}}`)) 129 assert.Equal(t, `helloworld`, testTemplate(g, `{{range slice "hello" "world"}}{{.}}{{end}}`)) 130 } 131 132 func TestHasTemplate(t *testing.T) { 133 g := &gomplate{ 134 funcMap: template.FuncMap{ 135 "yaml": data.YAML, 136 "has": conv.Has, 137 }, 138 } 139 assert.Equal(t, "true", testTemplate(g, `{{has ("foo:\n bar: true" | yaml) "foo"}}`)) 140 assert.Equal(t, "true", testTemplate(g, `{{has ("foo:\n bar: true" | yaml).foo "bar"}}`)) 141 assert.Equal(t, "false", testTemplate(g, `{{has ("foo: true" | yaml) "bah"}}`)) 142 tmpl := `{{- $data := yaml "foo: bar\nbaz: qux\n" }} 143 {{- if (has $data "baz") }} 144 {{- $data.baz }} 145 {{- end }}` 146 assert.Equal(t, "qux", testTemplate(g, tmpl)) 147 tmpl = `{{- $data := yaml "foo: bar\nbaz: qux\n" }} 148 {{- if (has $data "quux") }} 149 {{- $data.quux }} 150 {{- else }} 151 {{- $data.foo }} 152 {{- end }}` 153 assert.Equal(t, "bar", testTemplate(g, tmpl)) 154 } 155 156 func TestCustomDelim(t *testing.T) { 157 g := &gomplate{ 158 leftDelim: "[", 159 rightDelim: "]", 160 funcMap: template.FuncMap{}, 161 } 162 assert.Equal(t, "hi", testTemplate(g, `[print "hi"]`)) 163 } 164 165 func TestRunTemplates(t *testing.T) { 166 defer func() { Stdout = os.Stdout }() 167 buf := &bytes.Buffer{} 168 Stdout = &nopWCloser{buf} 169 config := &Config{Input: "foo", OutputFiles: []string{"-"}} 170 err := RunTemplates(config) 171 assert.NoError(t, err) 172 assert.Equal(t, "foo", buf.String()) 173 assert.Equal(t, 1, Metrics.TemplatesGathered) 174 assert.Equal(t, 1, Metrics.TemplatesProcessed) 175 assert.Equal(t, 0, Metrics.Errors) 176 } 177 178 func TestParseTemplateArg(t *testing.T) { 179 fs = afero.NewMemMapFs() 180 afero.WriteFile(fs, "foo.t", []byte("hi"), 0600) 181 _ = fs.MkdirAll("dir", 0755) 182 afero.WriteFile(fs, "dir/foo.t", []byte("hi"), 0600) 183 afero.WriteFile(fs, "dir/bar.t", []byte("hi"), 0600) 184 185 testdata := []struct { 186 arg string 187 expected map[string]string 188 err bool 189 }{ 190 {"bogus.t", nil, true}, 191 {"foo.t", map[string]string{"foo.t": "foo.t"}, false}, 192 {"foo=foo.t", map[string]string{"foo": "foo.t"}, false}, 193 {"dir/foo.t", map[string]string{"dir/foo.t": "dir/foo.t"}, false}, 194 {"foo=dir/foo.t", map[string]string{"foo": "dir/foo.t"}, false}, 195 {"dir/", map[string]string{"dir/foo.t": "dir/foo.t", "dir/bar.t": "dir/bar.t"}, false}, 196 {"t=dir/", map[string]string{"t/foo.t": "dir/foo.t", "t/bar.t": "dir/bar.t"}, false}, 197 } 198 199 for _, d := range testdata { 200 nested := templateAliases{} 201 err := parseTemplateArg(d.arg, nested) 202 if d.err { 203 assert.Error(t, err, d.arg) 204 } else { 205 assert.NoError(t, err, d.arg) 206 assert.Equal(t, templateAliases(d.expected), nested, d.arg) 207 } 208 } 209 } 210 211 func TestParseTemplateArgs(t *testing.T) { 212 fs = afero.NewMemMapFs() 213 afero.WriteFile(fs, "foo.t", []byte("hi"), 0600) 214 _ = fs.MkdirAll("dir", 0755) 215 afero.WriteFile(fs, "dir/foo.t", []byte("hi"), 0600) 216 afero.WriteFile(fs, "dir/bar.t", []byte("hi"), 0600) 217 218 args := []string{"foo.t", 219 "foo=foo.t", 220 "bar=dir/foo.t", 221 "dir/", 222 "t=dir/", 223 } 224 225 expected := map[string]string{ 226 "foo.t": "foo.t", 227 "foo": "foo.t", 228 "bar": "dir/foo.t", 229 "dir/foo.t": "dir/foo.t", 230 "dir/bar.t": "dir/bar.t", 231 "t/foo.t": "dir/foo.t", 232 "t/bar.t": "dir/bar.t", 233 } 234 235 nested, err := parseTemplateArgs(args) 236 assert.NoError(t, err) 237 assert.Equal(t, templateAliases(expected), nested) 238 239 _, err = parseTemplateArgs([]string{"bogus.t"}) 240 assert.Error(t, err) 241 } 242 243 func TestSimpleNamer(t *testing.T) { 244 n := simpleNamer("out/") 245 out, err := n("file") 246 assert.NoError(t, err) 247 expected := filepath.FromSlash("out/file") 248 assert.Equal(t, expected, out) 249 } 250 251 func TestMappingNamer(t *testing.T) { 252 g := &gomplate{funcMap: map[string]interface{}{ 253 "foo": func() string { return "foo" }, 254 }} 255 n := mappingNamer("out/{{ .in }}", g) 256 out, err := n("file") 257 assert.NoError(t, err) 258 expected := filepath.FromSlash("out/file") 259 assert.Equal(t, expected, out) 260 261 n = mappingNamer("out/{{ foo }}{{ .in }}", g) 262 out, err = n("file") 263 assert.NoError(t, err) 264 expected = filepath.FromSlash("out/foofile") 265 assert.Equal(t, expected, out) 266 }