diff --git a/helpers/path.go b/helpers/path.go index 8230d15c9..0425a5ae3 100644 --- a/helpers/path.go +++ b/helpers/path.go @@ -38,20 +38,21 @@ func MakePath(s string) string { return UnicodeSanitize(strings.Replace(strings.TrimSpace(s), " ", "-", -1)) } -// MakePathToLowerr creates a Unicode santized string, with the spaces replaced, +// MakePathToLower creates a Unicode santized string, with the spaces replaced, // and transformed to lower case. // E.g. Social Media -> social-media func MakePathToLower(s string) string { - return UnicodeSanitize(strings.ToLower(strings.Replace(strings.TrimSpace(s), " ", "-", -1))) + return strings.ToLower(MakePath(s)) } func MakeTitle(inpath string) string { return strings.Replace(strings.TrimSpace(inpath), "-", " ", -1) } -func Sanitize(s string) string { - return sanitizeRegexp.ReplaceAllString(s, "") -} +// unused +//func Sanitize(s string) string { +// return sanitizeRegexp.ReplaceAllString(s, "") +//} func UnicodeSanitize(s string) string { source := []rune(s) @@ -100,12 +101,15 @@ func IsEmpty(path string, fs afero.Fs) (bool, error) { return false, err } if fi.IsDir() { - f, err := fs.Open(path) + f, err := os.Open(path) + // FIX: Resource leak - f.close() should be called here by defer or is missed + // if the err != nil branch is taken. + defer f.Close() if err != nil { return false, err } list, err := f.Readdir(-1) - f.Close() + // f.Close() - see bug fix above return len(list) == 0, nil } else { return fi.Size() == 0, nil diff --git a/helpers/path_test.go b/helpers/path_test.go new file mode 100644 index 000000000..411f72099 --- /dev/null +++ b/helpers/path_test.go @@ -0,0 +1,530 @@ +package helpers + +import ( + "fmt" + "io/ioutil" + "os" + "strings" + "testing" +) + +func TestMakePath(t *testing.T) { + tests := []struct { + input string + expected string + }{ + {" Foo bar ", "Foo-bar"}, + {"Foo.Bar/foo_Bar-Foo", "Foo.Bar/foo_Bar-Foo"}, + {"fOO,bar:foo%bAR", "fOObarfoobAR"}, + {"FOo/BaR.html", "FOo/BaR.html"}, + {"трям/трям", "трям/трям"}, + {"은행", "은행"}, + {"Банковский кассир", "Банковский-кассир"}, + } + + for _, test := range tests { + output := MakePath(test.input) + if output != test.expected { + t.Errorf("Expected %#v, got %#v\n", test.expected, output) + } + } +} + +func TestMakePathToLower(t *testing.T) { + tests := []struct { + input string + expected string + }{ + {" FOO bar ", "foo-bar"}, + {"Foo.Bar/fOO_bAr-Foo", "foo.bar/foo_bar-foo"}, + {"FOO,bar:Foo%Bar", "foobarfoobar"}, + {"foo/BAR.HTML", "foo/bar.html"}, + {"трям/трям", "трям/трям"}, + {"은행", "은행"}, + } + for _, test := range tests { + output := MakePathToLower(test.input) + if output != test.expected { + t.Errorf("Expected %#v, got %#v\n", test.expected, output) + } + } +} + +func TestMakeTitle(t *testing.T) { + type test struct { + input, expected string + } + data := []test{ + {"Make-Title", "Make Title"}, + {"MakeTitle", "MakeTitle"}, + {"make_title", "make_title"}, + } + for i, d := range data { + output := MakeTitle(d.input) + if d.expected != output { + t.Errorf("Test %d failed. Expected %q got %q", i, d.expected, output) + } + } +} + +// +// comment +// +func TestReplaceExtension(t *testing.T) { + type test struct { + input, newext, expected string + } + data := []test{ + // none of these work as you might expect + {"/some/randome/path/file.xml", "html", "/some/randompath/file.html"}, + {"/banana.html", "HTML", "/banana.HTML"}, + {"./banana.html", "xml", "./banana.xml"}, + {"banana/pie/index.html", "xml", "banana/pie/index.xml"}, + {"../pies/fish/index.html", "xml", "../pies/fish/index.xml"}, + // but these all work even though they make no sense! + {"/directory", "ext", "/directory.ext"}, + {"/directory/mydir/", "ext", "/directory/mydir/.ext"}, + {"mydir/", "ext", "mydir/.ext"}, + } + + for i, d := range data { + output := ReplaceExtension(d.input, d.newext) + if d.expected != output { + t.Errorf("Test %d failed. Expected %q got %q", i, d.expected, output) + } + } +} + +func TestDirExists(t *testing.T) { + type test struct { + input string + expected bool + } + + data := []test{ + {".", true}, + {"./", true}, + {"..", true}, + {"../", true}, + {"./..", true}, + {"./../", true}, + {"/tmp", true}, + {"/tmp/", true}, + {"/", true}, + {"/some-really-random-directory-name", false}, + {"/some/really/random/directory/name", false}, + {"./some-really-random-local-directory-name", false}, + {"./some/really/random/local/directory/name", false}, + } + + for i, d := range data { + exists, _ := DirExists(d.input) + if d.expected != exists { + t.Errorf("Test %d failed. Expected %t got %t", i, d.expected, exists) + } + } +} + +func TestIsDir(t *testing.T) { + type test struct { + input string + expected bool + } + data := []test{ + {"./", true}, + {"/", true}, + {"./this-directory-does-not-existi", false}, + {"/this-absolute-directory/does-not-exist", false}, + } + + for i, d := range data { + exists, _ := IsDir(d.input) + if d.expected != exists { + t.Errorf("Test %d failed. Expected %t got %t", i, d.expected, exists) + } + } +} + +func TestIsEmpty(t *testing.T) { + zeroSizedFile, _ := createZeroSizedFileInTempDir() + defer deleteFileInTempDir(zeroSizedFile) + nonZeroSizedFile, _ := createNonZeroSizedFileInTempDir() + defer deleteFileInTempDir(nonZeroSizedFile) + emptyDirectory, _ := createEmptyTempDir() + defer deleteTempDir(emptyDirectory) + nonEmptyZeroLengthFilesDirectory, _ := createTempDirWithZeroLengthFiles() + defer deleteTempDir(nonEmptyZeroLengthFilesDirectory) + nonEmptyNonZeroLengthFilesDirectory, _ := createTempDirWithNonZeroLengthFiles() + defer deleteTempDir(nonEmptyNonZeroLengthFilesDirectory) + nonExistentFile := os.TempDir() + "/this-file-does-not-exist.txt" + nonExistentDir := os.TempDir() + "/this/direcotry/does/not/exist/" + + fileDoesNotExist := fmt.Errorf("%q path does not exist", nonExistentFile) + dirDoesNotExist := fmt.Errorf("%q path does not exist", nonExistentDir) + + type test struct { + input string + expectedResult bool + expectedErr error + } + + data := []test{ + {zeroSizedFile.Name(), true, nil}, + {nonZeroSizedFile.Name(), false, nil}, + {emptyDirectory, true, nil}, + {nonEmptyZeroLengthFilesDirectory, false, nil}, + {nonEmptyNonZeroLengthFilesDirectory, false, nil}, + {nonExistentFile, false, fileDoesNotExist}, + {nonExistentDir, false, dirDoesNotExist}, + } + for i, d := range data { + exists, err := IsEmpty(d.input) + if d.expectedResult != exists { + t.Errorf("Test %d failed. Expected result %t got %t", i, d.expectedResult, exists) + } + if d.expectedErr != nil { + if d.expectedErr.Error() != err.Error() { + t.Errorf("Test %d failed. Expected %q(%#v) got %q(%#v)", i, d.expectedErr, d.expectedErr, err, err) + } + } else { + if d.expectedErr != err { + t.Errorf("Test %d failed. Expected %q(%#v) got %q(%#v)", i, d.expectedErr, d.expectedErr, err, err) + } + } + } +} + +func createZeroSizedFileInTempDir() (*os.File, error) { + filePrefix := "_path_test_" + f, e := ioutil.TempFile("", filePrefix) // dir is os.TempDir() + if e != nil { + // if there was an error no file was created. + // => no requirement to delete the file + return nil, e + } + return f, nil +} + +func createNonZeroSizedFileInTempDir() (*os.File, error) { + f, err := createZeroSizedFileInTempDir() + if err != nil { + // no file ?? + } + byteString := []byte("byteString") + err = ioutil.WriteFile(f.Name(), byteString, 0644) + if err != nil { + // delete the file + deleteFileInTempDir(f) + return nil, err + } + return f, nil +} + +func deleteFileInTempDir(f *os.File) { + err := os.Remove(f.Name()) + if err != nil { + // now what? + } +} + +func createEmptyTempDir() (string, error) { + dirPrefix := "_dir_prefix_" + d, e := ioutil.TempDir("", dirPrefix) // will be in os.TempDir() + if e != nil { + // no directory to delete - it was never created + return "", e + } + return d, nil +} + +func createTempDirWithZeroLengthFiles() (string, error) { + d, dirErr := createEmptyTempDir() + if dirErr != nil { + //now what? + } + filePrefix := "_path_test_" + _, fileErr := ioutil.TempFile(d, filePrefix) // dir is os.TempDir() + if fileErr != nil { + // if there was an error no file was created. + // but we need to remove the directory to clean-up + deleteTempDir(d) + return "", fileErr + } + // the dir now has one, zero length file in it + return d, nil + +} + +func createTempDirWithNonZeroLengthFiles() (string, error) { + d, dirErr := createEmptyTempDir() + if dirErr != nil { + //now what? + } + filePrefix := "_path_test_" + f, fileErr := ioutil.TempFile(d, filePrefix) // dir is os.TempDir() + if fileErr != nil { + // if there was an error no file was created. + // but we need to remove the directory to clean-up + deleteTempDir(d) + return "", fileErr + } + byteString := []byte("byteString") + fileErr = ioutil.WriteFile(f.Name(), byteString, 0644) + if fileErr != nil { + // delete the file + deleteFileInTempDir(f) + // also delete the directory + deleteTempDir(d) + return "", fileErr + } + + // the dir now has one, zero length file in it + return d, nil + +} + +func deleteTempDir(d string) { + err := os.RemoveAll(d) + if err != nil { + // now what? + } +} + +func TestExists(t *testing.T) { + zeroSizedFile, _ := createZeroSizedFileInTempDir() + defer deleteFileInTempDir(zeroSizedFile) + nonZeroSizedFile, _ := createNonZeroSizedFileInTempDir() + defer deleteFileInTempDir(nonZeroSizedFile) + emptyDirectory, _ := createEmptyTempDir() + defer deleteTempDir(emptyDirectory) + nonExistentFile := os.TempDir() + "/this-file-does-not-exist.txt" + nonExistentDir := os.TempDir() + "/this/direcotry/does/not/exist/" + + type test struct { + input string + expectedResult bool + expectedErr error + } + + data := []test{ + {zeroSizedFile.Name(), true, nil}, + {nonZeroSizedFile.Name(), true, nil}, + {emptyDirectory, true, nil}, + {nonExistentFile, false, nil}, + {nonExistentDir, false, nil}, + } + for i, d := range data { + exists, err := Exists(d.input) + if d.expectedResult != exists { + t.Errorf("Test %d failed. Expected result %t got %t", i, d.expectedResult, exists) + } + if d.expectedErr != err { + t.Errorf("Test %d failed. Expected %q got %q", i, d.expectedErr, err) + } + } + +} + +// TestAbsPathify cannot be tested further because it relies on the +// viper.GetString("WorkingDir") which the test cannot know. +// viper.GetString("WorkingDir") should be passed to AbsPathify as a +// parameter. +func TestAbsPathify(t *testing.T) { + type test struct { + input, expected string + } + data := []test{ + {os.TempDir(), os.TempDir()}, + {"/banana/../dir/", "/dir"}, + } + + for i, d := range data { + expected := AbsPathify(d.input) + if d.expected != expected { + t.Errorf("Test %d failed. Expected %q but go %q", i, d.expected, expected) + } + } +} + +func TestFilename(t *testing.T) { + type test struct { + input, expected string + } + data := []test{ + {"index.html", "index"}, + {"./index.html", "index"}, + {"/index.html", "index"}, + {"index", "index"}, + {"/tmp/index.html", "index"}, + {"./filename-no-ext", "filename-no-ext"}, + {"/filename-no-ext", "filename-no-ext"}, + {"filename-no-ext", "filename-no-ext"}, + {"directoy/", ""}, // no filename case?? + {"directory/.hidden.ext", ".hidden"}, + } + + for i, d := range data { + output := Filename(d.input) + if d.expected != output { + t.Errorf("Test %d failed. Expected %q got %q", i, d.expected, output) + } + } +} + +func TestFileAndExt(t *testing.T) { + type test struct { + input, expectedFile, expectedExt string + } + data := []test{ + {"index.html", "index", ".html"}, + {"./index.html", "index", ".html"}, + {"/index.html", "index", ".html"}, + {"index", "index", ""}, + {"/tmp/index.html", "index", ".html"}, + {"./filename-no-ext", "filename-no-ext", ""}, + {"/filename-no-ext", "filename-no-ext", ""}, + {"filename-no-ext", "filename-no-ext", ""}, + {"directoy/", "", ""}, // no filename case?? + {"directory/.hidden.ext", ".hidden", ".ext"}, + } + + for i, d := range data { + file, ext := FileAndExt(d.input) + if d.expectedFile != file { + t.Errorf("Test %d failed. Expected filename %q got %q.", i, d.expectedFile, file) + } + if d.expectedExt != ext { + t.Errorf("Test %d failed. Expected extension $q got %q.", i, d.expectedExt, ext) + } + } + +} + +func TestGuessSection(t *testing.T) { + type test struct { + input, expected string + } + + data := []test{ + {"/", ""}, + {"", ""}, + {"/content", "/"}, + {"content/", "/"}, + {"/content/", "/"}, + {"/blog", "/blog"}, + {"/blog/", "/blog/"}, + {"blog", "blog"}, + {"content/blog", "/blog"}, + {"content/blog/", "/blog/"}, + {"/content/blog", "/blog/"}, + } + + for i, d := range data { + expected := GuessSection(d.input) + if d.expected != expected { + t.Errorf("Test %d failed. Expected %q got %q", i, d.expected, expected) + } + } +} + +func TestPathPrep(t *testing.T) { + +} + +func TestPrettifyPath(t *testing.T) { + +} + +func TestFindCWD(t *testing.T) { + type test struct { + expectedDir string + expectedErr error + } + + cwd, _ := os.Getwd() + data := []test{ + {cwd, nil}, + } + for i, d := range data { + dir, err := FindCWD() + if d.expectedDir != dir { + t.Errorf("Test %d failed. Expected %q but got %q", i, d.expectedDir, dir) + } + if d.expectedErr != err { + t.Error("Test %d failed. Expected %q but got %q", i, d.expectedErr, err) + } + } +} + +func TestSafeWriteToDisk(t *testing.T) { + /* + emptyFile, _ := createZeroSizedFileInTempDir() + defer deleteFileInTempDir(emptyFile) + tmpDir, _ := createEmptyTempDir() + defer deleteTempDir(tmpDir) + os.MkdirAll(tmpDir+"/this/dir/does/not/exist/", 0644) + + randomString := "This is a random string!" + reader := strings.NewReader(randomString) + + fileExists := fmt.Errorf("%v already exists", emptyFile.Name()) + type test struct { + filename string + expectedErr error + } + + data := []test{ + {emptyFile.Name(), fileExists}, + {tmpDir + "/" + emptyFile.Name(), nil}, + } + + for i, d := range data { + e := WriteToDisk(d.filename, reader) + t.Errorf("Failed: e is %q %#v", e, e) + if d.expectedErr != nil { + if d.expectedErr.Error() != e.Error() { + t.Errorf("Test %d failed. Expected error %q but got %q", i, d.expectedErr.Error(), e.Error()) + } + } + if d.expectedErr != e { + t.Errorf("Test %d failed. Expected %q but got %q", i, d.expectedErr, e) + } + contents, e := ioutil.ReadFile(d.filename) + if randomString != string(contents) { + t.Errorf("Test %d failed. Expected contents %q but got %q", i, randomString, string(contents)) + } + } + */ +} + +func TestWriteToDisk(t *testing.T) { + emptyFile, _ := createZeroSizedFileInTempDir() + defer deleteFileInTempDir(emptyFile) + tmpDir, _ := createEmptyTempDir() + defer deleteTempDir(tmpDir) + os.MkdirAll(tmpDir+"/this/dir/does/not/exist/", 0644) + + randomString := "This is a random string!" + reader := strings.NewReader(randomString) + + type test struct { + filename string + expectedErr error + } + + data := []test{ + {emptyFile.Name(), nil}, + {tmpDir + "/" + emptyFile.Name(), nil}, + } + + for i, d := range data { + e := WriteToDisk(d.filename, reader) + if d.expectedErr != e { + t.Errorf("Test %d failed. Expected %q but got %q", i, d.expectedErr, e) + } + contents, e := ioutil.ReadFile(d.filename) + if randomString != string(contents) { + t.Errorf("Test %d failed. Expected contents %q but got %q", i, randomString, string(contents)) + } + } +}