github.com/hairyhenderson/gomplate/v4@v4.0.0-pre-2.0.20240520121557-362f058f0c93/internal/tests/integration/inputdir_test.go (about)

     1  package integration
     2  
     3  import (
     4  	"os"
     5  	"testing"
     6  
     7  	"github.com/hairyhenderson/gomplate/v4/internal/iohelpers"
     8  	tassert "github.com/stretchr/testify/assert"
     9  	"gotest.tools/v3/assert"
    10  	"gotest.tools/v3/fs"
    11  )
    12  
    13  func setupInputDirTest(t *testing.T) *fs.Dir {
    14  	tmpDir := fs.NewDir(t, "gomplate-inttests",
    15  		fs.WithFile("config.yml", "one: eins\ntwo: deux\n"),
    16  		fs.WithFile("filemap.json", `{"eins.txt":"uno","deux.txt":"dos","drei.sh":"tres","vier.txt":"quatro"}`),
    17  		fs.WithFile("out.t", `{{- /* .in may contain a directory name - we want to preserve that */ -}}
    18  {{ $f := filepath.Base .in -}}
    19  out/{{ .in | strings.ReplaceAll $f (index .filemap $f) }}.out
    20  `),
    21  		fs.WithDir("in",
    22  			fs.WithFile("eins.txt", `{{ (ds "config").one }}`, fs.WithMode(0o644)),
    23  			fs.WithDir("inner",
    24  				fs.WithFile("deux.txt", `{{ (ds "config").two }}`, fs.WithMode(0o444)),
    25  			),
    26  			fs.WithFile("drei.sh", `#!/bin/sh\necho "hello world"\n`, fs.WithMode(0o755)),
    27  			fs.WithFile("vier.txt", `{{ (ds "config").two }} * {{ (ds "config").two }}`, fs.WithMode(0o544)),
    28  		),
    29  		fs.WithDir("out"),
    30  		fs.WithDir("bad_in",
    31  			fs.WithFile("bad.tmpl", "{{end}}"),
    32  		),
    33  	)
    34  	t.Cleanup(tmpDir.Remove)
    35  
    36  	return tmpDir
    37  }
    38  
    39  func TestInputDir_InputDir(t *testing.T) {
    40  	tmpDir := setupInputDirTest(t)
    41  
    42  	o, e, err := cmd(t,
    43  		"--input-dir", tmpDir.Join("in"),
    44  		"--output-dir", tmpDir.Join("out"),
    45  		"-d", "config="+tmpDir.Join("config.yml"),
    46  	).run()
    47  	assertSuccess(t, o, e, err, "")
    48  
    49  	files, err := os.ReadDir(tmpDir.Join("out"))
    50  	assert.NilError(t, err)
    51  	tassert.Len(t, files, 4)
    52  
    53  	files, err = os.ReadDir(tmpDir.Join("out", "inner"))
    54  	assert.NilError(t, err)
    55  	tassert.Len(t, files, 1)
    56  
    57  	testdata := []struct {
    58  		path    string
    59  		content string
    60  		mode    os.FileMode
    61  	}{
    62  		{tmpDir.Join("out", "eins.txt"), "eins", 0o644},
    63  		{tmpDir.Join("out", "inner", "deux.txt"), "deux", 0o444},
    64  		{tmpDir.Join("out", "drei.sh"), `#!/bin/sh\necho "hello world"\n`, 0o755},
    65  		{tmpDir.Join("out", "vier.txt"), "deux * deux", 0o544},
    66  	}
    67  	for _, v := range testdata {
    68  		info, err := os.Stat(v.path)
    69  		assert.NilError(t, err)
    70  		m := iohelpers.NormalizeFileMode(v.mode)
    71  		assert.Equal(t, m, info.Mode(), v.path)
    72  		content, err := os.ReadFile(v.path)
    73  		assert.NilError(t, err)
    74  		assert.Equal(t, v.content, string(content))
    75  	}
    76  }
    77  
    78  func TestInputDir_InputDirWithModeOverride(t *testing.T) {
    79  	tmpDir := setupInputDirTest(t)
    80  	o, e, err := cmd(t,
    81  		"--input-dir", tmpDir.Join("in"),
    82  		"--output-dir", tmpDir.Join("out"),
    83  		"--chmod", "0601",
    84  		"-d", "config="+tmpDir.Join("config.yml"),
    85  	).run()
    86  	assertSuccess(t, o, e, err, "")
    87  
    88  	files, err := os.ReadDir(tmpDir.Join("out"))
    89  	assert.NilError(t, err)
    90  	tassert.Len(t, files, 4)
    91  
    92  	files, err = os.ReadDir(tmpDir.Join("out", "inner"))
    93  	assert.NilError(t, err)
    94  	tassert.Len(t, files, 1)
    95  
    96  	testdata := []struct {
    97  		path    string
    98  		content string
    99  		mode    os.FileMode
   100  	}{
   101  		{tmpDir.Join("out", "eins.txt"), "eins", 0o601},
   102  		{tmpDir.Join("out", "inner", "deux.txt"), "deux", 0o601},
   103  		{tmpDir.Join("out", "drei.sh"), `#!/bin/sh\necho "hello world"\n`, 0o601},
   104  		{tmpDir.Join("out", "vier.txt"), "deux * deux", 0o601},
   105  	}
   106  	for _, v := range testdata {
   107  		info, err := os.Stat(v.path)
   108  		assert.NilError(t, err)
   109  		m := iohelpers.NormalizeFileMode(v.mode)
   110  		assert.Equal(t, m, info.Mode(), v.path)
   111  		content, err := os.ReadFile(v.path)
   112  		assert.NilError(t, err)
   113  		assert.Equal(t, v.content, string(content))
   114  	}
   115  }
   116  
   117  func TestInputDir_OutputMapInline(t *testing.T) {
   118  	tmpDir := setupInputDirTest(t)
   119  	o, e, err := cmd(t,
   120  		"--input-dir", tmpDir.Join("in"),
   121  		"--output-map", `OUT/{{ strings.ToUpper .in }}`,
   122  		"-d", "config.yml",
   123  	).withDir(tmpDir.Path()).run()
   124  	assertSuccess(t, o, e, err, "")
   125  
   126  	files, err := os.ReadDir(tmpDir.Join("OUT"))
   127  	assert.NilError(t, err)
   128  	tassert.Len(t, files, 4)
   129  
   130  	files, err = os.ReadDir(tmpDir.Join("OUT", "INNER"))
   131  	assert.NilError(t, err)
   132  	tassert.Len(t, files, 1)
   133  
   134  	testdata := []struct {
   135  		path    string
   136  		content string
   137  		mode    os.FileMode
   138  	}{
   139  		{tmpDir.Join("OUT", "EINS.TXT"), "eins", 0o644},
   140  		{tmpDir.Join("OUT", "INNER", "DEUX.TXT"), "deux", 0o444},
   141  		{tmpDir.Join("OUT", "DREI.SH"), `#!/bin/sh\necho "hello world"\n`, 0o755},
   142  		{tmpDir.Join("OUT", "VIER.TXT"), "deux * deux", 0o544},
   143  	}
   144  	for _, v := range testdata {
   145  		info, err := os.Stat(v.path)
   146  		assert.NilError(t, err)
   147  		m := iohelpers.NormalizeFileMode(v.mode)
   148  		assert.Equal(t, m, info.Mode(), v.path)
   149  		content, err := os.ReadFile(v.path)
   150  		assert.NilError(t, err)
   151  		assert.Equal(t, v.content, string(content))
   152  	}
   153  }
   154  
   155  func TestInputDir_OutputMapExternal(t *testing.T) {
   156  	tmpDir := setupInputDirTest(t)
   157  	o, e, err := cmd(t,
   158  		"--input-dir", tmpDir.Join("in"),
   159  		"--output-map", `{{ template "out" . }}`,
   160  		"-t", "out=out.t",
   161  		"-c", "filemap.json",
   162  		"-d", "config.yml",
   163  	).withDir(tmpDir.Path()).run()
   164  	assertSuccess(t, o, e, err, "")
   165  
   166  	files, err := os.ReadDir(tmpDir.Join("out"))
   167  	assert.NilError(t, err)
   168  	tassert.Len(t, files, 4)
   169  
   170  	files, err = os.ReadDir(tmpDir.Join("out", "inner"))
   171  	assert.NilError(t, err)
   172  	tassert.Len(t, files, 1)
   173  
   174  	testdata := []struct {
   175  		path    string
   176  		content string
   177  		mode    os.FileMode
   178  	}{
   179  		{tmpDir.Join("out", "uno.out"), "eins", 0o644},
   180  		{tmpDir.Join("out", "inner", "dos.out"), "deux", 0o444},
   181  		{tmpDir.Join("out", "tres.out"), `#!/bin/sh\necho "hello world"\n`, 0o755},
   182  		{tmpDir.Join("out", "quatro.out"), "deux * deux", 0o544},
   183  	}
   184  	for _, v := range testdata {
   185  		info, err := os.Stat(v.path)
   186  		assert.NilError(t, err)
   187  		m := iohelpers.NormalizeFileMode(v.mode)
   188  		assert.Equal(t, m, info.Mode(), v.path)
   189  		content, err := os.ReadFile(v.path)
   190  		assert.NilError(t, err)
   191  		assert.Equal(t, v.content, string(content))
   192  	}
   193  }
   194  
   195  func TestInputDir_DefaultOutputDir(t *testing.T) {
   196  	tmpDir := setupInputDirTest(t)
   197  	o, e, err := cmd(t,
   198  		"--input-dir", tmpDir.Join("in"),
   199  		"-d", "config="+tmpDir.Join("config.yml"),
   200  	).withDir(tmpDir.Join("out")).run()
   201  	assertSuccess(t, o, e, err, "")
   202  
   203  	files, err := os.ReadDir(tmpDir.Join("out"))
   204  	assert.NilError(t, err)
   205  	tassert.Len(t, files, 4)
   206  
   207  	files, err = os.ReadDir(tmpDir.Join("out", "inner"))
   208  	assert.NilError(t, err)
   209  	tassert.Len(t, files, 1)
   210  
   211  	content, err := os.ReadFile(tmpDir.Join("out", "eins.txt"))
   212  	assert.NilError(t, err)
   213  	assert.Equal(t, "eins", string(content))
   214  
   215  	content, err = os.ReadFile(tmpDir.Join("out", "inner", "deux.txt"))
   216  	assert.NilError(t, err)
   217  	assert.Equal(t, "deux", string(content))
   218  
   219  	content, err = os.ReadFile(tmpDir.Join("out", "drei.sh"))
   220  	assert.NilError(t, err)
   221  	assert.Equal(t, `#!/bin/sh\necho "hello world"\n`, string(content))
   222  
   223  	content, err = os.ReadFile(tmpDir.Join("out", "vier.txt"))
   224  	assert.NilError(t, err)
   225  	assert.Equal(t, `deux * deux`, string(content))
   226  }
   227  
   228  func TestInputDir_ReportsFilenameWithBadInputFile(t *testing.T) {
   229  	tmpDir := setupInputDirTest(t)
   230  	o, _, err := cmd(t,
   231  		"--input-dir", tmpDir.Join("bad_in"),
   232  		"--output-dir", tmpDir.Join("out"),
   233  		"-d", "config="+tmpDir.Join("config.yml"),
   234  	).run()
   235  	assert.ErrorContains(t, err, "bad.tmpl:1: unexpected {{end}}")
   236  	assert.Equal(t, "", o)
   237  }
   238  
   239  func TestInputDir_InputDirCwd(t *testing.T) {
   240  	tmpDir := setupInputDirTest(t)
   241  	o, e, err := cmd(t,
   242  		"--input-dir", ".",
   243  		"--include", "*.txt",
   244  		"--output-map", `{{ .in | strings.ReplaceAll ".txt" ".out" }}`,
   245  		"-d", "config="+tmpDir.Join("config.yml"),
   246  	).withDir(tmpDir.Path()).run()
   247  	assertSuccess(t, o, e, err, "")
   248  
   249  	testdata := []struct {
   250  		path    string
   251  		content string
   252  		mode    os.FileMode
   253  	}{
   254  		{tmpDir.Join("in", "eins.out"), "eins", 0o644},
   255  		{tmpDir.Join("in", "inner", "deux.out"), "deux", 0o444},
   256  		{tmpDir.Join("in", "vier.out"), "deux * deux", 0o544},
   257  	}
   258  	for _, v := range testdata {
   259  		info, err := os.Stat(v.path)
   260  		assert.NilError(t, err)
   261  		m := iohelpers.NormalizeFileMode(v.mode)
   262  		assert.Equal(t, m, info.Mode(), v.path)
   263  		content, err := os.ReadFile(v.path)
   264  		assert.NilError(t, err)
   265  		assert.Equal(t, v.content, string(content))
   266  	}
   267  }