Skip to content

Commit

Permalink
test(daemon): daemon testing
Browse files Browse the repository at this point in the history
  • Loading branch information
mefellows committed Jun 4, 2016
1 parent ddb127d commit 345cd9f
Show file tree
Hide file tree
Showing 5 changed files with 191 additions and 54 deletions.
59 changes: 31 additions & 28 deletions daemon/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ type VerifyRequest struct{}
// Daemon wraps the commands for the RPC server.
type Daemon struct {
pactMockSvcManager Service
signalChan chan os.Signal
}

// NewDaemon returns a new Daemon with all instance variables initialised.
Expand All @@ -59,13 +60,42 @@ func NewDaemon(pactMockServiceManager Service) *Daemon {

return &Daemon{
pactMockSvcManager: pactMockServiceManager,
signalChan: make(chan os.Signal, 1),
}
}

// StartDaemon starts the daemon RPC server.
func (d *Daemon) StartDaemon() {
fmt.Println("Starting daemon on port 6666")
rpc.Register(d)
rpc.HandleHTTP()

// Start daemon in background
go func() {
l, e := net.Listen("tcp", ":6666")
if e != nil {
log.Fatal("listen error:", e)
}
http.Serve(l, nil)
}()

d.pactMockSvcManager.Start()

// Wait for sigterm
signal.Notify(d.signalChan, os.Interrupt, os.Kill)
s := <-d.signalChan
fmt.Println("Got signal:", s, ". Shutting down all services")

d.Shutdown()
fmt.Println("done")
}

// Shutdown ensures all services are cleanly destroyed.
func (d *Daemon) Shutdown() {
for _, s := range d.pactMockSvcManager.List() {
d.pactMockSvcManager.Stop(s.Process.Pid)
if s != nil {
d.pactMockSvcManager.Stop(s.Process.Pid)
}
}
}

Expand Down Expand Up @@ -113,30 +143,3 @@ func (d *Daemon) Verify(request *VerifyRequest, reply *PactResponse) error {
}
return nil
}

// StartDaemon starts the daemon RPC server.
func (d *Daemon) StartDaemon() {
fmt.Println("Starting daemon on port 6666")
rpc.Register(d)
rpc.HandleHTTP()

// Start daemon in background
go func() {
l, e := net.Listen("tcp", ":6666")
if e != nil {
log.Fatal("listen error:", e)
}
http.Serve(l, nil)
}()

d.pactMockSvcManager.Start()

// Wait for sigterm
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt, os.Kill)
s := <-c
fmt.Println("Got signal:", s, ". Shutting down all services")

d.Shutdown()
fmt.Println("done")
}
136 changes: 113 additions & 23 deletions daemon/daemon_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,52 +2,142 @@ package daemon

import (
"fmt"
"net"
"os"
"os/exec"
"reflect"
"testing"
"time"
)

