walkfs_test.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. // Copyright (C) 2019 The Syncthing Authors.
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this file,
  5. // You can obtain one at https://mozilla.org/MPL/2.0/.
  6. package fs
  7. import (
  8. "errors"
  9. "fmt"
  10. osexec "os/exec"
  11. "path/filepath"
  12. "testing"
  13. "github.com/syncthing/syncthing/lib/build"
  14. )
  15. func testWalkSkipSymlink(t *testing.T, fsType FilesystemType, uri string) {
  16. if build.IsWindows {
  17. t.Skip("Symlinks skipping is not tested on windows")
  18. }
  19. fs := NewFilesystem(fsType, uri)
  20. if err := fs.MkdirAll("target/foo", 0755); err != nil {
  21. t.Fatal(err)
  22. }
  23. if err := fs.Mkdir("towalk", 0755); err != nil {
  24. t.Fatal(err)
  25. }
  26. if err := fs.CreateSymlink("target", "towalk/symlink"); err != nil {
  27. t.Fatal(err)
  28. }
  29. if err := fs.Walk("towalk", func(path string, info FileInfo, err error) error {
  30. if err != nil {
  31. t.Fatal(err)
  32. }
  33. if info.Name() != "symlink" && info.Name() != "towalk" {
  34. t.Fatal("Walk unexpected file", info.Name())
  35. }
  36. return nil
  37. }); err != nil {
  38. t.Fatal(err)
  39. }
  40. }
  41. func createDirJunct(target string, name string) error {
  42. output, err := osexec.Command("cmd", "/c", "mklink", "/J", name, target).CombinedOutput()
  43. if err != nil {
  44. return fmt.Errorf("Failed to run mklink %v %v: %v %q", name, target, err, output)
  45. }
  46. return nil
  47. }
  48. func testWalkTraverseDirJunct(t *testing.T, fsType FilesystemType, uri string) {
  49. if !build.IsWindows {
  50. t.Skip("Directory junctions are available and tested on windows only")
  51. }
  52. fs := NewFilesystem(fsType, uri, new(OptionJunctionsAsDirs))
  53. if err := fs.MkdirAll("target/foo", 0); err != nil {
  54. t.Fatal(err)
  55. }
  56. if err := fs.Mkdir("towalk", 0); err != nil {
  57. t.Fatal(err)
  58. }
  59. if err := createDirJunct(filepath.Join(uri, "target"), filepath.Join(uri, "towalk/dirjunct")); err != nil {
  60. t.Fatal(err)
  61. }
  62. traversed := false
  63. if err := fs.Walk("towalk", func(path string, info FileInfo, err error) error {
  64. if err != nil {
  65. t.Fatal(err)
  66. }
  67. if info.Name() == "foo" {
  68. traversed = true
  69. }
  70. return nil
  71. }); err != nil {
  72. t.Fatal(err)
  73. }
  74. if !traversed {
  75. t.Fatal("Directory junction was not traversed")
  76. }
  77. }
  78. func testWalkInfiniteRecursion(t *testing.T, fsType FilesystemType, uri string) {
  79. if !build.IsWindows {
  80. t.Skip("Infinite recursion detection is tested on windows only")
  81. }
  82. fs := NewFilesystem(fsType, uri, new(OptionJunctionsAsDirs))
  83. if err := fs.MkdirAll("target/foo", 0); err != nil {
  84. t.Fatal(err)
  85. }
  86. if err := fs.Mkdir("towalk", 0); err != nil {
  87. t.Fatal(err)
  88. }
  89. if err := createDirJunct(filepath.Join(uri, "target"), filepath.Join(uri, "towalk/dirjunct")); err != nil {
  90. t.Fatal(err)
  91. }
  92. if err := createDirJunct(filepath.Join(uri, "towalk"), filepath.Join(uri, "target/foo/recurse")); err != nil {
  93. t.Fatal(err)
  94. }
  95. dirjunctCnt := 0
  96. fooCnt := 0
  97. found := false
  98. if err := fs.Walk("towalk", func(path string, info FileInfo, err error) error {
  99. if err != nil {
  100. if errors.Is(err, ErrInfiniteRecursion) {
  101. if found {
  102. t.Fatal("second infinite recursion detected at", path)
  103. }
  104. found = true
  105. return nil
  106. }
  107. t.Fatal(err)
  108. }
  109. if info.Name() == "dirjunct" {
  110. dirjunctCnt++
  111. } else if info.Name() == "foo" {
  112. fooCnt++
  113. }
  114. return nil
  115. }); err != nil {
  116. t.Fatal(err)
  117. }
  118. if dirjunctCnt != 2 || fooCnt != 1 || !found {
  119. t.Fatal("Infinite recursion not detected correctly")
  120. }
  121. }