Skip to content

Commit

Permalink
test(daemon): RPC Client error tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mefellows committed Jun 4, 2016
1 parent 7d8a0fd commit 3b859cf
Show file tree
Hide file tree
Showing 9 changed files with 127 additions and 46 deletions.
2 changes: 1 addition & 1 deletion command/pact_mock_service_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ var mockServiceCmd = &cobra.Command{
// Start the service
svcManager := &daemon.PactMockService{}
svcManager.Setup()
_, svc := svcManager.NewService()
_, svc := svcManager.NewService([]string{})
svc.Start()

// Block until a signal is received.
Expand Down
7 changes: 0 additions & 7 deletions command/pact_mock_service_cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,9 @@ package command

import "testing"

func init() {
// os.Args = append(os.Args, "mock")
// os.Args = append(os.Args, "--help")
}

func Test_PactMockServiceCommand(t *testing.T) {
err := mockServiceCmd.Help()
if err != nil {
t.Fatalf("Error: %v", err)
}

// mockServiceCmd.Run(nil, os.Args)
}
3 changes: 2 additions & 1 deletion daemon/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ type PactMockServer struct {
Pid int
Port int
Status int
Args []string
}

// PublishRequest contains the details required to Publish Pacts to a broker.
Expand Down Expand Up @@ -121,7 +122,7 @@ func (d *Daemon) Shutdown() {
// struct.
func (d *Daemon) StartServer(request *PactMockServer, reply *PactMockServer) error {
server := &PactMockServer{}
port, svc := d.pactMockSvcManager.NewService()
port, svc := d.pactMockSvcManager.NewService(request.Args)
server.Port = port
cmd := svc.Start()
server.Pid = cmd.Process.Pid
Expand Down
3 changes: 2 additions & 1 deletion daemon/pact_mock_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ type PactMockService struct {
}

// NewService creates a new PactMockService with default settings.
func (m *PactMockService) NewService() (int, Service) {
func (m *PactMockService) NewService(args []string) (int, Service) {
port, _ := utils.GetFreePort()
// version := 2
// dir, _ := os.Getwd()
Expand All @@ -30,6 +30,7 @@ func (m *PactMockService) NewService() (int, Service) {
// fmt.Sprintf("--log-dir %s", logDir),
// fmt.Sprintf("--ssl"),
}
m.Args = append(m.Args, args...)
m.Command = getCommandPath()
return port, m
}
Expand Down
2 changes: 1 addition & 1 deletion daemon/pact_mock_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import "testing"

func TestNewService(t *testing.T) {
s := &PactMockService{}
port, svc := s.NewService()
port, svc := s.NewService([]string{})

if port <= 0 {
t.Fatalf("Expected non-zero port but got: %d", port)
Expand Down
2 changes: 1 addition & 1 deletion daemon/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ type Service interface {
Stop(pid int) (bool, error)
List() map[int]*exec.Cmd
Start() *exec.Cmd
NewService() (int, Service)
NewService(args []string) (int, Service)
}

// ServiceManager is the default implementation of the Service interface.
Expand Down
2 changes: 1 addition & 1 deletion daemon/service_mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,6 @@ func (s *ServiceMock) Start() *exec.Cmd {
}

// NewService creates a new MockService with default settings.
func (s *ServiceMock) NewService() (int, Service) {
func (s *ServiceMock) NewService(args []string) (int, Service) {
return s.ServicePort, s
}
58 changes: 40 additions & 18 deletions dsl/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"github.com/mefellows/pact-go/daemon"
)

var timeoutDuration = 1 * time.Second

// Client is the simplified remote interface to the Pact Daemon
type Client interface {
StartServer() *daemon.PactMockServer
Expand All @@ -22,24 +24,28 @@ type PactClient struct {
}

func getHTTPClient(port int) (*rpc.Client, error) {
waitForPort(port)
err := waitForPort(port)
if err != nil {
return nil, err
}
return rpc.DialHTTP("tcp", fmt.Sprintf(":%d", port))
}

// Use this to wait for a daemon to be running prior
// to running tests
func waitForPort(port int) {
func waitForPort(port int) error {
fmt.Printf("client - Waiting for daemon port: %d", port)
timeout := time.After(10 * time.Second)
timeout := time.After(timeoutDuration)

for {
select {
case <-timeout:
log.Fatalf("Expected server to start < 1s.")
log.Printf("Expected server to start < %s", timeoutDuration)
return fmt.Errorf("Expected server to start < %s", timeoutDuration)
case <-time.After(50 * time.Millisecond):
_, err := net.Dial("tcp", fmt.Sprintf(":%d", port))
if err == nil {
return
return nil
}
}
}
Expand All @@ -49,12 +55,11 @@ func waitForPort(port int) {
func (p *PactClient) StartServer() *daemon.PactMockServer {
var res daemon.PactMockServer
client, err := getHTTPClient(p.Port)
if err != nil {
log.Fatal("rpc error:", err)
}
err = client.Call("Daemon.StartServer", daemon.PactMockServer{}, &res)
if err != nil {
log.Fatal("rpc error:", err)
if err == nil {
err = client.Call("Daemon.StartServer", daemon.PactMockServer{}, &res)
if err != nil {
log.Fatal("rpc error:", err)
}
}
return &res
}
Expand All @@ -63,20 +68,37 @@ func (p *PactClient) StartServer() *daemon.PactMockServer {
func (p *PactClient) ListServers() *daemon.PactListResponse {
var res daemon.PactListResponse
client, err := getHTTPClient(p.Port)
err = client.Call("Daemon.ListServers", daemon.PactMockServer{}, &res)
if err != nil {
log.Fatal("rpc error:", err)
if err == nil {
err = client.Call("Daemon.ListServers", daemon.PactMockServer{}, &res)
if err != nil {
log.Fatal("rpc error:", err)
}
}
return &res
}

// StopServer stops a remote Pact Mock Server.
func (p *PactClient) StopServer(server *daemon.PactMockServer) *daemon.PactMockServer {
client, err := getHTTPClient(p.Port)
var res daemon.PactMockServer
err = client.Call("Daemon.StopServer", server, &res)
if err != nil {
log.Fatal("rpc error:", err)
client, err := getHTTPClient(p.Port)
if err == nil {
err = client.Call("Daemon.StopServer", server, &res)
if err != nil {
log.Fatal("rpc error:", err)
}
}
return &res
}

// StopDaemon remotely shuts down the Pact Daemon.
func (p *PactClient) StopDaemon() error {
var req, res string
client, err := getHTTPClient(p.Port)
if err == nil {
err = client.Call("Daemon.StopDaemon", &req, &res)
if err != nil {
log.Fatal("rpc error:", err)
}
}
return err
}
94 changes: 79 additions & 15 deletions dsl/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"net/rpc"
"os"
"os/exec"
"reflect"
"testing"
"time"

Expand Down Expand Up @@ -35,19 +36,16 @@ func waitForPortInTest(port int, t *testing.T) {
func waitForDaemonToShutdown(port int, t *testing.T) {
req := ""
res := ""
// var req interface{}

waitForPortInTest(port, t)

fmt.Println("Sending remote shutdown signal...")
client, err := rpc.DialHTTP("tcp", fmt.Sprintf(":%d", port))

err = client.Call("Daemon.StopDaemon", &req, &res)
// err = client.Call("Daemon.StopDaemon", req, &res)
if err != nil {
log.Fatal("rpc error:", err)
}
fmt.Println(res)

t.Logf("Waiting for deamon to shutdown before next test")
timeout := time.After(1 * time.Second)
Expand All @@ -72,7 +70,8 @@ func waitForDaemonToShutdown(port int, t *testing.T) {
}

// This guy mocks out the underlying Service provider in the Daemon,
// but executes actual Daemon code.
// but executes actual Daemon code. This means we don't spin up the real
// mock service but execute our code in isolation.
//
// Stubbing the exec.Cmd interface is hard, see fakeExec* functions for
// the magic.
Expand Down Expand Up @@ -108,44 +107,109 @@ func createDaemon(port int) (*daemon.Daemon, *daemon.ServiceMock) {
return d, svc
}

// func TestClient_Fail(t *testing.T) {
// client := NewPactClient{ /* don't supply port */ }
//
// }

// Integration style test: Can a client hit each endpoint?
func TestRPCClient_List(t *testing.T) {
func TestClient_List(t *testing.T) {
port, _ := utils.GetFreePort()
createDaemon(port)
waitForPortInTest(port, t)
defer waitForDaemonToShutdown(port, t)
client := &PactClient{Port: port}

waitForPortInTest(port, t)

s := client.ListServers()

if len(s.Servers) != 3 {
t.Fatalf("Expected 3 server to be running, got %d", len(s.Servers))
}
}

func TestClient_ListFail(t *testing.T) {
timeoutDuration = 50 * time.Millisecond
client := &PactClient{ /* don't supply port */ }
client.StartServer()
list := client.ListServers()

if len(list.Servers) != 0 {
t.Fatalf("Expected 0 servers, got %d", len(list.Servers))
}
timeoutDuration = oldTimeoutDuration
}

// Integration style test: Can a client hit each endpoint?
func TestRPCClient_StartServer(t *testing.T) {
func TestClient_StartServer(t *testing.T) {
port, _ := utils.GetFreePort()
_, svc := createDaemon(port)
waitForPortInTest(port, t)
defer waitForDaemonToShutdown(port, t)
client := &PactClient{Port: port}

waitForPortInTest(port, t)

client.StartServer()
if svc.ServiceStartCount != 1 {
t.Fatalf("Expected 1 server to have been started, got %d", svc.ServiceStartCount)
}
}

var oldTimeoutDuration = timeoutDuration

func TestClient_StartServerFail(t *testing.T) {
timeoutDuration = 50 * time.Millisecond

client := &PactClient{ /* don't supply port */ }
server := client.StartServer()
if server.Port != 0 {
t.Fatalf("Expected server to be empty %v", server)
}
timeoutDuration = oldTimeoutDuration
}

// Integration style test: Can a client hit each endpoint?
func TestClient_StopServer(t *testing.T) {
port, _ := utils.GetFreePort()
_, svc := createDaemon(port)
waitForPortInTest(port, t)
defer waitForDaemonToShutdown(port, t)
client := &PactClient{Port: port}

client.StopServer(&daemon.PactMockServer{})
if svc.ServiceStopCount != 1 {
t.Fatalf("Expected 1 server to have been stopped, got %d", svc.ServiceStartCount)
}
}

func TestClient_StopServerFail(t *testing.T) {
timeoutDuration = 50 * time.Millisecond
client := &PactClient{ /* don't supply port */ }
res := client.StopServer(&daemon.PactMockServer{})
should := &daemon.PactMockServer{}
if !reflect.DeepEqual(res, should) {
t.Fatalf("Expected nil object but got a difference: %v != %v", res, should)
}
timeoutDuration = oldTimeoutDuration
}

// Integration style test: Can a client hit each endpoint?
func TestClient_StopDaemon(t *testing.T) {
port, _ := utils.GetFreePort()
createDaemon(port)
waitForPortInTest(port, t)
client := &PactClient{Port: port}

err := client.StopDaemon()
if err != nil {
t.Fatalf("Err: %v", err)
}
waitForDaemonToShutdown(port, t)
}

func TestClient_StopDaemonFail(t *testing.T) {
timeoutDuration = 50 * time.Millisecond
client := &PactClient{ /* don't supply port */ }
err := client.StopDaemon()
if err == nil {
t.Fatalf("Expected error but got none")
}
timeoutDuration = oldTimeoutDuration
}

// Adapted from http://npf.io/2015/06/testing-exec-command/
var fakeExecSuccessCommand = func() *exec.Cmd {
return fakeExecCommand("", true, "")
Expand Down

0 comments on commit 3b859cf

Please sign in to comment.