fileutils_test.go 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. package fileutils // import "github.com/docker/docker/pkg/fileutils"
  2. import (
  3. "context"
  4. "errors"
  5. "os"
  6. "path"
  7. "path/filepath"
  8. "runtime"
  9. "strings"
  10. "testing"
  11. )
  12. // CopyFile with invalid src
  13. func TestCopyFileWithInvalidSrc(t *testing.T) {
  14. tempDir := t.TempDir()
  15. bytes, err := CopyFile(filepath.Join(tempDir, "/invalid/file/path"), path.Join(t.TempDir(), "dest"))
  16. if err == nil {
  17. t.Error("Should have fail to copy an invalid src file")
  18. }
  19. if !errors.Is(err, os.ErrNotExist) {
  20. t.Errorf("Expected an os.ErrNotExist, got: %v", err)
  21. }
  22. if bytes != 0 {
  23. t.Errorf("Should have written 0 bytes, got: %d", bytes)
  24. }
  25. }
  26. // CopyFile with invalid dest
  27. func TestCopyFileWithInvalidDest(t *testing.T) {
  28. tempFolder := t.TempDir()
  29. src := path.Join(tempFolder, "file")
  30. err := os.WriteFile(src, []byte("content"), 0o740)
  31. if err != nil {
  32. t.Fatal(err)
  33. }
  34. bytes, err := CopyFile(src, path.Join(tempFolder, "/invalid/dest/path"))
  35. if err == nil {
  36. t.Error("Should have fail to copy an invalid src file")
  37. }
  38. if !errors.Is(err, os.ErrNotExist) {
  39. t.Errorf("Expected an os.ErrNotExist, got: %v", err)
  40. }
  41. if bytes != 0 {
  42. t.Errorf("Should have written 0 bytes, got: %d", bytes)
  43. }
  44. }
  45. // CopyFile with same src and dest
  46. func TestCopyFileWithSameSrcAndDest(t *testing.T) {
  47. file := path.Join(t.TempDir(), "file")
  48. err := os.WriteFile(file, []byte("content"), 0o740)
  49. if err != nil {
  50. t.Fatal(err)
  51. }
  52. bytes, err := CopyFile(file, file)
  53. if err != nil {
  54. t.Fatal(err)
  55. }
  56. if bytes != 0 {
  57. t.Fatal("Should have written 0 bytes as it is the same file.")
  58. }
  59. }
  60. // CopyFile with same src and dest but path is different and not clean
  61. func TestCopyFileWithSameSrcAndDestWithPathNameDifferent(t *testing.T) {
  62. testFolder := path.Join(t.TempDir(), "test")
  63. err := os.Mkdir(testFolder, 0o740)
  64. if err != nil {
  65. t.Fatal(err)
  66. }
  67. file := path.Join(testFolder, "file")
  68. sameFile := testFolder + "/../test/file"
  69. err = os.WriteFile(file, []byte("content"), 0o740)
  70. if err != nil {
  71. t.Fatal(err)
  72. }
  73. bytes, err := CopyFile(file, sameFile)
  74. if err != nil {
  75. t.Fatal(err)
  76. }
  77. if bytes != 0 {
  78. t.Fatal("Should have written 0 bytes as it is the same file.")
  79. }
  80. }
  81. func TestCopyFile(t *testing.T) {
  82. tempFolder := t.TempDir()
  83. src := path.Join(tempFolder, "src")
  84. dest := path.Join(tempFolder, "dest")
  85. err := os.WriteFile(src, []byte("content"), 0o777)
  86. if err != nil {
  87. t.Error(err)
  88. }
  89. err = os.WriteFile(dest, []byte("destContent"), 0o777)
  90. if err != nil {
  91. t.Error(err)
  92. }
  93. bytes, err := CopyFile(src, dest)
  94. if err != nil {
  95. t.Fatal(err)
  96. }
  97. if bytes != 7 {
  98. t.Fatalf("Should have written %d bytes but wrote %d", 7, bytes)
  99. }
  100. actual, err := os.ReadFile(dest)
  101. if err != nil {
  102. t.Fatal(err)
  103. }
  104. if string(actual) != "content" {
  105. t.Fatalf("Dest content was '%s', expected '%s'", string(actual), "content")
  106. }
  107. }
  108. // Reading a symlink to a directory must return the directory
  109. func TestReadSymlinkedDirectoryExistingDirectory(t *testing.T) {
  110. // TODO Windows: Port this test
  111. if runtime.GOOS == "windows" {
  112. t.Skip("Needs porting to Windows")
  113. }
  114. // On macOS, tmp itself is symlinked, so resolve this one upfront;
  115. // see https://github.com/golang/go/issues/56259
  116. tmpDir, err := filepath.EvalSymlinks(t.TempDir())
  117. if err != nil {
  118. t.Fatal(err)
  119. }
  120. srcPath := filepath.Join(tmpDir, "/testReadSymlinkToExistingDirectory")
  121. dstPath := filepath.Join(tmpDir, "/dirLinkTest")
  122. if err = os.Mkdir(srcPath, 0o777); err != nil {
  123. t.Errorf("failed to create directory: %s", err)
  124. }
  125. if err = os.Symlink(srcPath, dstPath); err != nil {
  126. t.Errorf("failed to create symlink: %s", err)
  127. }
  128. var symlinkedPath string
  129. if symlinkedPath, err = ReadSymlinkedDirectory(dstPath); err != nil {
  130. t.Fatalf("failed to read symlink to directory: %s", err)
  131. }
  132. if symlinkedPath != srcPath {
  133. t.Fatalf("symlink returned unexpected directory: %s", symlinkedPath)
  134. }
  135. if err = os.Remove(srcPath); err != nil {
  136. t.Errorf("failed to remove temporary directory: %s", err)
  137. }
  138. if err = os.Remove(dstPath); err != nil {
  139. t.Errorf("failed to remove symlink: %s", err)
  140. }
  141. }
  142. // Reading a non-existing symlink must fail
  143. func TestReadSymlinkedDirectoryNonExistingSymlink(t *testing.T) {
  144. tmpDir := t.TempDir()
  145. symLinkedPath, err := ReadSymlinkedDirectory(path.Join(tmpDir, "/Non/ExistingPath"))
  146. if err == nil {
  147. t.Errorf("error expected for non-existing symlink")
  148. }
  149. if !errors.Is(err, os.ErrNotExist) {
  150. t.Errorf("Expected an os.ErrNotExist, got: %v", err)
  151. }
  152. if symLinkedPath != "" {
  153. t.Fatalf("expected empty path, but '%s' was returned", symLinkedPath)
  154. }
  155. }
  156. // Reading a symlink to a file must fail
  157. func TestReadSymlinkedDirectoryToFile(t *testing.T) {
  158. // TODO Windows: Port this test
  159. if runtime.GOOS == "windows" {
  160. t.Skip("Needs porting to Windows")
  161. }
  162. var err error
  163. var file *os.File
  164. // #nosec G303
  165. if file, err = os.Create("/tmp/testReadSymlinkToFile"); err != nil {
  166. t.Fatalf("failed to create file: %s", err)
  167. }
  168. _ = file.Close()
  169. if err = os.Symlink("/tmp/testReadSymlinkToFile", "/tmp/fileLinkTest"); err != nil {
  170. t.Errorf("failed to create symlink: %s", err)
  171. }
  172. symlinkedPath, err := ReadSymlinkedDirectory("/tmp/fileLinkTest")
  173. if err == nil {
  174. t.Errorf("ReadSymlinkedDirectory on a symlink to a file should've failed")
  175. }
  176. if !strings.HasPrefix(err.Error(), "canonical path points to a file") {
  177. t.Errorf("unexpected error: %v", err)
  178. }
  179. if symlinkedPath != "" {
  180. t.Errorf("path should've been empty: %s", symlinkedPath)
  181. }
  182. if err = os.Remove("/tmp/testReadSymlinkToFile"); err != nil {
  183. t.Errorf("failed to remove file: %s", err)
  184. }
  185. if err = os.Remove("/tmp/fileLinkTest"); err != nil {
  186. t.Errorf("failed to remove symlink: %s", err)
  187. }
  188. }
  189. func TestCreateIfNotExistsDir(t *testing.T) {
  190. folderToCreate := filepath.Join(t.TempDir(), "tocreate")
  191. if err := CreateIfNotExists(folderToCreate, true); err != nil {
  192. t.Fatal(err)
  193. }
  194. fileinfo, err := os.Stat(folderToCreate)
  195. if err != nil {
  196. t.Fatalf("Should have create a folder, got %v", err)
  197. }
  198. if !fileinfo.IsDir() {
  199. t.Errorf("Should have been a dir, seems it's not")
  200. }
  201. }
  202. func TestCreateIfNotExistsFile(t *testing.T) {
  203. fileToCreate := filepath.Join(t.TempDir(), "file/to/create")
  204. if err := CreateIfNotExists(fileToCreate, false); err != nil {
  205. t.Error(err)
  206. }
  207. fileinfo, err := os.Stat(fileToCreate)
  208. if err != nil {
  209. t.Fatalf("Should have create a file, got %v", err)
  210. }
  211. if fileinfo.IsDir() {
  212. t.Errorf("Should have been a file, seems it's not")
  213. }
  214. }
  215. func BenchmarkGetTotalUsedFds(b *testing.B) {
  216. ctx := context.Background()
  217. b.ReportAllocs()
  218. for i := 0; i < b.N; i++ {
  219. _ = GetTotalUsedFds(ctx)
  220. }
  221. }