2
0

cgroup_test.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. package worker
  2. import (
  3. "io/ioutil"
  4. "os"
  5. "path/filepath"
  6. "strconv"
  7. "strings"
  8. "testing"
  9. "time"
  10. . "github.com/smartystreets/goconvey/convey"
  11. )
  12. func TestCgroup(t *testing.T) {
  13. Convey("Cgroup Should Work", t, func(ctx C) {
  14. tmpDir, err := ioutil.TempDir("", "tunasync")
  15. defer os.RemoveAll(tmpDir)
  16. So(err, ShouldBeNil)
  17. cmdScript := filepath.Join(tmpDir, "cmd.sh")
  18. daemonScript := filepath.Join(tmpDir, "daemon.sh")
  19. tmpFile := filepath.Join(tmpDir, "log_file")
  20. bgPidfile := filepath.Join(tmpDir, "bg.pid")
  21. c := cmdConfig{
  22. name: "tuna-cgroup",
  23. upstreamURL: "http://mirrors.tuna.moe/",
  24. command: cmdScript + " " + daemonScript,
  25. workingDir: tmpDir,
  26. logDir: tmpDir,
  27. logFile: tmpFile,
  28. interval: 600 * time.Second,
  29. env: map[string]string{
  30. "BG_PIDFILE": bgPidfile,
  31. },
  32. }
  33. cmdScriptContent := `#!/bin/bash
  34. redirect-std() {
  35. [[ -t 0 ]] && exec </dev/null
  36. [[ -t 1 ]] && exec >/dev/null
  37. [[ -t 2 ]] && exec 2>/dev/null
  38. }
  39. # close all non-std* fds
  40. close-fds() {
  41. eval exec {3..255}\>\&-
  42. }
  43. # full daemonization of external command with setsid
  44. daemonize() {
  45. (
  46. redirect-std
  47. cd /
  48. close-fds
  49. exec setsid "$@"
  50. ) &
  51. }
  52. echo $$
  53. daemonize $@
  54. sleep 5
  55. `
  56. daemonScriptContent := `#!/bin/bash
  57. echo $$ > $BG_PIDFILE
  58. sleep 30
  59. `
  60. err = ioutil.WriteFile(cmdScript, []byte(cmdScriptContent), 0755)
  61. So(err, ShouldBeNil)
  62. err = ioutil.WriteFile(daemonScript, []byte(daemonScriptContent), 0755)
  63. So(err, ShouldBeNil)
  64. provider, err := newCmdProvider(c)
  65. So(err, ShouldBeNil)
  66. cg := newCgroupHook(provider, "/sys/fs/cgroup", "tunasync", "cpu", "")
  67. provider.AddHook(cg)
  68. err = cg.preExec()
  69. if err != nil {
  70. logger.Errorf("Failed to create cgroup")
  71. return
  72. }
  73. So(err, ShouldBeNil)
  74. go func() {
  75. err = provider.Run()
  76. ctx.So(err, ShouldNotBeNil)
  77. }()
  78. time.Sleep(1 * time.Second)
  79. // Deamon should be started
  80. daemonPidBytes, err := ioutil.ReadFile(bgPidfile)
  81. So(err, ShouldBeNil)
  82. daemonPid := strings.Trim(string(daemonPidBytes), " \n")
  83. logger.Debug("daemon pid: %s", daemonPid)
  84. procDir := filepath.Join("/proc", daemonPid)
  85. _, err = os.Stat(procDir)
  86. So(err, ShouldBeNil)
  87. err = provider.Terminate()
  88. So(err, ShouldBeNil)
  89. // Deamon won't be killed
  90. _, err = os.Stat(procDir)
  91. So(err, ShouldBeNil)
  92. // Deamon can be killed by cgroup killer
  93. cg.postExec()
  94. _, err = os.Stat(procDir)
  95. So(os.IsNotExist(err), ShouldBeTrue)
  96. })
  97. Convey("Rsync Memory Should Be Limited", t, func() {
  98. tmpDir, err := ioutil.TempDir("", "tunasync")
  99. defer os.RemoveAll(tmpDir)
  100. So(err, ShouldBeNil)
  101. scriptFile := filepath.Join(tmpDir, "myrsync")
  102. tmpFile := filepath.Join(tmpDir, "log_file")
  103. c := rsyncConfig{
  104. name: "tuna-cgroup",
  105. upstreamURL: "rsync://rsync.tuna.moe/tuna/",
  106. rsyncCmd: scriptFile,
  107. workingDir: tmpDir,
  108. logDir: tmpDir,
  109. logFile: tmpFile,
  110. useIPv6: true,
  111. interval: 600 * time.Second,
  112. }
  113. provider, err := newRsyncProvider(c)
  114. So(err, ShouldBeNil)
  115. cg := newCgroupHook(provider, "/sys/fs/cgroup", "tunasync", "cpu", "512M")
  116. provider.AddHook(cg)
  117. err = cg.preExec()
  118. if err != nil {
  119. logger.Errorf("Failed to create cgroup")
  120. return
  121. }
  122. if cg.subsystem == "memory" {
  123. memoLimit, err := ioutil.ReadFile(filepath.Join(cg.basePath, "memory", cg.baseGroup, provider.Name(), "memory.limit_in_bytes"))
  124. So(err, ShouldBeNil)
  125. So(strings.Trim(string(memoLimit), "\n"), ShouldEqual, strconv.Itoa(512*1024*1024))
  126. }
  127. cg.postExec()
  128. })
  129. }