package worker import ( "io/ioutil" "os" "path/filepath" "strings" "testing" "time" . "github.com/smartystreets/goconvey/convey" ) func TestCgroup(t *testing.T) { Convey("Cgroup Should Work", t, func(ctx C) { tmpDir, err := ioutil.TempDir("", "tunasync") defer os.RemoveAll(tmpDir) So(err, ShouldBeNil) cmdScript := filepath.Join(tmpDir, "cmd.sh") daemonScript := filepath.Join(tmpDir, "daemon.sh") tmpFile := filepath.Join(tmpDir, "log_file") bgPidfile := filepath.Join(tmpDir, "bg.pid") c := cmdConfig{ name: "tuna-cgroup", upstreamURL: "http://mirrors.tuna.moe/", command: cmdScript + " " + daemonScript, workingDir: tmpDir, logDir: tmpDir, logFile: tmpFile, interval: 600 * time.Second, env: map[string]string{ "BG_PIDFILE": bgPidfile, }, } cmdScriptContent := `#!/bin/bash redirect-std() { [[ -t 0 ]] && exec /dev/null [[ -t 2 ]] && exec 2>/dev/null } # close all non-std* fds close-fds() { eval exec {3..255}\>\&- } # full daemonization of external command with setsid daemonize() { ( redirect-std cd / close-fds exec setsid "$@" ) & } echo $$ daemonize $@ sleep 5 ` daemonScriptContent := `#!/bin/bash echo $$ > $BG_PIDFILE sleep 30 ` err = ioutil.WriteFile(cmdScript, []byte(cmdScriptContent), 0755) So(err, ShouldBeNil) err = ioutil.WriteFile(daemonScript, []byte(daemonScriptContent), 0755) So(err, ShouldBeNil) provider, err := newCmdProvider(c) So(err, ShouldBeNil) cg := newCgroupHook(provider, "/sys/fs/cgroup", "tunasync") provider.AddHook(cg) err = cg.preExec() So(err, ShouldBeNil) go func() { err = provider.Run() ctx.So(err, ShouldNotBeNil) }() time.Sleep(1 * time.Second) // Deamon should be started daemonPidBytes, err := ioutil.ReadFile(bgPidfile) So(err, ShouldBeNil) daemonPid := strings.Trim(string(daemonPidBytes), " \n") logger.Debug("daemon pid: %s", daemonPid) procDir := filepath.Join("/proc", daemonPid) _, err = os.Stat(procDir) So(err, ShouldBeNil) err = provider.Terminate() So(err, ShouldBeNil) // Deamon won't be killed _, err = os.Stat(procDir) So(err, ShouldBeNil) // Deamon can be killed by cgroup killer cg.postExec() _, err = os.Stat(procDir) So(os.IsNotExist(err), ShouldBeTrue) }) }