github.com/hairyhenderson/templater@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  }