Skip to content

Commit

Permalink
feat(security): Add more tests to increase coverage
Browse files Browse the repository at this point in the history
Added some more missing testable tests to increase the test coverage.

Signed-off-by: Jim Wang <[email protected]>
  • Loading branch information
jim-wang-intel committed Jan 20, 2021
1 parent ca01f42 commit bd0b3a8
Show file tree
Hide file tree
Showing 14 changed files with 545 additions and 13 deletions.
2 changes: 1 addition & 1 deletion internal/security/bootstrapper/command/gate/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func NewCommand(
return nil, fmt.Errorf("Unable to parse command: %s: %w", strings.Join(args, " "), err)
}

return &cmd, err
return &cmd, nil
}

// Execute implements Command and runs this command
Expand Down
160 changes: 160 additions & 0 deletions internal/security/bootstrapper/command/gate/command_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
/*******************************************************************************
* Copyright 2021 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*
*******************************************************************************/

package gate

import (
"context"
"sync"
"testing"
"time"

"github.com/edgexfoundry/edgex-go/internal/security/bootstrapper/config"
"github.com/edgexfoundry/edgex-go/internal/security/bootstrapper/interfaces"
"github.com/edgexfoundry/edgex-go/internal/security/bootstrapper/tcp"

"github.com/stretchr/testify/require"

"github.com/edgexfoundry/go-mod-core-contracts/clients/logger"
)

func TestNewCommand(t *testing.T) {
// Arrange
ctx := context.Background()
wg := &sync.WaitGroup{}
lc := logger.MockLogger{}
config := &config.ConfigurationStruct{}

tests := []struct {
name string
cmdArgs []string
expectedErr bool
}{
{"Good: gate cmd empty option", []string{}, false},
{"Bad: gate invalid option", []string{"--invalid=xxx"}, true},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
command, err := NewCommand(ctx, wg, lc, config, tt.cmdArgs)
if tt.expectedErr {
require.Error(t, err)
} else {
require.NoError(t, err)
require.NotNil(t, command)
}
})
}
}

type testConfig struct {
testHost string
bootstrapperStartPort int
consulReadyPort int
redisReadyPort int
postgresReadyPort int
readyToRunPort int
}

func TestExecuteWithAllDependentsRun(t *testing.T) {
// Arrange
lc := logger.MockLogger{}
testHost := "localhost"
testConfig := &testConfig{
testHost: "localhost",
bootstrapperStartPort: 28001,
consulReadyPort: 28002,
redisReadyPort: 28003,
postgresReadyPort: 28004,
readyToRunPort: 28009,
}
config := setupMockServiceConfigs(testConfig)

type executeReturn struct {
code int
err error
}

ctx, cancelFunc := context.WithTimeout(context.Background(), 5*time.Second)
wg := &sync.WaitGroup{}
gate, err := NewCommand(ctx, wg, lc, config, []string{})
defer func() {
cancelFunc()
wg.Wait()
}()
require.NoError(t, err)
require.NotNil(t, gate)
require.Equal(t, "gate", gate.GetCommandName())
execRet := make(chan executeReturn, 1)
// in a separate go-routine since the listenTcp is a blocking call
go func() {
statusCode, err := gate.Execute()
execRet <- executeReturn{code: statusCode, err: err}
}()

tcpSrvErr := make(chan error)
// start up all other dependent mock services:
go func() {
tcpSrvErr <- tcp.NewTcpServer().StartListener(testConfig.consulReadyPort,
lc, testHost)
}()
go func() {
tcpSrvErr <- tcp.NewTcpServer().StartListener(testConfig.postgresReadyPort,
lc, testHost)
}()
go func() {
tcpSrvErr <- tcp.NewTcpServer().StartListener(testConfig.redisReadyPort,
lc, testHost)
}()

select {
case ret := <-execRet:
require.NoError(t, ret.err)
require.Equal(t, interfaces.StatusCodeExitNormal, ret.code)
case err := <-tcpSrvErr:
require.NoError(t, err)
case <-time.After(5 * time.Second):
require.Fail(t, "security bootstrapper gate never returned")
}
}

func setupMockServiceConfigs(testConf *testConfig) *config.ConfigurationStruct {
conf := &config.ConfigurationStruct{}
conf.StageGate = config.StageGateInfo{
BootStrapper: config.BootStrapperInfo{
Host: testConf.testHost,
StartPort: testConf.bootstrapperStartPort,
},
Consul: config.ConsulInfo{
Host: testConf.testHost,
Port: 12001,
ReadyPort: testConf.consulReadyPort,
},
Redis: config.RedisInfo{
Host: testConf.testHost,
Port: 12002,
ReadyPort: testConf.redisReadyPort,
},
PG: config.PostgresInfo{
Host: testConf.testHost,
Port: 12003,
ReadyPort: testConf.postgresReadyPort,
},
Ready: config.ReadyInfo{
ToRunPort: testConf.readyToRunPort,
},
}
return conf
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ func NewCommand(
return nil, fmt.Errorf("Unable to parse command: %s: %w", strings.Join(args, " "), err)
}

return &cmd, err
return &cmd, nil
}

