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  }