Skip to content
This repository was archived by the owner on Mar 24, 2023. It is now read-only.

Commit b20557d

Browse files
authored
Merge pull request #894 from laverya/fix-test-data-races
fix several races in unit tests
2 parents 137d152 + 86358a2 commit b20557d

File tree

4 files changed

+42
-17
lines changed

4 files changed

+42
-17
lines changed

Makefile

+7
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,13 @@ lint: vet ineffassign .state/lint
250250

251251
test: lint .state/test
252252

253+
.state/race: $(SRC)
254+
go test --race ./pkg/...
255+
@mkdir -p .state
256+
@touch .state/race
257+
258+
race: lint .state/race
259+
253260
.state/coverage.out: $(SRC)
254261
@mkdir -p .state/
255262
#the reduced parallelism here is to avoid hitting the memory limits - we consistently did so with two threads on a 4gb instance

pkg/lifecycle/daemon/daemon_channel_test.go

+15-9
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ func TestDaemonChannel(t *testing.T) {
5757
}
5858
for _, test := range tests {
5959
t.Run(test.name, func(t *testing.T) {
60+
req := require.New(t)
61+
6062
v := viper.New()
6163

6264
port := rand.Intn(2000) + 33000
@@ -82,32 +84,36 @@ func TestDaemonChannel(t *testing.T) {
8284
}
8385

8486
daemonCtx, daemonCancelFunc := context.WithCancel(context.Background())
85-
defer daemonCancelFunc()
8687

8788
errChan := make(chan error)
8889
log.Log("starting daemon")
89-
go func() {
90+
go func(errCh chan error) {
9091
err := daemon.Serve(daemonCtx, test.release)
9192
log.Log("daemon.error", err)
92-
errChan <- err
93-
}()
93+
errCh <- err
94+
}(errChan)
9495

9596
// sigh. Give the server a second to start up
9697
time.Sleep(500 * time.Millisecond)
9798

9899
resp, err := http.Get(fmt.Sprintf("http://localhost:%d/api/v1/metadata", port))
99-
require.NoError(t, err)
100+
req.NoError(err)
100101

101102
body, err := ioutil.ReadAll(resp.Body)
102-
require.NoError(t, err)
103+
req.NoError(err)
103104
log.Log("received body", fmt.Sprintf("\"%s\"", body))
104105

106+
daemonCancelFunc()
107+
105108
unmarshalled := make(map[string]string)
106109
err = json.Unmarshal(body, &unmarshalled)
107-
require.NoError(t, err)
110+
req.NoError(err)
111+
112+
req.Equal(test.expectName, unmarshalled["name"])
113+
req.Equal(test.expectIcon, unmarshalled["icon"])
108114

109-
require.Equal(t, test.expectName, unmarshalled["name"])
110-
require.Equal(t, test.expectIcon, unmarshalled["icon"])
115+
daemonErr := <-errChan
116+
req.EqualError(daemonErr, "context canceled")
111117
})
112118
}
113119
}

pkg/lifecycle/daemon/routes_navcycle.go

+6
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"fmt"
66
"net/http"
7+
"sync"
78

89
"github.com/gin-gonic/gin"
910
"github.com/go-kit/kit/log"
@@ -54,6 +55,9 @@ type NavcycleRoutes struct {
5455

5556
// This isn't known at injection time, so we have to set in Register
5657
Release *api.Release
58+
59+
// Prevent data races when registering preexecute functions
60+
mut sync.Mutex
5761
}
5862

5963
// Register registers routes
@@ -95,6 +99,7 @@ func (d *NavcycleRoutes) Register(group *gin.RouterGroup, release *api.Release)
9599
type preExecuteFunc func(context.Context, api.Step) error
96100

97101
func (d *NavcycleRoutes) registerPreExecuteFuncs() {
102+
d.mut.Lock()
98103
preExecuteFuncMap := make(map[string]preExecuteFunc)
99104

100105
for _, step := range d.Release.Spec.Lifecycle.V1 {
@@ -104,6 +109,7 @@ func (d *NavcycleRoutes) registerPreExecuteFuncs() {
104109
}
105110

106111
d.PreExecuteFuncMap = preExecuteFuncMap
112+
d.mut.Unlock()
107113
}
108114

109115
func (d *NavcycleRoutes) shutdown(c *gin.Context) {

pkg/lifecycle/render/config/daemonresolver_test.go

+14-8
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@ import (
77

88
"github.com/mitchellh/cli"
99
"github.com/replicatedhq/libyaml"
10+
"github.com/spf13/afero"
11+
"github.com/spf13/viper"
12+
"github.com/stretchr/testify/require"
13+
1014
"github.com/replicatedhq/ship/pkg/api"
1115
"github.com/replicatedhq/ship/pkg/lifecycle/daemon"
1216
"github.com/replicatedhq/ship/pkg/lifecycle/kustomize"
1317
"github.com/replicatedhq/ship/pkg/testing/logger"
14-
"github.com/spf13/afero"
15-
"github.com/spf13/viper"
16-
"github.com/stretchr/testify/require"
1718
)
1819

1920
type daemonResolverTestCase struct {
@@ -147,19 +148,24 @@ func TestDaemonResolver(t *testing.T) {
147148
}
148149

149150
daemonCtx, daemonCancelFunc := context.WithCancel(context.Background())
150-
defer daemonCancelFunc()
151+
daemonCloseChan := make(chan struct{})
151152

152-
log.Log("starting daemon")
153-
go func() {
153+
require.NoError(t, log.Log("starting daemon"))
154+
go func(closeChan chan struct{}) {
154155
daemon.Serve(daemonCtx, test.release)
155-
}()
156+
closeChan <- struct{}{}
157+
}(daemonCloseChan)
156158

157159
resolver := &DaemonResolver{log, daemon}
158160

159161
resolveContext, cancel := context.WithTimeout(context.Background(), 1*time.Second)
160-
defer cancel()
161162
config, err := resolver.ResolveConfig(resolveContext, test.release, test.inputContext)
162163

164+
daemonCancelFunc()
165+
cancel()
166+
167+
<-daemonCloseChan
168+
163169
test.expect(t, config, err)
164170

165171
//req.NoError(err)

0 commit comments

Comments
 (0)