// Execute implements Command and runs this command
Expand Down
75 changes: 75 additions & 0 deletions internal/security/bootstrapper/command/genpassword/command_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*******************************************************************************
* Copyright 2021 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*
*******************************************************************************/

package genpassword

import (
"context"
"sync"
"testing"

"github.com/edgexfoundry/edgex-go/internal/security/bootstrapper/config"
"github.com/edgexfoundry/edgex-go/internal/security/bootstrapper/interfaces"

"github.com/stretchr/testify/require"

"github.com/edgexfoundry/go-mod-core-contracts/clients/logger"
)

func TestNewCommand(t *testing.T) {
// Arrange
ctx := context.Background()
wg := &sync.WaitGroup{}
lc := logger.MockLogger{}
config := &config.ConfigurationStruct{}

tests := []struct {
name string
cmdArgs []string
expectedErr bool
}{
{"Good: genPasswd cmd empty option", []string{}, false},
{"Bad: genPasswd invalid option", []string{"--invalid=xxx"}, true},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
command, err := NewCommand(ctx, wg, lc, config, tt.cmdArgs)
if tt.expectedErr {
require.Error(t, err)
} else {
require.NoError(t, err)
require.NotNil(t, command)
}
})
}
}

func TestExecute(t *testing.T) {
// Arrange
ctx := context.Background()
wg := &sync.WaitGroup{}
lc := logger.MockLogger{}
config := &config.ConfigurationStruct{}

genPwd, err := NewCommand(ctx, wg, lc, config, []string{})
require.NoError(t, err)
require.NotNil(t, genPwd)
require.Equal(t, "genPassword", genPwd.GetCommandName())

statusCode, err := genPwd.Execute()
require.NoError(t, err)
require.Equal(t, interfaces.StatusCodeExitNormal, statusCode)
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func NewCommand(
return nil, fmt.Errorf("%s %s: argument --url is required", os.Args[0], CommandName)
}

return &cmd, err
return &cmd, nil
}

// GetCommandName returns the name of this command
Expand Down
101 changes: 101 additions & 0 deletions internal/security/bootstrapper/command/gethttpstatus/command_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*******************************************************************************
* Copyright 2021 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*
*******************************************************************************/

package gethttpstatus

import (
"context"
"net/http"
"net/http/httptest"
"sync"
"testing"

"github.com/edgexfoundry/edgex-go/internal/security/bootstrapper/config"
"github.com/edgexfoundry/edgex-go/internal/security/bootstrapper/interfaces"

"github.com/stretchr/testify/require"

"github.com/edgexfoundry/go-mod-core-contracts/clients/logger"
)

func TestNewCommand(t *testing.T) {
// Arrange
ctx := context.Background()
wg := &sync.WaitGroup{}
lc := logger.MockLogger{}
config := &config.ConfigurationStruct{}

tests := []struct {
name string
cmdArgs []string
expectedErr bool
}{
{"Good: getHttpStatus required --url option", []string{"--url=http://localhost:32323"}, false},
{"Bad: getHttpStatus invalid option", []string{"--invalid=http://localhost:123"}, true},
{"Bad: getHttpStatus empty option", []string{""}, true},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
command, err := NewCommand(ctx, wg, lc, config, tt.cmdArgs)
if tt.expectedErr {
require.Error(t, err)
} else {
require.NoError(t, err)
require.NotNil(t, command)
}
})
}
}

func TestExecute(t *testing.T) {
// Arrange
ctx := context.Background()
wg := &sync.WaitGroup{}
lc := logger.MockLogger{}
config := &config.ConfigurationStruct{}

testSrv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}))
defer testSrv.Close()

tests := []struct {
name string
cmdArgs []string
expectedErr bool
}{
{"Good: getHttpStatus with existing server", []string{"--url=" + testSrv.URL}, false},
{"Bad: getHttpStatus with non-existing server", []string{"--url=http://non-existing:1111"}, true},
{"Bad: getHttpStatus with malformed URL", []string{"--url=_http!@xxxxxx:1111"}, true},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
getHttpStatus, err := NewCommand(ctx, wg, lc, config, tt.cmdArgs)
require.NoError(t, err)
require.NotNil(t, getHttpStatus)
require.Equal(t, "getHttpStatus", getHttpStatus.GetCommandName())

statusCode, err := getHttpStatus.Execute()

if tt.expectedErr {
require.Error(t, err)
require.Equal(t, interfaces.StatusCodeExitWithError, statusCode)
} else {
require.NoError(t, err)
require.Equal(t, interfaces.StatusCodeExitNormal, statusCode)
}
})
}
}
2 changes: 1 addition & 1 deletion internal/security/bootstrapper/command/listen/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func NewCommand(
return nil, fmt.Errorf("%s %s: argument --port is required", os.Args[0], CommandName)
}

return &cmd, err
return &cmd, nil
}

// Execute implements Command and runs this command
Expand Down
Loading

0 comments on commit bd0b3a8

Please sign in to comment.