hugo

Fork of github.com/gohugoio/hugo with reverse pagination support

git clone git://git.shimmy1996.com/hugo.git

path_test.go (15260B)

    1 // Copyright 2015 The Hugo Authors. All rights reserved.
    2 //
    3 // Licensed under the Apache License, Version 2.0 (the "License");
    4 // you may not use this file except in compliance with the License.
    5 // You may obtain a copy of the License at
    6 // http://www.apache.org/licenses/LICENSE-2.0
    7 //
    8 // Unless required by applicable law or agreed to in writing, software
    9 // distributed under the License is distributed on an "AS IS" BASIS,
   10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   11 // See the License for the specific language governing permissions and
   12 // limitations under the License.
   13 
   14 package helpers
   15 
   16 import (
   17 	"fmt"
   18 	"io/ioutil"
   19 	"os"
   20 	"path/filepath"
   21 	"reflect"
   22 	"runtime"
   23 	"strconv"
   24 	"strings"
   25 	"testing"
   26 	"time"
   27 
   28 	"github.com/gohugoio/hugo/langs"
   29 
   30 	qt "github.com/frankban/quicktest"
   31 
   32 	"github.com/gohugoio/hugo/hugofs"
   33 	"github.com/spf13/afero"
   34 )
   35 
   36 func TestMakePath(t *testing.T) {
   37 	c := qt.New(t)
   38 	tests := []struct {
   39 		input         string
   40 		expected      string
   41 		removeAccents bool
   42 	}{
   43 		{"dot.slash/backslash\\underscore_pound#plus+hyphen-", "dot.slash/backslash\\underscore_pound#plus+hyphen-", true},
   44 		{"abcXYZ0123456789", "abcXYZ0123456789", true},
   45 		{"%20 %2", "%20-2", true},
   46 		{"foo- bar", "foo-bar", true},
   47 		{"  Foo bar  ", "Foo-bar", true},
   48 		{"Foo.Bar/foo_Bar-Foo", "Foo.Bar/foo_Bar-Foo", true},
   49 		{"fOO,bar:foobAR", "fOObarfoobAR", true},
   50 		{"FOo/BaR.html", "FOo/BaR.html", true},
   51 		{"трям/трям", "трям/трям", true},
   52 		{"은행", "은행", true},
   53 		{"Банковский кассир", "Банковскии-кассир", true},
   54 		// Issue #1488
   55 		{"संस्कृत", "संस्कृत", false},
   56 		{"a%C3%B1ame", "a%C3%B1ame", false},         // Issue #1292
   57 		{"this+is+a+test", "this+is+a+test", false}, // Issue #1290
   58 		{"~foo", "~foo", false},                     // Issue #2177
   59 		{"foo--bar", "foo--bar", true},              // Issue #7288
   60 	}
   61 
   62 	for _, test := range tests {
   63 		v := newTestCfg()
   64 		v.Set("removePathAccents", test.removeAccents)
   65 
   66 		l := langs.NewDefaultLanguage(v)
   67 		p, err := NewPathSpec(hugofs.NewMem(v), l, nil)
   68 		c.Assert(err, qt.IsNil)
   69 
   70 		output := p.MakePath(test.input)
   71 		if output != test.expected {
   72 			t.Errorf("Expected %#v, got %#v\n", test.expected, output)
   73 		}
   74 	}
   75 }
   76 
   77 func TestMakePathSanitized(t *testing.T) {
   78 	v := newTestCfg()
   79 
   80 	p, _ := NewPathSpec(hugofs.NewMem(v), v, nil)
   81 
   82 	tests := []struct {
   83 		input    string
   84 		expected string
   85 	}{
   86 		{"  FOO bar  ", "foo-bar"},
   87 		{"Foo.Bar/fOO_bAr-Foo", "foo.bar/foo_bar-foo"},
   88 		{"FOO,bar:FooBar", "foobarfoobar"},
   89 		{"foo/BAR.HTML", "foo/bar.html"},
   90 		{"трям/трям", "трям/трям"},
   91 		{"은행", "은행"},
   92 	}
   93 
   94 	for _, test := range tests {
   95 		output := p.MakePathSanitized(test.input)
   96 		if output != test.expected {
   97 			t.Errorf("Expected %#v, got %#v\n", test.expected, output)
   98 		}
   99 	}
  100 }
  101 
  102 func TestMakePathSanitizedDisablePathToLower(t *testing.T) {
  103 	v := newTestCfg()
  104 
  105 	v.Set("disablePathToLower", true)
  106 
  107 	l := langs.NewDefaultLanguage(v)
  108 	p, _ := NewPathSpec(hugofs.NewMem(v), l, nil)
  109 
  110 	tests := []struct {
  111 		input    string
  112 		expected string
  113 	}{
  114 		{"  FOO bar  ", "FOO-bar"},
  115 		{"Foo.Bar/fOO_bAr-Foo", "Foo.Bar/fOO_bAr-Foo"},
  116 		{"FOO,bar:FooBar", "FOObarFooBar"},
  117 		{"foo/BAR.HTML", "foo/BAR.HTML"},
  118 		{"трям/трям", "трям/трям"},
  119 		{"은행", "은행"},
  120 	}
  121 
  122 	for _, test := range tests {
  123 		output := p.MakePathSanitized(test.input)
  124 		if output != test.expected {
  125 			t.Errorf("Expected %#v, got %#v\n", test.expected, output)
  126 		}
  127 	}
  128 }
  129 
  130 func TestMakePathRelative(t *testing.T) {
  131 	type test struct {
  132 		inPath, path1, path2, output string
  133 	}
  134 
  135 	data := []test{
  136 		{"/abc/bcd/ab.css", "/abc/bcd", "/bbc/bcd", "/ab.css"},
  137 		{"/abc/bcd/ab.css", "/abcd/bcd", "/abc/bcd", "/ab.css"},
  138 	}
  139 
  140 	for i, d := range data {
  141 		output, _ := makePathRelative(d.inPath, d.path1, d.path2)
  142 		if d.output != output {
  143 			t.Errorf("Test #%d failed. Expected %q got %q", i, d.output, output)
  144 		}
  145 	}
  146 	_, error := makePathRelative("a/b/c.ss", "/a/c", "/d/c", "/e/f")
  147 
  148 	if error == nil {
  149 		t.Errorf("Test failed, expected error")
  150 	}
  151 }
  152 
  153 func TestGetDottedRelativePath(t *testing.T) {
  154 	// on Windows this will receive both kinds, both country and western ...
  155 	for _, f := range []func(string) string{filepath.FromSlash, func(s string) string { return s }} {
  156 		doTestGetDottedRelativePath(f, t)
  157 	}
  158 }
  159 
  160 func doTestGetDottedRelativePath(urlFixer func(string) string, t *testing.T) {
  161 	type test struct {
  162 		input, expected string
  163 	}
  164 	data := []test{
  165 		{"", "./"},
  166 		{urlFixer("/"), "./"},
  167 		{urlFixer("post"), "../"},
  168 		{urlFixer("/post"), "../"},
  169 		{urlFixer("post/"), "../"},
  170 		{urlFixer("tags/foo.html"), "../"},
  171 		{urlFixer("/tags/foo.html"), "../"},
  172 		{urlFixer("/post/"), "../"},
  173 		{urlFixer("////post/////"), "../"},
  174 		{urlFixer("/foo/bar/index.html"), "../../"},
  175 		{urlFixer("/foo/bar/foo/"), "../../../"},
  176 		{urlFixer("/foo/bar/foo"), "../../../"},
  177 		{urlFixer("foo/bar/foo/"), "../../../"},
  178 		{urlFixer("foo/bar/foo/bar"), "../../../../"},
  179 		{"404.html", "./"},
  180 		{"404.xml", "./"},
  181 		{"/404.html", "./"},
  182 	}
  183 	for i, d := range data {
  184 		output := GetDottedRelativePath(d.input)
  185 		if d.expected != output {
  186 			t.Errorf("Test %d failed. Expected %q got %q", i, d.expected, output)
  187 		}
  188 	}
  189 }
  190 
  191 func TestMakeTitle(t *testing.T) {
  192 	type test struct {
  193 		input, expected string
  194 	}
  195 	data := []test{
  196 		{"Make-Title", "Make Title"},
  197 		{"MakeTitle", "MakeTitle"},
  198 		{"make_title", "make_title"},
  199 	}
  200 	for i, d := range data {
  201 		output := MakeTitle(d.input)
  202 		if d.expected != output {
  203 			t.Errorf("Test %d failed. Expected %q got %q", i, d.expected, output)
  204 		}
  205 	}
  206 }
  207 
  208 func TestDirExists(t *testing.T) {
  209 	type test struct {
  210 		input    string
  211 		expected bool
  212 	}
  213 
  214 	data := []test{
  215 		{".", true},
  216 		{"./", true},
  217 		{"..", true},
  218 		{"../", true},
  219 		{"./..", true},
  220 		{"./../", true},
  221 		{os.TempDir(), true},
  222 		{os.TempDir() + FilePathSeparator, true},
  223 		{"/", true},
  224 		{"/some-really-random-directory-name", false},
  225 		{"/some/really/random/directory/name", false},
  226 		{"./some-really-random-local-directory-name", false},
  227 		{"./some/really/random/local/directory/name", false},
  228 	}
  229 
  230 	for i, d := range data {
  231 		exists, _ := DirExists(filepath.FromSlash(d.input), new(afero.OsFs))
  232 		if d.expected != exists {
  233 			t.Errorf("Test %d failed. Expected %t got %t", i, d.expected, exists)
  234 		}
  235 	}
  236 }
  237 
  238 func TestIsDir(t *testing.T) {
  239 	type test struct {
  240 		input    string
  241 		expected bool
  242 	}
  243 	data := []test{
  244 		{"./", true},
  245 		{"/", true},
  246 		{"./this-directory-does-not-existi", false},
  247 		{"/this-absolute-directory/does-not-exist", false},
  248 	}
  249 
  250 	for i, d := range data {
  251 
  252 		exists, _ := IsDir(d.input, new(afero.OsFs))
  253 		if d.expected != exists {
  254 			t.Errorf("Test %d failed. Expected %t got %t", i, d.expected, exists)
  255 		}
  256 	}
  257 }
  258 
  259 func createZeroSizedFileInTempDir() (*os.File, error) {
  260 	filePrefix := "_path_test_"
  261 	f, e := ioutil.TempFile("", filePrefix) // dir is os.TempDir()
  262 	if e != nil {
  263 		// if there was an error no file was created.
  264 		// => no requirement to delete the file
  265 		return nil, e
  266 	}
  267 	return f, nil
  268 }
  269 
  270 func createNonZeroSizedFileInTempDir() (*os.File, error) {
  271 	f, err := createZeroSizedFileInTempDir()
  272 	if err != nil {
  273 		// no file ??
  274 		return nil, err
  275 	}
  276 	byteString := []byte("byteString")
  277 	err = ioutil.WriteFile(f.Name(), byteString, 0644)
  278 	if err != nil {
  279 		// delete the file
  280 		deleteFileInTempDir(f)
  281 		return nil, err
  282 	}
  283 	return f, nil
  284 }
  285 
  286 func deleteFileInTempDir(f *os.File) {
  287 	_ = os.Remove(f.Name())
  288 }
  289 
  290 func createEmptyTempDir() (string, error) {
  291 	dirPrefix := "_dir_prefix_"
  292 	d, e := ioutil.TempDir("", dirPrefix) // will be in os.TempDir()
  293 	if e != nil {
  294 		// no directory to delete - it was never created
  295 		return "", e
  296 	}
  297 	return d, nil
  298 }
  299 
  300 func deleteTempDir(d string) {
  301 	_ = os.RemoveAll(d)
  302 }
  303 
  304 func TestExists(t *testing.T) {
  305 	zeroSizedFile, _ := createZeroSizedFileInTempDir()
  306 	defer deleteFileInTempDir(zeroSizedFile)
  307 	nonZeroSizedFile, _ := createNonZeroSizedFileInTempDir()
  308 	defer deleteFileInTempDir(nonZeroSizedFile)
  309 	emptyDirectory, _ := createEmptyTempDir()
  310 	defer deleteTempDir(emptyDirectory)
  311 	nonExistentFile := os.TempDir() + "/this-file-does-not-exist.txt"
  312 	nonExistentDir := os.TempDir() + "/this/directory/does/not/exist/"
  313 
  314 	type test struct {
  315 		input          string
  316 		expectedResult bool
  317 		expectedErr    error
  318 	}
  319 
  320 	data := []test{
  321 		{zeroSizedFile.Name(), true, nil},
  322 		{nonZeroSizedFile.Name(), true, nil},
  323 		{emptyDirectory, true, nil},
  324 		{nonExistentFile, false, nil},
  325 		{nonExistentDir, false, nil},
  326 	}
  327 	for i, d := range data {
  328 		exists, err := Exists(d.input, new(afero.OsFs))
  329 		if d.expectedResult != exists {
  330 			t.Errorf("Test %d failed. Expected result %t got %t", i, d.expectedResult, exists)
  331 		}
  332 		if d.expectedErr != err {
  333 			t.Errorf("Test %d failed. Expected %q got %q", i, d.expectedErr, err)
  334 		}
  335 	}
  336 }
  337 
  338 func TestAbsPathify(t *testing.T) {
  339 	type test struct {
  340 		inPath, workingDir, expected string
  341 	}
  342 	data := []test{
  343 		{os.TempDir(), filepath.FromSlash("/work"), filepath.Clean(os.TempDir())}, // TempDir has trailing slash
  344 		{"dir", filepath.FromSlash("/work"), filepath.FromSlash("/work/dir")},
  345 	}
  346 
  347 	windowsData := []test{
  348 		{"c:\\banana\\..\\dir", "c:\\foo", "c:\\dir"},
  349 		{"\\dir", "c:\\foo", "c:\\foo\\dir"},
  350 		{"c:\\", "c:\\foo", "c:\\"},
  351 	}
  352 
  353 	unixData := []test{
  354 		{"/banana/../dir/", "/work", "/dir"},
  355 	}
  356 
  357 	for i, d := range data {
  358 		// todo see comment in AbsPathify
  359 		ps := newTestDefaultPathSpec("workingDir", d.workingDir)
  360 
  361 		expected := ps.AbsPathify(d.inPath)
  362 		if d.expected != expected {
  363 			t.Errorf("Test %d failed. Expected %q but got %q", i, d.expected, expected)
  364 		}
  365 	}
  366 	t.Logf("Running platform specific path tests for %s", runtime.GOOS)
  367 	if runtime.GOOS == "windows" {
  368 		for i, d := range windowsData {
  369 			ps := newTestDefaultPathSpec("workingDir", d.workingDir)
  370 
  371 			expected := ps.AbsPathify(d.inPath)
  372 			if d.expected != expected {
  373 				t.Errorf("Test %d failed. Expected %q but got %q", i, d.expected, expected)
  374 			}
  375 		}
  376 	} else {
  377 		for i, d := range unixData {
  378 			ps := newTestDefaultPathSpec("workingDir", d.workingDir)
  379 
  380 			expected := ps.AbsPathify(d.inPath)
  381 			if d.expected != expected {
  382 				t.Errorf("Test %d failed. Expected %q but got %q", i, d.expected, expected)
  383 			}
  384 		}
  385 	}
  386 }
  387 
  388 func TestExtractAndGroupRootPaths(t *testing.T) {
  389 	in := []string{
  390 		filepath.FromSlash("/a/b/c/d"),
  391 		filepath.FromSlash("/a/b/c/e"),
  392 		filepath.FromSlash("/a/b/e/f"),
  393 		filepath.FromSlash("/a/b"),
  394 		filepath.FromSlash("/a/b/c/b/g"),
  395 		filepath.FromSlash("/c/d/e"),
  396 	}
  397 
  398 	inCopy := make([]string, len(in))
  399 	copy(inCopy, in)
  400 
  401 	result := ExtractAndGroupRootPaths(in)
  402 
  403 	c := qt.New(t)
  404 	c.Assert(fmt.Sprint(result), qt.Equals, filepath.FromSlash("[/a/b/{c,e} /c/d/e]"))
  405 
  406 	// Make sure the original is preserved
  407 	c.Assert(in, qt.DeepEquals, inCopy)
  408 }
  409 
  410 func TestExtractRootPaths(t *testing.T) {
  411 	tests := []struct {
  412 		input    []string
  413 		expected []string
  414 	}{{
  415 		[]string{
  416 			filepath.FromSlash("a/b"), filepath.FromSlash("a/b/c/"), "b",
  417 			filepath.FromSlash("/c/d"), filepath.FromSlash("d/"), filepath.FromSlash("//e//"),
  418 		},
  419 		[]string{"a", "a", "b", "c", "d", "e"},
  420 	}}
  421 
  422 	for _, test := range tests {
  423 		output := ExtractRootPaths(test.input)
  424 		if !reflect.DeepEqual(output, test.expected) {
  425 			t.Errorf("Expected %#v, got %#v\n", test.expected, output)
  426 		}
  427 	}
  428 }
  429 
  430 func TestFindCWD(t *testing.T) {
  431 	type test struct {
  432 		expectedDir string
  433 		expectedErr error
  434 	}
  435 
  436 	// cwd, _ := os.Getwd()
  437 	data := []test{
  438 		//{cwd, nil},
  439 		// Commenting this out. It doesn't work properly.
  440 		// There's a good reason why we don't use os.Getwd(), it doesn't actually work the way we want it to.
  441 		// I really don't know a better way to test this function. - SPF 2014.11.04
  442 	}
  443 	for i, d := range data {
  444 		dir, err := FindCWD()
  445 		if d.expectedDir != dir {
  446 			t.Errorf("Test %d failed. Expected %q but got %q", i, d.expectedDir, dir)
  447 		}
  448 		if d.expectedErr != err {
  449 			t.Errorf("Test %d failed. Expected %q but got %q", i, d.expectedErr, err)
  450 		}
  451 	}
  452 }
  453 
  454 func TestSafeWriteToDisk(t *testing.T) {
  455 	emptyFile, _ := createZeroSizedFileInTempDir()
  456 	defer deleteFileInTempDir(emptyFile)
  457 	tmpDir, _ := createEmptyTempDir()
  458 	defer deleteTempDir(tmpDir)
  459 
  460 	randomString := "This is a random string!"
  461 	reader := strings.NewReader(randomString)
  462 
  463 	fileExists := fmt.Errorf("%v already exists", emptyFile.Name())
  464 
  465 	type test struct {
  466 		filename    string
  467 		expectedErr error
  468 	}
  469 
  470 	now := time.Now().Unix()
  471 	nowStr := strconv.FormatInt(now, 10)
  472 	data := []test{
  473 		{emptyFile.Name(), fileExists},
  474 		{tmpDir + "/" + nowStr, nil},
  475 	}
  476 
  477 	for i, d := range data {
  478 		e := SafeWriteToDisk(d.filename, reader, new(afero.OsFs))
  479 		if d.expectedErr != nil {
  480 			if d.expectedErr.Error() != e.Error() {
  481 				t.Errorf("Test %d failed. Expected error %q but got %q", i, d.expectedErr.Error(), e.Error())
  482 			}
  483 		} else {
  484 			if d.expectedErr != e {
  485 				t.Errorf("Test %d failed. Expected %q but got %q", i, d.expectedErr, e)
  486 			}
  487 			contents, _ := ioutil.ReadFile(d.filename)
  488 			if randomString != string(contents) {
  489 				t.Errorf("Test %d failed. Expected contents %q but got %q", i, randomString, string(contents))
  490 			}
  491 		}
  492 		reader.Seek(0, 0)
  493 	}
  494 }
  495 
  496 func TestWriteToDisk(t *testing.T) {
  497 	emptyFile, _ := createZeroSizedFileInTempDir()
  498 	defer deleteFileInTempDir(emptyFile)
  499 	tmpDir, _ := createEmptyTempDir()
  500 	defer deleteTempDir(tmpDir)
  501 
  502 	randomString := "This is a random string!"
  503 	reader := strings.NewReader(randomString)
  504 
  505 	type test struct {
  506 		filename    string
  507 		expectedErr error
  508 	}
  509 
  510 	now := time.Now().Unix()
  511 	nowStr := strconv.FormatInt(now, 10)
  512 	data := []test{
  513 		{emptyFile.Name(), nil},
  514 		{tmpDir + "/" + nowStr, nil},
  515 	}
  516 
  517 	for i, d := range data {
  518 		e := WriteToDisk(d.filename, reader, new(afero.OsFs))
  519 		if d.expectedErr != e {
  520 			t.Errorf("Test %d failed. WriteToDisk Error Expected %q but got %q", i, d.expectedErr, e)
  521 		}
  522 		contents, e := ioutil.ReadFile(d.filename)
  523 		if e != nil {
  524 			t.Errorf("Test %d failed. Could not read file %s. Reason: %s\n", i, d.filename, e)
  525 		}
  526 		if randomString != string(contents) {
  527 			t.Errorf("Test %d failed. Expected contents %q but got %q", i, randomString, string(contents))
  528 		}
  529 		reader.Seek(0, 0)
  530 	}
  531 }
  532 
  533 func TestGetTempDir(t *testing.T) {
  534 	dir := os.TempDir()
  535 	if FilePathSeparator != dir[len(dir)-1:] {
  536 		dir = dir + FilePathSeparator
  537 	}
  538 	testDir := "hugoTestFolder" + FilePathSeparator
  539 	tests := []struct {
  540 		input    string
  541 		expected string
  542 	}{
  543 		{"", dir},
  544 		{testDir + "  Foo bar  ", dir + testDir + "  Foo bar  " + FilePathSeparator},
  545 		{testDir + "Foo.Bar/foo_Bar-Foo", dir + testDir + "Foo.Bar/foo_Bar-Foo" + FilePathSeparator},
  546 		{testDir + "fOO,bar:foo%bAR", dir + testDir + "fOObarfoo%bAR" + FilePathSeparator},
  547 		{testDir + "fOO,bar:foobAR", dir + testDir + "fOObarfoobAR" + FilePathSeparator},
  548 		{testDir + "FOo/BaR.html", dir + testDir + "FOo/BaR.html" + FilePathSeparator},
  549 		{testDir + "трям/трям", dir + testDir + "трям/трям" + FilePathSeparator},
  550 		{testDir + "은행", dir + testDir + "은행" + FilePathSeparator},
  551 		{testDir + "Банковский кассир", dir + testDir + "Банковский кассир" + FilePathSeparator},
  552 	}
  553 
  554 	for _, test := range tests {
  555 		output := GetTempDir(test.input, new(afero.MemMapFs))
  556 		if output != test.expected {
  557 			t.Errorf("Expected %#v, got %#v\n", test.expected, output)
  558 		}
  559 	}
  560 }