Skip to content

Commit

Permalink
Add tests for controlsvc control types (#865)
Browse files Browse the repository at this point in the history
  • Loading branch information
resoluteCoder authored Oct 2, 2023
1 parent 5f5094f commit 45d7df5
Show file tree
Hide file tree
Showing 11 changed files with 595 additions and 69 deletions.
14 changes: 7 additions & 7 deletions pkg/controlsvc/connect.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ import (
)

type (
connectCommandType struct{}
connectCommand struct {
ConnectCommandType struct{}
ConnectCommand struct {
targetNode string
targetService string
tlsConfigName string
}
)

func (t *connectCommandType) InitFromString(params string) (ControlCommand, error) {
func (t *ConnectCommandType) InitFromString(params string) (ControlCommand, error) {
tokens := strings.Split(params, " ")
if len(tokens) < 2 {
return nil, fmt.Errorf("no connect target")
Expand All @@ -29,7 +29,7 @@ func (t *connectCommandType) InitFromString(params string) (ControlCommand, erro
if len(tokens) == 3 {
tlsConfigName = tokens[2]
}
c := &connectCommand{
c := &ConnectCommand{
targetNode: tokens[0],
targetService: tokens[1],
tlsConfigName: tlsConfigName,
Expand All @@ -38,7 +38,7 @@ func (t *connectCommandType) InitFromString(params string) (ControlCommand, erro
return c, nil
}

func (t *connectCommandType) InitFromJSON(config map[string]interface{}) (ControlCommand, error) {
func (t *ConnectCommandType) InitFromJSON(config map[string]interface{}) (ControlCommand, error) {
targetNode, ok := config["node"]
if !ok {
return nil, fmt.Errorf("no connect target node")
Expand All @@ -65,7 +65,7 @@ func (t *connectCommandType) InitFromJSON(config map[string]interface{}) (Contro
} else {
tlsConfigStr = ""
}
c := &connectCommand{
c := &ConnectCommand{
targetNode: targetNodeStr,
targetService: targetServiceStr,
tlsConfigName: tlsConfigStr,
Expand All @@ -74,7 +74,7 @@ func (t *connectCommandType) InitFromJSON(config map[string]interface{}) (Contro
return c, nil
}

func (c *connectCommand) ControlFunc(_ context.Context, nc NetceptorForControlCommand, cfo ControlFuncOperations) (map[string]interface{}, error) {
func (c *ConnectCommand) ControlFunc(_ context.Context, nc NetceptorForControlCommand, cfo ControlFuncOperations) (map[string]interface{}, error) {
tlscfg, err := nc.GetClientTLSConfig(c.tlsConfigName, c.targetNode, netceptor.ExpectedHostnameTypeReceptor)
if err != nil {
return nil, err
Expand Down
150 changes: 150 additions & 0 deletions pkg/controlsvc/connect_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
package controlsvc_test

import (
"context"
"errors"
"testing"

"github.com/ansible/receptor/pkg/controlsvc"
"github.com/ansible/receptor/pkg/controlsvc/mock_controlsvc"
"github.com/ansible/receptor/pkg/logger"
"github.com/golang/mock/gomock"
)

func CheckExpectedError(expectedError bool, errorMessage string, t *testing.T, err error) {
if expectedError && errorMessage != err.Error() {
t.Errorf("expected: %s , received: %s", errorMessage, err)
}

if !expectedError && err != nil {
t.Error(err)
}
}

func TestConnectInitFromString(t *testing.T) {
connectCommandType := controlsvc.ConnectCommandType{}

initFromStringTestCases := []struct {
name string
expectedError bool
errorMessage string
input string
}{
{
name: "no connect target",
expectedError: true,
errorMessage: "no connect target",
input: "",
},
{
name: "too many parameters",
expectedError: true,
errorMessage: "too many parameters",
input: "one two three four",
},
{
name: "three params - pass",
expectedError: false,
errorMessage: "",
input: "one two three",
},
}

for _, testCase := range initFromStringTestCases {
t.Run(testCase.name, func(t *testing.T) {
_, err := connectCommandType.InitFromString(testCase.input)

CheckExpectedError(testCase.expectedError, testCase.errorMessage, t, err)
})
}
}

func TestConnectInitFromJSON(t *testing.T) {
connectCommandType := controlsvc.ConnectCommandType{}

initFromJSONTestCases := []struct {
name string
expectedError bool
errorMessage string
input map[string]interface{}
}{
BuildInitFromJSONTestCases("no connect target node", true, "no connect target node", map[string]interface{}{}),
BuildInitFromJSONTestCases("connect target node must be string 1", true, "connect target node must be string", map[string]interface{}{"node": 7}),
BuildInitFromJSONTestCases("no connect target service", true, "no connect target service", map[string]interface{}{"node": "node1"}),
BuildInitFromJSONTestCases("connect target service must be string1", true, "connect target service must be string", map[string]interface{}{"node": "node2", "service": 7}),
BuildInitFromJSONTestCases("connect tls name be string", true, "connect tls name must be string", map[string]interface{}{"node": "node3", "service": "service1", "tls": 7}),
BuildInitFromJSONTestCases("pass with empty tls config", false, "connect target service must be string", map[string]interface{}{"node": "node4", "service": "service2"}),
BuildInitFromJSONTestCases("pass with all targets and tls config", false, "", map[string]interface{}{"node": "node4", "service": "service3", "tls": "tls1"}),
}

for _, testCase := range initFromJSONTestCases {
t.Run(testCase.name, func(t *testing.T) {
_, err := connectCommandType.InitFromJSON(testCase.input)
CheckExpectedError(testCase.expectedError, testCase.errorMessage, t, err)
})
}
}

func TestConnectControlFunc(t *testing.T) {
connectCommand := controlsvc.ConnectCommand{}
ctrl := gomock.NewController(t)
mockNetceptor := mock_controlsvc.NewMockNetceptorForControlsvc(ctrl)
mockControlFunc := mock_controlsvc.NewMockControlFuncOperations(ctrl)
logger := logger.NewReceptorLogger("")

controlFuncTestCases := []struct {
name string
expectedError bool
errorMessage string
expectedCalls func()
}{
{
name: "tls config error",
expectedError: true,
errorMessage: "terminated tls",
expectedCalls: func() {
mockNetceptor.EXPECT().GetClientTLSConfig(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, errors.New("terminated tls"))
},
},
{
name: "dial error",
errorMessage: "terminated dial",
expectedError: true,
expectedCalls: func() {
mockNetceptor.EXPECT().GetClientTLSConfig(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, nil)
mockNetceptor.EXPECT().Dial(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, errors.New("terminated dial"))
},
},
{
name: "bridge conn error",
errorMessage: "terminated bridge conn",
expectedError: true,
expectedCalls: func() {
mockNetceptor.EXPECT().GetClientTLSConfig(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, nil)
mockNetceptor.EXPECT().Dial(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, nil)
mockControlFunc.EXPECT().BridgeConn(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(errors.New("terminated bridge conn"))
mockNetceptor.EXPECT().GetLogger().Return(logger)
},
},
{
name: "control func pass",
errorMessage: "",
expectedError: false,
expectedCalls: func() {
mockNetceptor.EXPECT().GetClientTLSConfig(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, nil)
mockNetceptor.EXPECT().Dial(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, nil)
mockControlFunc.EXPECT().BridgeConn(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil)
mockNetceptor.EXPECT().GetLogger().Return(logger)
},
},
}

for _, testCase := range controlFuncTestCases {
t.Run(testCase.name, func(t *testing.T) {
testCase.expectedCalls()
_, err := connectCommand.ControlFunc(context.Background(), mockNetceptor, mockControlFunc)

CheckExpectedError(testCase.expectedError, testCase.errorMessage, t, err)
})
}
}
10 changes: 5 additions & 5 deletions pkg/controlsvc/controlsvc.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,11 @@ func New(stdServices bool, nc NetceptorForControlsvc) *Server {
serverTLS: &TLS{},
}
if stdServices {
s.controlTypes["ping"] = &pingCommandType{}
s.controlTypes["status"] = &statusCommandType{}
s.controlTypes["connect"] = &connectCommandType{}
s.controlTypes["traceroute"] = &tracerouteCommandType{}
s.controlTypes["reload"] = &reloadCommandType{}
s.controlTypes["ping"] = &PingCommandType{}
s.controlTypes["status"] = &StatusCommandType{}
s.controlTypes["connect"] = &ConnectCommandType{}
s.controlTypes["traceroute"] = &TracerouteCommandType{}
s.controlTypes["reload"] = &ReloadCommandType{}
}

return s
Expand Down
58 changes: 29 additions & 29 deletions pkg/controlsvc/mock_controlsvc/interfaces.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 45d7df5

Please sign in to comment.