2
0

provider_test.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. package worker
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "os"
  6. "path/filepath"
  7. "testing"
  8. "time"
  9. . "github.com/smartystreets/goconvey/convey"
  10. )
  11. func TestRsyncProvider(t *testing.T) {
  12. Convey("Rsync Provider should work", t, func() {
  13. tmpDir, err := ioutil.TempDir("", "tunasync")
  14. defer os.RemoveAll(tmpDir)
  15. So(err, ShouldBeNil)
  16. scriptFile := filepath.Join(tmpDir, "myrsync")
  17. tmpFile := filepath.Join(tmpDir, "log_file")
  18. c := rsyncConfig{
  19. name: "tuna",
  20. upstreamURL: "rsync://rsync.tuna.moe/tuna/",
  21. rsyncCmd: scriptFile,
  22. workingDir: tmpDir,
  23. logDir: tmpDir,
  24. logFile: tmpFile,
  25. useIPv6: true,
  26. interval: 600 * time.Second,
  27. }
  28. provider, err := newRsyncProvider(c)
  29. So(err, ShouldBeNil)
  30. So(provider.Type(), ShouldEqual, provRsync)
  31. So(provider.Name(), ShouldEqual, c.name)
  32. So(provider.WorkingDir(), ShouldEqual, c.workingDir)
  33. So(provider.LogDir(), ShouldEqual, c.logDir)
  34. So(provider.LogFile(), ShouldEqual, c.logFile)
  35. So(provider.Interval(), ShouldEqual, c.interval)
  36. Convey("When entering a context (auto exit)", func() {
  37. func() {
  38. ctx := provider.EnterContext()
  39. defer provider.ExitContext()
  40. So(provider.WorkingDir(), ShouldEqual, c.workingDir)
  41. newWorkingDir := "/srv/mirror/working/tuna"
  42. ctx.Set(_WorkingDirKey, newWorkingDir)
  43. So(provider.WorkingDir(), ShouldEqual, newWorkingDir)
  44. }()
  45. Convey("After context is done", func() {
  46. So(provider.WorkingDir(), ShouldEqual, c.workingDir)
  47. })
  48. })
  49. Convey("When entering a context (manually exit)", func() {
  50. ctx := provider.EnterContext()
  51. So(provider.WorkingDir(), ShouldEqual, c.workingDir)
  52. newWorkingDir := "/srv/mirror/working/tuna"
  53. ctx.Set(_WorkingDirKey, newWorkingDir)
  54. So(provider.WorkingDir(), ShouldEqual, newWorkingDir)
  55. Convey("After context is done", func() {
  56. provider.ExitContext()
  57. So(provider.WorkingDir(), ShouldEqual, c.workingDir)
  58. })
  59. })
  60. Convey("Let's try a run", func() {
  61. scriptContent := `#!/bin/bash
  62. echo "syncing to $(pwd)"
  63. echo $RSYNC_PASSWORD $@
  64. sleep 1
  65. echo "Total file size: 1.33T bytes"
  66. echo "Done"
  67. exit 0
  68. `
  69. err = ioutil.WriteFile(scriptFile, []byte(scriptContent), 0755)
  70. So(err, ShouldBeNil)
  71. targetDir, _ := filepath.EvalSymlinks(provider.WorkingDir())
  72. expectedOutput := fmt.Sprintf(
  73. "syncing to %s\n"+
  74. "%s\n"+
  75. "Total file size: 1.33T bytes\n"+
  76. "Done\n",
  77. targetDir,
  78. fmt.Sprintf(
  79. "-aHvh --no-o --no-g --stats --exclude .~tmp~/ "+
  80. "--delete --delete-after --delay-updates --safe-links "+
  81. "--timeout=120 --contimeout=120 -6 %s %s",
  82. provider.upstreamURL, provider.WorkingDir(),
  83. ),
  84. )
  85. err = provider.Run()
  86. So(err, ShouldBeNil)
  87. loggedContent, err := ioutil.ReadFile(provider.LogFile())
  88. So(err, ShouldBeNil)
  89. So(string(loggedContent), ShouldEqual, expectedOutput)
  90. // fmt.Println(string(loggedContent))
  91. So(provider.DataSize(), ShouldEqual, "1.33T")
  92. })
  93. })
  94. }
  95. func TestRsyncProviderWithAuthentication(t *testing.T) {
  96. Convey("Rsync Provider with password should work", t, func() {
  97. tmpDir, err := ioutil.TempDir("", "tunasync")
  98. defer os.RemoveAll(tmpDir)
  99. So(err, ShouldBeNil)
  100. scriptFile := filepath.Join(tmpDir, "myrsync")
  101. tmpFile := filepath.Join(tmpDir, "log_file")
  102. c := rsyncConfig{
  103. name: "tuna",
  104. upstreamURL: "rsync://rsync.tuna.moe/tuna/",
  105. rsyncCmd: scriptFile,
  106. username: "tunasync",
  107. password: "tunasyncpassword",
  108. workingDir: tmpDir,
  109. logDir: tmpDir,
  110. logFile: tmpFile,
  111. useIPv6: true,
  112. interval: 600 * time.Second,
  113. }
  114. provider, err := newRsyncProvider(c)
  115. So(err, ShouldBeNil)
  116. So(provider.Name(), ShouldEqual, c.name)
  117. So(provider.WorkingDir(), ShouldEqual, c.workingDir)
  118. So(provider.LogDir(), ShouldEqual, c.logDir)
  119. So(provider.LogFile(), ShouldEqual, c.logFile)
  120. So(provider.Interval(), ShouldEqual, c.interval)
  121. Convey("Let's try a run", func() {
  122. scriptContent := `#!/bin/bash
  123. echo "syncing to $(pwd)"
  124. echo $USER $RSYNC_PASSWORD $@
  125. sleep 1
  126. echo "Done"
  127. exit 0
  128. `
  129. err = ioutil.WriteFile(scriptFile, []byte(scriptContent), 0755)
  130. So(err, ShouldBeNil)
  131. targetDir, _ := filepath.EvalSymlinks(provider.WorkingDir())
  132. expectedOutput := fmt.Sprintf(
  133. "syncing to %s\n"+
  134. "%s\n"+
  135. "Done\n",
  136. targetDir,
  137. fmt.Sprintf(
  138. "%s %s -aHvh --no-o --no-g --stats --exclude .~tmp~/ "+
  139. "--delete --delete-after --delay-updates --safe-links "+
  140. "--timeout=120 --contimeout=120 -6 %s %s",
  141. provider.username, provider.password, provider.upstreamURL, provider.WorkingDir(),
  142. ),
  143. )
  144. err = provider.Run()
  145. So(err, ShouldBeNil)
  146. loggedContent, err := ioutil.ReadFile(provider.LogFile())
  147. So(err, ShouldBeNil)
  148. So(string(loggedContent), ShouldEqual, expectedOutput)
  149. // fmt.Println(string(loggedContent))
  150. })
  151. })
  152. }
  153. func TestCmdProvider(t *testing.T) {
  154. Convey("Command Provider should work", t, func(ctx C) {
  155. tmpDir, err := ioutil.TempDir("", "tunasync")
  156. defer os.RemoveAll(tmpDir)
  157. So(err, ShouldBeNil)
  158. scriptFile := filepath.Join(tmpDir, "cmd.sh")
  159. tmpFile := filepath.Join(tmpDir, "log_file")
  160. c := cmdConfig{
  161. name: "tuna-cmd",
  162. upstreamURL: "http://mirrors.tuna.moe/",
  163. command: "bash " + scriptFile,
  164. workingDir: tmpDir,
  165. logDir: tmpDir,
  166. logFile: tmpFile,
  167. interval: 600 * time.Second,
  168. env: map[string]string{
  169. "AOSP_REPO_BIN": "/usr/local/bin/repo",
  170. },
  171. }
  172. provider, err := newCmdProvider(c)
  173. So(err, ShouldBeNil)
  174. So(provider.Type(), ShouldEqual, provCommand)
  175. So(provider.Name(), ShouldEqual, c.name)
  176. So(provider.WorkingDir(), ShouldEqual, c.workingDir)
  177. So(provider.LogDir(), ShouldEqual, c.logDir)
  178. So(provider.LogFile(), ShouldEqual, c.logFile)
  179. So(provider.Interval(), ShouldEqual, c.interval)
  180. Convey("Let's try to run a simple command", func() {
  181. scriptContent := `#!/bin/bash
  182. echo $TUNASYNC_WORKING_DIR
  183. echo $TUNASYNC_MIRROR_NAME
  184. echo $TUNASYNC_UPSTREAM_URL
  185. echo $TUNASYNC_LOG_FILE
  186. echo $AOSP_REPO_BIN
  187. `
  188. expectedOutput := fmt.Sprintf(
  189. "%s\n%s\n%s\n%s\n%s\n",
  190. provider.WorkingDir(),
  191. provider.Name(),
  192. provider.upstreamURL,
  193. provider.LogFile(),
  194. "/usr/local/bin/repo",
  195. )
  196. err = ioutil.WriteFile(scriptFile, []byte(scriptContent), 0755)
  197. So(err, ShouldBeNil)
  198. readedScriptContent, err := ioutil.ReadFile(scriptFile)
  199. So(err, ShouldBeNil)
  200. So(readedScriptContent, ShouldResemble, []byte(scriptContent))
  201. err = provider.Run()
  202. So(err, ShouldBeNil)
  203. loggedContent, err := ioutil.ReadFile(provider.LogFile())
  204. So(err, ShouldBeNil)
  205. So(string(loggedContent), ShouldEqual, expectedOutput)
  206. })
  207. Convey("If a command fails", func() {
  208. scriptContent := `exit 1`
  209. err = ioutil.WriteFile(scriptFile, []byte(scriptContent), 0755)
  210. So(err, ShouldBeNil)
  211. readedScriptContent, err := ioutil.ReadFile(scriptFile)
  212. So(err, ShouldBeNil)
  213. So(readedScriptContent, ShouldResemble, []byte(scriptContent))
  214. err = provider.Run()
  215. So(err, ShouldNotBeNil)
  216. })
  217. Convey("If a long job is killed", func(ctx C) {
  218. scriptContent := `#!/bin/bash
  219. sleep 5
  220. `
  221. err = ioutil.WriteFile(scriptFile, []byte(scriptContent), 0755)
  222. So(err, ShouldBeNil)
  223. go func() {
  224. err = provider.Run()
  225. ctx.So(err, ShouldNotBeNil)
  226. }()
  227. time.Sleep(1 * time.Second)
  228. err = provider.Terminate()
  229. So(err, ShouldBeNil)
  230. })
  231. })
  232. Convey("Command Provider without log file should work", t, func(ctx C) {
  233. tmpDir, err := ioutil.TempDir("", "tunasync")
  234. defer os.RemoveAll(tmpDir)
  235. So(err, ShouldBeNil)
  236. c := cmdConfig{
  237. name: "run-ls",
  238. upstreamURL: "http://mirrors.tuna.moe/",
  239. command: "ls",
  240. workingDir: tmpDir,
  241. logDir: tmpDir,
  242. logFile: "/dev/null",
  243. interval: 600 * time.Second,
  244. }
  245. provider, err := newCmdProvider(c)
  246. So(err, ShouldBeNil)
  247. So(provider.IsMaster(), ShouldEqual, false)
  248. So(provider.ZFS(), ShouldBeNil)
  249. So(provider.Type(), ShouldEqual, provCommand)
  250. So(provider.Name(), ShouldEqual, c.name)
  251. So(provider.WorkingDir(), ShouldEqual, c.workingDir)
  252. So(provider.LogDir(), ShouldEqual, c.logDir)
  253. So(provider.LogFile(), ShouldEqual, c.logFile)
  254. So(provider.Interval(), ShouldEqual, c.interval)
  255. Convey("Run the command", func() {
  256. err = provider.Run()
  257. So(err, ShouldBeNil)
  258. })
  259. })
  260. }
  261. func TestTwoStageRsyncProvider(t *testing.T) {
  262. Convey("TwoStageRsync Provider should work", t, func(ctx C) {
  263. tmpDir, err := ioutil.TempDir("", "tunasync")
  264. defer os.RemoveAll(tmpDir)
  265. So(err, ShouldBeNil)
  266. scriptFile := filepath.Join(tmpDir, "myrsync")
  267. tmpFile := filepath.Join(tmpDir, "log_file")
  268. c := twoStageRsyncConfig{
  269. name: "tuna-two-stage-rsync",
  270. upstreamURL: "rsync://mirrors.tuna.moe/",
  271. stage1Profile: "debian",
  272. rsyncCmd: scriptFile,
  273. workingDir: tmpDir,
  274. logDir: tmpDir,
  275. logFile: tmpFile,
  276. useIPv6: true,
  277. excludeFile: tmpFile,
  278. username: "hello",
  279. password: "world",
  280. }
  281. provider, err := newTwoStageRsyncProvider(c)
  282. So(err, ShouldBeNil)
  283. So(provider.Type(), ShouldEqual, provTwoStageRsync)
  284. So(provider.Name(), ShouldEqual, c.name)
  285. So(provider.WorkingDir(), ShouldEqual, c.workingDir)
  286. So(provider.LogDir(), ShouldEqual, c.logDir)
  287. So(provider.LogFile(), ShouldEqual, c.logFile)
  288. So(provider.Interval(), ShouldEqual, c.interval)
  289. Convey("Try a command", func(ctx C) {
  290. scriptContent := `#!/bin/bash
  291. echo "syncing to $(pwd)"
  292. echo $@
  293. sleep 1
  294. echo "Done"
  295. exit 0
  296. `
  297. err = ioutil.WriteFile(scriptFile, []byte(scriptContent), 0755)
  298. So(err, ShouldBeNil)
  299. err = provider.Run()
  300. So(err, ShouldBeNil)
  301. targetDir, _ := filepath.EvalSymlinks(provider.WorkingDir())
  302. expectedOutput := fmt.Sprintf(
  303. "syncing to %s\n"+
  304. "%s\n"+
  305. "Done\n"+
  306. "syncing to %s\n"+
  307. "%s\n"+
  308. "Done\n",
  309. targetDir,
  310. fmt.Sprintf(
  311. "-aHvh --no-o --no-g --stats --exclude .~tmp~/ --safe-links "+
  312. "--timeout=120 --contimeout=120 --exclude dists/ -6 "+
  313. "--exclude-from %s %s %s",
  314. provider.excludeFile, provider.upstreamURL, provider.WorkingDir(),
  315. ),
  316. targetDir,
  317. fmt.Sprintf(
  318. "-aHvh --no-o --no-g --stats --exclude .~tmp~/ "+
  319. "--delete --delete-after --delay-updates --safe-links "+
  320. "--timeout=120 --contimeout=120 -6 --exclude-from %s %s %s",
  321. provider.excludeFile, provider.upstreamURL, provider.WorkingDir(),
  322. ),
  323. )
  324. loggedContent, err := ioutil.ReadFile(provider.LogFile())
  325. So(err, ShouldBeNil)
  326. So(string(loggedContent), ShouldEqual, expectedOutput)
  327. // fmt.Println(string(loggedContent))
  328. })
  329. Convey("Try terminating", func(ctx C) {
  330. scriptContent := `#!/bin/bash
  331. echo $@
  332. sleep 4
  333. exit 0
  334. `
  335. err = ioutil.WriteFile(scriptFile, []byte(scriptContent), 0755)
  336. So(err, ShouldBeNil)
  337. go func() {
  338. err = provider.Run()
  339. ctx.So(err, ShouldNotBeNil)
  340. }()
  341. time.Sleep(1 * time.Second)
  342. err = provider.Terminate()
  343. So(err, ShouldBeNil)
  344. expectedOutput := fmt.Sprintf(
  345. "-aHvh --no-o --no-g --stats --exclude .~tmp~/ --safe-links "+
  346. "--timeout=120 --contimeout=120 --exclude dists/ -6 "+
  347. "--exclude-from %s %s %s\n",
  348. provider.excludeFile, provider.upstreamURL, provider.WorkingDir(),
  349. )
  350. loggedContent, err := ioutil.ReadFile(provider.LogFile())
  351. So(err, ShouldBeNil)
  352. So(string(loggedContent), ShouldEqual, expectedOutput)
  353. // fmt.Println(string(loggedContent))
  354. })
  355. })
  356. }