type MockService struct {
// func createDefaultDaemon() {
// getCommandPath = func() string {
// dir, _ := os.Getwd()
// return fmt.Sprintf(filepath.Join(dir, "../", "pact-mock-service", "bin", "pact-mock-service"))
// }
// }

// type MockService struct {
// }
//
// func (r MockService) Run(command string, args ...string) ([]byte, error) {
// cs := []string{"-test.run=TestHelperProcess", "--"}
// cs = append(cs, args...)
// cmd := exec.Command(os.Args[0], cs...)
// cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"}
// out, err := cmd.CombinedOutput()
// return out, err
// }
//
// func TestHello(t *testing.T) {
// runner = MockService{}
// out := Hello()
// if out == "testing helper process" {
// t.Logf("out was eq to %s", string(out))
// }
// }
//
// func TestHelperProcess(*testing.T) {
// if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" {
// return
// }
// defer os.Exit(0)
// fmt.Println("testing helper process")
// }

func createMockedDaemon() *Daemon {
svc := &ServiceMock{
Command: "test",
Args: []string{},
ServiceStopResult: true,
ServiceStopError: nil,
ServiceList: map[int]*exec.Cmd{
1: fakeExecCommand("", true, ""),
2: fakeExecCommand("", true, ""),
3: fakeExecCommand("", true, ""),
},
ServiceStartCmd: nil,
}
return NewDaemon(svc)
}

func (r MockService) Run(command string, args ...string) ([]byte, error) {
cs := []string{"-test.run=TestHelperProcess", "--"}
cs = append(cs, args...)
cmd := exec.Command(os.Args[0], cs...)
cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"}
out, err := cmd.CombinedOutput()
return out, err
func TestNewDaemon(t *testing.T) {
var daemon interface{}
daemon = createMockedDaemon()

if _, ok := daemon.(Daemon); !ok {
t.Fatalf("must be a Daemon")
}
}

func TestHello(t *testing.T) {
runner = MockService{}
out := Hello()
if out == "testing helper process" {
t.Logf("out was eq to %s", string(out))
func TestStartAndStopDaemon(t *testing.T) {
daemon := createMockedDaemon()
go daemon.StartDaemon()

for {
select {
case <-time.After(1 * time.Second):
t.Fatalf("Expected server to start < 1s.")
case <-time.After(50 * time.Millisecond):
_, err := net.Dial("tcp", ":6666")
if err == nil {
daemon.signalChan <- os.Interrupt
return
}
}
}
}

func TestHelperProcess(*testing.T) {
// Adapted from http://npf.io/2015/06/testing-exec-command/
func fakeExecCommand(command string, success bool, args ...string) *exec.Cmd {
cs := []string{"-test.run=TestHelperProcess", "--", command}
cs = append(cs, args...)
cmd := exec.Command(os.Args[0], cs...)
cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1", fmt.Sprintf("GO_WANT_HELPER_PROCESS_TO_SUCCEED=%t", success)}
return cmd
}

func TestHelperProcess(t *testing.T) {
fmt.Fprintln(os.Stdout, "HELLLlloooo")
<-time.After(30 * time.Second)
if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" {
return
}
defer os.Exit(0)
fmt.Println("testing helper process")

// some code here to check arguments perhaps?
// Fail :(
if os.Getenv("GO_WANT_HELPER_PROCESS_TO_SUCCEED") == "false" {
os.Exit(1)
}

// Success :)
os.Exit(0)
}

func TestStartDaemon(t *testing.T) {
func TestDaemonShutdown(t *testing.T) {
daemon := createMockedDaemon()
manager := daemon.pactMockSvcManager.(*ServiceMock)

// Start all processes to get the Pids!
for _, s := range manager.ServiceList {
s.Start()
}

daemon.Shutdown()

if manager.ServiceStopCount != 3 {
t.Fatalf("Expected Stop() to be called 3 times but got: %d", manager.ServiceStopCount)
}
}

func TestStartDaemon_Fail(t *testing.T) {

}

func TestStartServer(t *testing.T) {
daemon := CreateDaemon()
req := MockServer{Pid: 1234}
res := MockServer{}
daemon := createMockedDaemon()
req := PactMockServer{Pid: 1234}
res := PactMockServer{}
err := daemon.StartServer(&req, &res)
if err != nil {
t.Fatalf("Error: %v", err)
Expand All @@ -60,7 +150,7 @@ func TestStartServer(t *testing.T) {

func TestListServers(t *testing.T) {
daemon := &Daemon{}
var res []MockServer
var res []PactMockServer
err := daemon.ListServers(nil, &res)
if err != nil {
t.Fatalf("Error: %v", err)
Expand All @@ -74,8 +164,8 @@ func TestListServers(t *testing.T) {
func TestStopServer(t *testing.T) {
daemon := &Daemon{}

req := MockServer{Pid: 1234}
res := MockServer{}
req := PactMockServer{Pid: 1234}
res := PactMockServer{}
err := daemon.StopServer(&req, &res)
if err != nil {
t.Fatalf("Error: %v", err)
Expand Down
6 changes: 3 additions & 3 deletions daemon/pact_mock_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ func TestNewService(t *testing.T) {
t.Fatalf("Expected a non-nil object but got nil")
}

if len(svc.Args) != 1 {
t.Fatalf("Expected 1 argument (--port) but got: %d", len(svc.Args))
}
// if len(svc.Args) != 1 {
// t.Fatalf("Expected 1 argument (--port) but got: %d", len(svc.Args))
// }
}
43 changes: 43 additions & 0 deletions daemon/service_mock.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package daemon

import "os/exec"

// ServiceMock is the mock implementation of the Service interface.
type ServiceMock struct {
Command string
processes map[int]*exec.Cmd
Args []string
ServiceStopResult bool
ServiceStopError error
ServiceList map[int]*exec.Cmd
ServiceStartCmd *exec.Cmd
ServicePort int
ServiceStopCount int
ServicesSetupCalled bool
}

// Setup the Management services.
func (s *ServiceMock) Setup() {
s.ServicesSetupCalled = true
}

// Stop a Service and returns the exit status.
func (s *ServiceMock) Stop(pid int) (bool, error) {
s.ServiceStopCount++
return s.ServiceStopResult, s.ServiceStopError
}

// List all Service PIDs.
func (s *ServiceMock) List() map[int]*exec.Cmd {
return s.ServiceList
}

// Start a Service and log its output.
func (s *ServiceMock) Start() *exec.Cmd {
return s.ServiceStartCmd
}

// NewService creates a new MockService with default settings.
func (s *ServiceMock) NewService() (int, Service) {
return s.ServicePort, s
}
1 change: 1 addition & 0 deletions daemon/service_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package daemon

0 comments on commit 345cd9f

Please sign in to comment.