Implement readDirEntries method

Signed-off-by: vasicvuk <vuk.vasic@asseco-see.rs>
This commit is contained in:
vasicvuk
2022-07-26 16:20:38 +02:00
parent d27765148e
commit 68d7c5f6a4
8 changed files with 194 additions and 71 deletions
+7
View File
@@ -1,9 +1,12 @@
package tmpl
import "io/fs"
type Context struct {
preRender bool
basePath string
readFile func(string) ([]byte, error)
readDir func(string) ([]fs.DirEntry, error)
}
// SetBasePath sets the base path for the template
@@ -14,3 +17,7 @@ func (c *Context) SetBasePath(path string) {
func (c *Context) SetReadFile(f func(string) ([]byte, error)) {
c.readFile = f
}
func (c *Context) SetReadDir(f func(string) ([]fs.DirEntry, error)) {
c.readDir = f
}
+32 -4
View File
@@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"io"
"io/fs"
"os"
"os/exec"
"path/filepath"
@@ -47,6 +48,7 @@ func (c *Context) createFuncMap() template.FuncMap {
"isFile": c.IsFile,
"readFile": c.ReadFile,
"readDir": c.ReadDir,
"readDirEntries": c.ReadDirEntries,
"toYaml": ToYaml,
"fromYaml": FromYaml,
"setValueAtPath": SetValueAtPath,
@@ -69,6 +71,12 @@ func (c *Context) createFuncMap() template.FuncMap {
funcMap["readFile"] = func(string) (string, error) {
return "", nil
}
funcMap["readDir"] = func(string) ([]string, error) {
return []string{}, nil
}
funcMap["readDirEntries"] = func(string) ([]fs.DirEntry, error) {
return []fs.DirEntry{}, nil
}
}
if disableInsecureFeatures {
// disable insecure functions
@@ -78,6 +86,12 @@ func (c *Context) createFuncMap() template.FuncMap {
funcMap["readFile"] = func(string) (string, error) {
return "", DisableInsecureFeaturesErr
}
funcMap["readDir"] = func(string) ([]string, error) {
return nil, DisableInsecureFeaturesErr
}
funcMap["readDirEntries"] = func(string) ([]string, error) {
return nil, DisableInsecureFeaturesErr
}
}
return funcMap
@@ -224,20 +238,34 @@ func (c *Context) ReadDir(path string) ([]string, error) {
contextPath = filepath.Join(c.basePath, path)
}
entries, err := os.ReadDir(contextPath)
entries, err := c.readDir(contextPath)
if err != nil {
return nil, fmt.Errorf("ReadDir %q: %w", contextPath, err)
}
var filenames []string
var paths []string
for _, entry := range entries {
if entry.IsDir() {
continue
}
filenames = append(filenames, filepath.Join(path, entry.Name()))
paths = append(paths, filepath.Join(path, entry.Name()))
}
return filenames, nil
return paths, nil
}
func (c *Context) ReadDirEntries(path string) ([]fs.DirEntry, error) {
var contextPath string
if filepath.IsAbs(path) {
contextPath = path
} else {
contextPath = filepath.Join(c.basePath, path)
}
entries, err := c.readDir(contextPath)
if err != nil {
return nil, fmt.Errorf("ReadDirEntries %q: %w", contextPath, err)
}
return entries, nil
}
func (c *Context) Tpl(text string, data interface{}) (string, error) {
+104 -67
View File
@@ -3,11 +3,11 @@ package tmpl
import (
"encoding/json"
"fmt"
"io/fs"
"path/filepath"
"reflect"
"runtime"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/stretchr/testify/require"
)
@@ -74,12 +74,88 @@ func TestReadFile(t *testing.T) {
return []byte(expected), nil
}}
actual, err := ctx.ReadFile(expectedFilename)
if err != nil {
t.Errorf("unexpected error: %v", err)
require.NoError(t, err)
require.Equal(t, expected, actual)
}
type entry struct {
name string
fType fs.FileMode
isDir bool
}
func (e *entry) Name() string {
return e.name
}
func (e *entry) IsDir() bool {
return e.isDir
}
func (e *entry) Type() fs.FileMode {
return e.fType
}
func (e *entry) Info() (fs.FileInfo, error) {
return nil, fmt.Errorf("You should not call this method")
}
func TestReadDir(t *testing.T) {
result := []fs.DirEntry{
&entry{name: "file1.yaml"},
&entry{name: "file2.yaml"},
&entry{name: "file3.yaml"},
&entry{name: "folder1", isDir: true},
}
if !reflect.DeepEqual(actual, expected) {
t.Errorf("unexpected result: expected=%v, actual=%v", expected, actual)
expectedArrayWindows := []string{
"sampleDirectory\\file1.yaml",
"sampleDirectory\\file2.yaml",
"sampleDirectory\\file3.yaml",
}
expectedArrayUnix := []string{
"sampleDirectory/file1.yaml",
"sampleDirectory/file2.yaml",
"sampleDirectory/file3.yaml",
}
var expectedArray []string
if runtime.GOOS == "windows" {
expectedArray = expectedArrayWindows
} else {
expectedArray = expectedArrayUnix
}
expectedDirname := "sampleDirectory"
ctx := &Context{basePath: ".", readDir: func(dirname string) ([]fs.DirEntry, error) {
if dirname != expectedDirname {
return nil, fmt.Errorf("unexpected filename: expected=%v, actual=%s", expectedDirname, dirname)
}
return result, nil
}}
actual, err := ctx.ReadDir(expectedDirname)
require.NoError(t, err)
require.ElementsMatch(t, expectedArray, actual)
}
func TestReadDirEntries(t *testing.T) {
result := []fs.DirEntry{
&entry{name: "file1.yaml"},
&entry{name: "file2.yaml"},
&entry{name: "file3.yaml"},
&entry{name: "folder1", isDir: true},
}
expectedDirname := "sampleDirectory"
ctx := &Context{basePath: ".", readDir: func(dirname string) ([]fs.DirEntry, error) {
if dirname != expectedDirname {
return nil, fmt.Errorf("unexpected filename: expected=%v, actual=%s", expectedDirname, dirname)
}
return result, nil
}}
actual, err := ctx.ReadDirEntries(expectedDirname)
require.NoError(t, err)
require.ElementsMatch(t, result, actual)
}
func TestReadFile_PassAbsPath(t *testing.T) {
@@ -94,12 +170,8 @@ func TestReadFile_PassAbsPath(t *testing.T) {
return []byte(expected), nil
}}
actual, err := ctx.ReadFile(expectedFilename)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if !reflect.DeepEqual(actual, expected) {
t.Errorf("unexpected result: expected=%v, actual=%v", expected, actual)
}
require.NoError(t, err)
require.Equal(t, actual, expected)
}
func TestToYaml_UnsupportedNestedMapKey(t *testing.T) {
@@ -111,15 +183,8 @@ func TestToYaml_UnsupportedNestedMapKey(t *testing.T) {
},
})
actual, err := ToYaml(vals)
if err == nil {
t.Fatalf("expected error but got none")
} else if err.Error() != "error marshaling into JSON: json: unsupported type: map[interface {}]interface {}" {
t.Fatalf("unexpected error: %v", err)
}
if !reflect.DeepEqual(actual, expected) {
t.Errorf("unexpected result: expected=%v, actual=%v", expected, actual)
}
require.Error(t, err, "error marshaling into JSON: json: unsupported type: map[interface {}]interface {}")
require.Equal(t, expected, actual)
}
func TestToYaml(t *testing.T) {
@@ -133,12 +198,8 @@ func TestToYaml(t *testing.T) {
},
})
actual, err := ToYaml(vals)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if !reflect.DeepEqual(actual, expected) {
t.Errorf("unexpected result: expected=%v, actual=%v", expected, actual)
}
require.NoError(t, err)
require.Equal(t, expected, actual)
}
func TestFromYaml(t *testing.T) {
@@ -152,12 +213,8 @@ func TestFromYaml(t *testing.T) {
},
})
actual, err := FromYaml(raw)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if !reflect.DeepEqual(actual, expected) {
t.Errorf("unexpected result: expected=%v, actual=%v", expected, actual)
}
require.NoError(t, err)
require.Equal(t, expected, actual)
}
func TestFromYamlToJson(t *testing.T) {
@@ -167,18 +224,11 @@ func TestFromYamlToJson(t *testing.T) {
want := `{"foo":{"bar":"BAR"}}`
m, err := FromYaml(input)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
require.NoError(t, err)
got, err := json.Marshal(m)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if d := cmp.Diff(want, string(got)); d != "" {
t.Errorf("unexpected result: want (-), got (+):\n%s", d)
}
require.NoError(t, err)
require.Equal(t, string(got), want)
}
func TestSetValueAtPath_OneComponent(t *testing.T) {
@@ -189,12 +239,8 @@ func TestSetValueAtPath_OneComponent(t *testing.T) {
"foo": "FOO",
}
actual, err := SetValueAtPath("foo", "FOO", input)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if !reflect.DeepEqual(actual, expected) {
t.Errorf("unexpected result: expected=%v, actual=%v", expected, actual)
}
require.NoError(t, err)
require.Equal(t, expected, actual)
}
func TestSetValueAtPath_TwoComponents(t *testing.T) {
@@ -209,12 +255,8 @@ func TestSetValueAtPath_TwoComponents(t *testing.T) {
},
}
actual, err := SetValueAtPath("foo.bar", "FOO_BAR", input)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if !reflect.DeepEqual(actual, expected) {
t.Errorf("unexpected result: expected=%v, actual=%v", expected, actual)
}
require.NoError(t, err)
require.Equal(t, expected, actual)
}
func TestTpl(t *testing.T) {
@@ -224,12 +266,8 @@ func TestTpl(t *testing.T) {
`
ctx := &Context{basePath: "."}
actual, err := ctx.Tpl(text, map[string]interface{}{"foo": "FOO"})
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if !reflect.DeepEqual(actual, expected) {
t.Errorf("unexpected result: expected=%v, actual=%v", expected, actual)
}
require.NoError(t, err)
require.Equal(t, expected, actual)
}
func TestRequired(t *testing.T) {
@@ -266,13 +304,12 @@ func TestRequired(t *testing.T) {
testCase := tt
t.Run(testCase.name, func(t *testing.T) {
got, err := Required(testCase.args.warn, testCase.args.val)
if (err != nil) != testCase.wantErr {
t.Errorf("Required() error = %v, wantErr %v", err, testCase.wantErr)
return
}
if !reflect.DeepEqual(got, testCase.want) {
t.Errorf("Required() got = %v, want %v", got, testCase.want)
if testCase.wantErr {
require.Error(t, err)
} else {
require.NoError(t, err)
}
require.Equal(t, testCase.want, got)
})
}
}