symlink_test.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. // Copyright (C) 2014 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. //go:build integration
  7. // +build integration
  8. package integration
  9. import (
  10. "log"
  11. "os"
  12. "testing"
  13. "github.com/syncthing/syncthing/lib/config"
  14. "github.com/syncthing/syncthing/lib/events"
  15. "github.com/syncthing/syncthing/lib/protocol"
  16. "github.com/syncthing/syncthing/lib/rc"
  17. )
  18. func TestSymlinks(t *testing.T) {
  19. if !symlinksSupported() {
  20. t.Skip("symlinks unsupported")
  21. }
  22. // Use no versioning
  23. id, _ := protocol.DeviceIDFromString(id2)
  24. cfg, _, _ := config.Load("h2/config.xml", id, events.NoopLogger)
  25. fld := cfg.Folders()["default"]
  26. fld.Versioning = config.VersioningConfiguration{}
  27. cfg.SetFolder(fld)
  28. os.Rename("h2/config.xml", "h2/config.xml.orig")
  29. defer os.Rename("h2/config.xml.orig", "h2/config.xml")
  30. cfg.Save()
  31. testSymlinks(t)
  32. }
  33. func TestSymlinksSimpleVersioning(t *testing.T) {
  34. if !symlinksSupported() {
  35. t.Skip("symlinks unsupported")
  36. }
  37. // Use simple versioning
  38. id, _ := protocol.DeviceIDFromString(id2)
  39. cfg, _, _ := config.Load("h2/config.xml", id, events.NoopLogger)
  40. fld := cfg.Folders()["default"]
  41. fld.Versioning = config.VersioningConfiguration{
  42. Type: "simple",
  43. Params: map[string]string{"keep": "5"},
  44. }
  45. cfg.SetFolder(fld)
  46. os.Rename("h2/config.xml", "h2/config.xml.orig")
  47. defer os.Rename("h2/config.xml.orig", "h2/config.xml")
  48. cfg.Save()
  49. testSymlinks(t)
  50. }
  51. func TestSymlinksStaggeredVersioning(t *testing.T) {
  52. if !symlinksSupported() {
  53. t.Skip("symlinks unsupported")
  54. }
  55. // Use staggered versioning
  56. id, _ := protocol.DeviceIDFromString(id2)
  57. cfg, _, _ := config.Load("h2/config.xml", id, events.NoopLogger)
  58. fld := cfg.Folders()["default"]
  59. fld.Versioning = config.VersioningConfiguration{
  60. Type: "staggered",
  61. }
  62. cfg.SetFolder(fld)
  63. os.Rename("h2/config.xml", "h2/config.xml.orig")
  64. defer os.Rename("h2/config.xml.orig", "h2/config.xml")
  65. cfg.Save()
  66. testSymlinks(t)
  67. }
  68. func testSymlinks(t *testing.T) {
  69. log.Println("Cleaning...")
  70. err := removeAll("s1", "s2", "h1/index*", "h2/index*")
  71. if err != nil {
  72. t.Fatal(err)
  73. }
  74. log.Println("Generating files...")
  75. err = generateFiles("s1", 100, 20, "../LICENSE")
  76. if err != nil {
  77. t.Fatal(err)
  78. }
  79. // A file that we will replace with a symlink later
  80. fd, err := os.Create("s1/fileToReplace")
  81. if err != nil {
  82. t.Fatal(err)
  83. }
  84. fd.Close()
  85. // A directory that we will replace with a symlink later
  86. err = os.Mkdir("s1/dirToReplace", 0755)
  87. if err != nil {
  88. t.Fatal(err)
  89. }
  90. // A file and a symlink to that file
  91. fd, err = os.Create("s1/file")
  92. if err != nil {
  93. t.Fatal(err)
  94. }
  95. fd.Close()
  96. err = os.Symlink("file", "s1/fileLink")
  97. if err != nil {
  98. log.Fatal(err)
  99. }
  100. // A directory and a symlink to that directory
  101. err = os.Mkdir("s1/dir", 0755)
  102. if err != nil {
  103. t.Fatal(err)
  104. }
  105. err = os.Symlink("dir", "s1/dirLink")
  106. if err != nil {
  107. log.Fatal(err)
  108. }
  109. // A link to something in the repo that does not exist
  110. err = os.Symlink("does/not/exist", "s1/noneLink")
  111. if err != nil {
  112. log.Fatal(err)
  113. }
  114. // A link we will replace with a file later
  115. err = os.Symlink("does/not/exist", "s1/repFileLink")
  116. if err != nil {
  117. log.Fatal(err)
  118. }
  119. // A link we will replace with a directory later
  120. err = os.Symlink("does/not/exist", "s1/repDirLink")
  121. if err != nil {
  122. log.Fatal(err)
  123. }
  124. // A link we will remove later
  125. err = os.Symlink("does/not/exist", "s1/removeLink")
  126. if err != nil {
  127. log.Fatal(err)
  128. }
  129. // Verify that the files and symlinks sync to the other side
  130. sender := startInstance(t, 1)
  131. defer checkedStop(t, sender)
  132. receiver := startInstance(t, 2)
  133. defer checkedStop(t, receiver)
  134. sender.ResumeAll()
  135. receiver.ResumeAll()
  136. log.Println("Syncing...")
  137. rc.AwaitSync("default", sender, receiver)
  138. log.Println("Comparing directories...")
  139. err = compareDirectories("s1", "s2")
  140. if err != nil {
  141. t.Fatal(err)
  142. }
  143. log.Println("Making some changes...")
  144. // Remove one symlink
  145. err = os.Remove("s1/fileLink")
  146. if err != nil {
  147. log.Fatal(err)
  148. }
  149. // Change the target of another
  150. err = os.Remove("s1/dirLink")
  151. if err != nil {
  152. log.Fatal(err)
  153. }
  154. err = os.Symlink("file", "s1/dirLink")
  155. if err != nil {
  156. log.Fatal(err)
  157. }
  158. // Replace one with a file
  159. err = os.Remove("s1/repFileLink")
  160. if err != nil {
  161. log.Fatal(err)
  162. }
  163. fd, err = os.Create("s1/repFileLink")
  164. if err != nil {
  165. log.Fatal(err)
  166. }
  167. fd.Close()
  168. // Replace one with a directory
  169. err = os.Remove("s1/repDirLink")
  170. if err != nil {
  171. log.Fatal(err)
  172. }
  173. err = os.Mkdir("s1/repDirLink", 0755)
  174. if err != nil {
  175. log.Fatal(err)
  176. }
  177. // Replace a file with a symlink
  178. err = os.Remove("s1/fileToReplace")
  179. if err != nil {
  180. log.Fatal(err)
  181. }
  182. err = os.Symlink("somewhere/non/existent", "s1/fileToReplace")
  183. if err != nil {
  184. log.Fatal(err)
  185. }
  186. // Replace a directory with a symlink
  187. err = os.RemoveAll("s1/dirToReplace")
  188. if err != nil {
  189. log.Fatal(err)
  190. }
  191. err = os.Symlink("somewhere/non/existent", "s1/dirToReplace")
  192. if err != nil {
  193. log.Fatal(err)
  194. }
  195. // Remove a broken symlink
  196. err = os.Remove("s1/removeLink")
  197. if err != nil {
  198. log.Fatal(err)
  199. }
  200. // Sync these changes and recheck
  201. log.Println("Syncing...")
  202. if err := sender.Rescan("default"); err != nil {
  203. t.Fatal(err)
  204. }
  205. rc.AwaitSync("default", sender, receiver)
  206. log.Println("Comparing directories...")
  207. err = compareDirectories("s1", "s2")
  208. if err != nil {
  209. t.Fatal(err)
  210. }
  211. }