Add Files action to template context. (closes #1198) (#1226)

* Add Files action to template context. (#1198)

* Fixes to testFiles().

- Set os.ModePerm on directories created during test.
- Use filepath.Join() to create directory path.
- Use Fatalf, not Fatal.

* Make additional fixes to test cases.

* Fix test cases to use correct path format.

Dir.Open() in net/http requires '/'-separated paths while
filepath.Join() may produce paths with different separator.

* Remove directory created by test at end of loop.

* Close the FileSystem before returning.

* Initialize names slice to the number of entries.

Also, do not call os.RemoveAll() unless the path to the directory
is a valid one.
This commit is contained in:
ericdreeves 2016-11-01 23:04:53 -05:00 committed by Matt Holt
parent 49cb225cbd
commit 08c17c7c31
2 changed files with 125 additions and 0 deletions

View File

@ -288,3 +288,33 @@ func (c Context) Map(values ...interface{}) (map[string]interface{}, error) {
}
return dict, nil
}
// Files reads and returns a slice of names from the given directory
// relative to the root of Context c.
func (c Context) Files(name string) ([]string, error) {
dir, err := c.Root.Open(path.Clean(name))
if err != nil {
return nil, err
}
defer dir.Close()
stat, err := dir.Stat()
if err != nil {
return nil, err
}
if !stat.IsDir() {
return nil, fmt.Errorf("%v is not a directory", name)
}
dirInfo, err := dir.Readdir(0)
if err != nil {
return nil, err
}
names := make([]string, len(dirInfo))
for i, fileInfo := range dirInfo {
names[i] = fileInfo.Name()
}
return names, nil
}

View File

@ -8,6 +8,7 @@ import (
"net/url"
"os"
"path/filepath"
"reflect"
"strings"
"testing"
"time"
@ -684,3 +685,97 @@ func TestTemplates(t *testing.T) {
}
}
}
func TestFiles(t *testing.T) {
tests := []struct {
fileNames []string
inputBase string
shouldErr bool
verifyErr func(error) bool
}{
// Test 1 - directory and files exist
{
fileNames: []string{"file1", "file2"},
shouldErr: false,
},
// Test 2 - directory exists, no files
{
fileNames: []string{},
shouldErr: false,
},
// Test 3 - file or directory does not exist
{
fileNames: nil,
inputBase: "doesNotExist",
shouldErr: true,
verifyErr: os.IsNotExist,
},
// Test 4 - directory and files exist, but path to a file
{
fileNames: []string{"file1", "file2"},
inputBase: "file1",
shouldErr: true,
verifyErr: func(err error) bool {
return strings.HasSuffix(err.Error(), "is not a directory")
},
},
// Test 5 - try to leave Context Root
{
fileNames: nil,
inputBase: filepath.Join("..", "..", "..", "..", "..", "etc"),
shouldErr: true,
verifyErr: os.IsNotExist,
},
}
for i, test := range tests {
context := getContextOrFail(t)
testPrefix := getTestPrefix(i + 1)
var dirPath string
var err error
// Create directory / files from test case.
if test.fileNames != nil {
dirPath, err = ioutil.TempDir(fmt.Sprintf("%s", context.Root), "caddy_test")
if err != nil {
t.Fatalf(testPrefix+"Expected no error creating directory, got: '%s'", err.Error())
}
for _, name := range test.fileNames {
absFilePath := filepath.Join(dirPath, name)
if err = ioutil.WriteFile(absFilePath, []byte(""), os.ModePerm); err != nil {
t.Fatalf(testPrefix+"Expected no error creating file, got: '%s'", err.Error())
}
}
}
// Perform test case.
input := filepath.ToSlash(filepath.Join(filepath.Base(dirPath), test.inputBase))
actual, err := context.Files(input)
if err != nil {
if !test.shouldErr {
t.Errorf(testPrefix+"Expected no error, got: '%s'", err.Error())
} else if !test.verifyErr(err) {
t.Errorf(testPrefix+"Could not verify error content, got: '%s'", err.Error())
}
} else if test.shouldErr {
t.Errorf(testPrefix + "Expected error but had none")
} else {
numFiles := len(test.fileNames)
// reflect.DeepEqual does not consider two empty slices to be equal
if numFiles == 0 && len(actual) != 0 {
t.Errorf(testPrefix+"Expected files %v, got: %v",
test.fileNames, actual)
} else if numFiles > 0 && !reflect.DeepEqual(test.fileNames, actual) {
t.Errorf(testPrefix+"Expected files %v, got: %v",
test.fileNames, actual)
}
}
if dirPath != "" {
if err := os.RemoveAll(dirPath); err != nil && !os.IsNotExist(err) {
t.Fatalf(testPrefix+"Expected no error removing directory, got: '%s'", err.Error())
}
}
}
}