diff --git a/daemon/daemon_test.go b/daemon/daemon_test.go index 7f9a657d1..e4b9b23e8 100644 --- a/daemon/daemon_test.go +++ b/daemon/daemon_test.go @@ -285,8 +285,8 @@ func TestRPCClient_StopServer(t *testing.T) { log.Fatal("rpc error:", err) } - if res.Pid == cmd.Process.Pid { - t.Fatalf("Expected PID to match request but got: %d", res.Pid) + if res.Pid != cmd.Process.Pid { + t.Fatalf("Expected PID to match request %d but got: %d", cmd.Process.Pid, res.Pid) } if res.Port != 0 { diff --git a/daemon/service.go b/daemon/service.go index 0b38c3aff..2b8f2e819 100644 --- a/daemon/service.go +++ b/daemon/service.go @@ -3,7 +3,6 @@ package daemon import ( "bufio" "fmt" - "log" "os" "os/exec" ) @@ -23,6 +22,7 @@ type ServiceManager struct { Command string processes map[int]*exec.Cmd Args []string + Env []string commandCompleteChan chan *exec.Cmd commandCreatedChan chan *exec.Cmd } @@ -43,8 +43,9 @@ func (s *ServiceManager) addServiceMonitor() { for { select { case p := <-s.commandCreatedChan: - log.Printf("Adding service with pid: %d", p.Process.Pid) - s.processes[p.Process.Pid] = p + if p != nil && p.Process != nil { + s.processes[p.Process.Pid] = p + } } } } @@ -55,9 +56,10 @@ func (s *ServiceManager) removeServiceMonitor() { for { select { case p = <-s.commandCompleteChan: - log.Println("Removing service with pid: ", p.Process.Pid) - p.Process.Signal(os.Interrupt) - delete(s.processes, p.Process.Pid) + if p != nil && p.Process != nil { + p.Process.Signal(os.Interrupt) + delete(s.processes, p.Process.Pid) + } } } } @@ -88,6 +90,7 @@ func (s *ServiceManager) List() map[int]*exec.Cmd { // Start a Service and log its output. func (s *ServiceManager) Start() *exec.Cmd { cmd := exec.Command(s.Command, s.Args...) + cmd.Env = s.Env cmdReader, err := cmd.StdoutPipe() if err != nil { diff --git a/daemon/service_test.go b/daemon/service_test.go index 9d3072094..180e98aa1 100644 --- a/daemon/service_test.go +++ b/daemon/service_test.go @@ -1 +1,174 @@ package daemon + +import ( + "fmt" + "os" + "os/exec" + "reflect" + "testing" + "time" +) + +var channelTimeout = time.After(50 * time.Millisecond) + +func createServiceManager() *ServiceManager { + cs := []string{"-test.run=TestHelperProcess", "--", os.Args[0]} + env := []string{"GO_WANT_HELPER_PROCESS=1", fmt.Sprintf("GO_WANT_HELPER_PROCESS_TO_SUCCEED=true")} + mgr := &ServiceManager{ + Command: os.Args[0], + Args: cs, + Env: env, + } + mgr.Setup() + return mgr +} + +func TestServiceManager(t *testing.T) { + var manager interface{} + manager = new(ServiceManager) + + if _, ok := manager.(*ServiceManager); !ok { + t.Fatalf("Must be a ServiceManager") + } +} + +func TestServiceManager_Setup(t *testing.T) { + mgr := createServiceManager() + + if mgr.commandCompleteChan == nil { + t.Fatalf("Expected commandCompleteChan to be non-nil but got nil") + } + + if mgr.commandCreatedChan == nil { + t.Fatalf("Expected commandCreatedChan to be non-nil but got nil") + } +} + +func TestServiceManager_removeServiceMonitor(t *testing.T) { + mgr := createServiceManager() + cmd := fakeExecCommand("", true, "") + cmd.Start() + mgr.processes = map[int]*exec.Cmd{ + cmd.Process.Pid: cmd, + } + + mgr.commandCompleteChan <- cmd + + for { + select { + case <-time.After(10 * time.Millisecond): + if len(mgr.processes) == 0 { + return + } + case <-channelTimeout: + if len(mgr.processes) != 0 { + t.Fatalf(`Expected 1 command to be removed from the queue. + Timed out after 500millis`) + } + } + } +} + +func TestServiceManager_addServiceMonitor(t *testing.T) { + mgr := createServiceManager() + cmd := fakeExecCommand("", true, "") + cmd.Start() + mgr.commandCreatedChan <- cmd + + for { + select { + case <-time.After(10 * time.Millisecond): + if len(mgr.processes) == 1 { + return + } + case <-channelTimeout: + if len(mgr.processes) != 1 { + t.Fatalf(`Expected 1 command to be added to the queue, but got: %d. + Timed out after 500millis`, len(mgr.processes)) + } + return + } + } +} + +func TestServiceManager_addServiceMonitorWithDeadJob(t *testing.T) { + mgr := createServiceManager() + cmd := fakeExecCommand("", true, "") + mgr.commandCreatedChan <- cmd + + attempts := 0 + for { + select { + case <-time.After(10 * time.Millisecond): + if len(mgr.processes) != 0 { + t.Fatalf(`Expected 0 command to be added to the queue, but got: %d. + Timed out after 5 attempts`, len(mgr.processes)) + } + attempts++ + if attempts == 5 { + return + } + } + } +} + +func TestServiceManager_Stop(t *testing.T) { + mgr := createServiceManager() + cmd := fakeExecCommand("", true, "") + cmd.Start() + mgr.processes = map[int]*exec.Cmd{ + cmd.Process.Pid: cmd, + } + + mgr.Stop(cmd.Process.Pid) + + for { + select { + case <-time.After(10 * time.Millisecond): + if len(mgr.processes) == 0 { + return + } + case <-channelTimeout: + if len(mgr.processes) != 0 { + t.Fatalf(`Expected 1 command to be removed from the queue. + Timed out after 500millis`) + } + return + } + } +} + +func TestServiceManager_List(t *testing.T) { + mgr := createServiceManager() + cmd := fakeExecCommand("", true, "") + cmd.Start() + processes := map[int]*exec.Cmd{ + cmd.Process.Pid: cmd, + } + mgr.processes = processes + + if !reflect.DeepEqual(processes, mgr.List()) { + t.Fatalf("Expected mgr.List() to equal processes") + } +} + +func TestServiceManager_Start(t *testing.T) { + mgr := createServiceManager() + mgr.Start() + + for { + select { + case <-time.After(10 * time.Millisecond): + if len(mgr.processes) == 1 { + return + } + case <-channelTimeout: + if len(mgr.processes) != 1 { + t.Fatalf(`Expected 1 command to be added to the queue, but got: %d. + Timed out after 500millis`, len(mgr.processes)) + } + return + } + } + +}