Skip to content

Commit

Permalink
Add tests for controlsvc control types
Browse files Browse the repository at this point in the history
  • Loading branch information
resoluteCoder committed Sep 28, 2023
1 parent 7aee413 commit 3ac33d3
Show file tree
Hide file tree
Showing 11 changed files with 694 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
207 changes: 207 additions & 0 deletions pkg/controlsvc/connect_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
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 {
if errorMessage != err.Error() {
t.Errorf("expected: %s , received: %s", errorMessage, err)
}
}

if !expectedError {
if 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{}
}{
{
name: "no connect target node",
expectedError: true,
errorMessage: "no connect target node",
input: map[string]interface{}{},
},
{
name: "connect target node must be string 1",
expectedError: true,
errorMessage: "connect target node must be string",
input: map[string]interface{}{
"node": 7,
},
},
{
name: "no connect target service",
expectedError: true,
errorMessage: "no connect target service",
input: map[string]interface{}{
"node": "node1",
},
},
{
name: "connect target service must be string 1",
expectedError: true,
errorMessage: "connect target service must be string",
input: map[string]interface{}{
"node": "node2",
"service": 7,
},
},
{
name: "connect tls name must be string",
expectedError: true,
errorMessage: "connect tls name must be string",
input: map[string]interface{}{
"node": "node3",
"service": "service1",
"tls": 7,
},
},
{
name: "pass with empty tls config",
expectedError: false,
errorMessage: "connect target service must be string",
input: map[string]interface{}{
"node": "node4",
"service": "service2",
},
},
{
name: "pass with all targets and tls config",
expectedError: false,
errorMessage: "",
input: map[string]interface{}{
"node": "node5",
"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
Loading

0 comments on commit 3ac33d3

Please sign in to comment.