symlink_test.go 5.4 KB

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