Skip to content

Commit 5efe6d8

Browse files
committed
Add basic unit test for StepRunner
Signed-off-by: Ilya <[email protected]>
1 parent 7922406 commit 5efe6d8

File tree

3 files changed

+170
-48
lines changed

3 files changed

+170
-48
lines changed

pkg/runner/base_test_suite_test.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package runner
2+
3+
import (
4+
"encoding/json"
5+
6+
"github.com/benbjohnson/clock"
7+
"github.com/linuxboot/contest/pkg/event/testevent"
8+
"github.com/linuxboot/contest/pkg/pluginregistry"
9+
"github.com/linuxboot/contest/pkg/target"
10+
"github.com/linuxboot/contest/pkg/test"
11+
"github.com/linuxboot/contest/pkg/xcontext"
12+
"github.com/linuxboot/contest/plugins/targetlocker/inmemory"
13+
"github.com/stretchr/testify/require"
14+
"github.com/stretchr/testify/suite"
15+
)
16+
17+
type BaseTestSuite struct {
18+
suite.Suite
19+
20+
pluginRegistry *pluginregistry.PluginRegistry
21+
internalStorage *MemoryStorageEngine
22+
}
23+
24+
func (s *BaseTestSuite) SetupTest() {
25+
storageEngine, err := NewMemoryStorageEngine()
26+
require.NoError(s.T(), err)
27+
s.internalStorage = storageEngine
28+
29+
target.SetLocker(inmemory.New(clock.New()))
30+
31+
s.pluginRegistry = pluginregistry.NewPluginRegistry(xcontext.Background())
32+
}
33+
34+
func (s *BaseTestSuite) TearDownTest() {
35+
target.SetLocker(nil)
36+
}
37+
38+
func (s *BaseTestSuite) RegisterStateFullStep(
39+
runFunction func(
40+
ctx xcontext.Context, ch test.TestStepChannels, params test.TestStepParameters,
41+
ev testevent.Emitter, resumeState json.RawMessage) (json.RawMessage, error),
42+
validateFunction func(ctx xcontext.Context, params test.TestStepParameters) error) error {
43+
44+
return s.pluginRegistry.RegisterTestStep(stateFullStepName, func() test.TestStep {
45+
return &stateFullStep{
46+
runFunction: runFunction,
47+
validateFunction: validateFunction,
48+
}
49+
}, nil)
50+
}
51+
52+
func (s *BaseTestSuite) NewStep(label, name string, params test.TestStepParameters) test.TestStepBundle {
53+
td := test.TestStepDescriptor{
54+
Name: name,
55+
Label: label,
56+
Parameters: params,
57+
}
58+
sb, err := s.pluginRegistry.NewTestStepBundle(ctx, td)
59+
require.NoError(s.T(), err)
60+
return *sb
61+
}

pkg/runner/job_runner_test.go

Lines changed: 9 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,10 @@ import (
1717
"github.com/linuxboot/contest/pkg/event"
1818
"github.com/linuxboot/contest/pkg/event/testevent"
1919
"github.com/linuxboot/contest/pkg/job"
20-
"github.com/linuxboot/contest/pkg/pluginregistry"
2120
"github.com/linuxboot/contest/pkg/storage"
2221
"github.com/linuxboot/contest/pkg/target"
2322
"github.com/linuxboot/contest/pkg/test"
2423
"github.com/linuxboot/contest/pkg/xcontext"
25-
"github.com/linuxboot/contest/plugins/targetlocker/inmemory"
2624
"github.com/linuxboot/contest/plugins/targetmanagers/targetlist"
2725
"github.com/linuxboot/contest/plugins/teststeps"
2826
"github.com/linuxboot/contest/plugins/teststeps/echo"
@@ -84,24 +82,16 @@ func (r *collectingReporter) FinalReport(ctx xcontext.Context, parameters interf
8482
}
8583

8684
type JobRunnerSuite struct {
87-
suite.Suite
88-
89-
pluginRegistry *pluginregistry.PluginRegistry
90-
internalStorage *MemoryStorageEngine
85+
BaseTestSuite
9186
}
9287

9388
func TestTestStepSuite(t *testing.T) {
9489
suite.Run(t, &JobRunnerSuite{})
9590
}
9691

9792
func (s *JobRunnerSuite) SetupTest() {
98-
storageEngine, err := NewMemoryStorageEngine()
99-
require.NoError(s.T(), err)
100-
s.internalStorage = storageEngine
93+
s.BaseTestSuite.SetupTest()
10194

102-
target.SetLocker(inmemory.New(clock.New()))
103-
104-
s.pluginRegistry = pluginregistry.NewPluginRegistry(xcontext.Background())
10595
for _, e := range []struct {
10696
name string
10797
factory test.TestStepFactory
@@ -113,40 +103,11 @@ func (s *JobRunnerSuite) SetupTest() {
113103
}
114104
}
115105

116-
func (s *JobRunnerSuite) TearDownTest() {
117-
target.SetLocker(nil)
118-
}
119-
120-
func (s *JobRunnerSuite) registerStateFullStep(
121-
runFunction func(
122-
ctx xcontext.Context, ch test.TestStepChannels, params test.TestStepParameters,
123-
ev testevent.Emitter, resumeState json.RawMessage) (json.RawMessage, error),
124-
validateFunction func(ctx xcontext.Context, params test.TestStepParameters) error) error {
125-
126-
return s.pluginRegistry.RegisterTestStep(stateFullStepName, func() test.TestStep {
127-
return &stateFullStep{
128-
runFunction: runFunction,
129-
validateFunction: validateFunction,
130-
}
131-
}, nil)
132-
}
133-
134-
func (s *JobRunnerSuite) newStep(label, name string, params test.TestStepParameters) test.TestStepBundle {
135-
td := test.TestStepDescriptor{
136-
Name: name,
137-
Label: label,
138-
Parameters: params,
139-
}
140-
sb, err := s.pluginRegistry.NewTestStepBundle(ctx, td)
141-
require.NoError(s.T(), err)
142-
return *sb
143-
}
144-
145106
func (s *JobRunnerSuite) TestSimpleJobStartFinish() {
146107
var mu sync.Mutex
147108
var resultTargets []*target.Target
148109

149-
require.NoError(s.T(), s.registerStateFullStep(
110+
require.NoError(s.T(), s.RegisterStateFullStep(
150111
func(ctx xcontext.Context, ch test.TestStepChannels, params test.TestStepParameters, ev testevent.Emitter, resumeState json.RawMessage) (json.RawMessage, error) {
151112
return teststeps.ForEachTarget(stateFullStepName, ctx, ch, func(ctx xcontext.Context, target *target.Target) error {
152113
assert.NotNil(s.T(), target)
@@ -180,7 +141,7 @@ func (s *JobRunnerSuite) TestSimpleJobStartFinish() {
180141
TargetManager: targetlist.New(),
181142
},
182143
TestStepsBundles: []test.TestStepBundle{
183-
s.newStep("test_step_label", stateFullStepName, nil),
144+
s.NewStep("test_step_label", stateFullStepName, nil),
184145
},
185146
},
186147
},
@@ -209,7 +170,7 @@ func (s *JobRunnerSuite) TestJobWithTestRetry() {
209170
var resultTargets []*target.Target
210171
var callsCount int
211172

212-
require.NoError(s.T(), s.registerStateFullStep(
173+
require.NoError(s.T(), s.RegisterStateFullStep(
213174
func(ctx xcontext.Context, ch test.TestStepChannels, params test.TestStepParameters, ev testevent.Emitter, resumeState json.RawMessage) (json.RawMessage, error) {
214175
return teststeps.ForEachTarget(stateFullStepName, ctx, ch, func(ctx xcontext.Context, target *target.Target) error {
215176
assert.NotNil(s.T(), target)
@@ -259,11 +220,11 @@ func (s *JobRunnerSuite) TestJobWithTestRetry() {
259220
TargetManager: targetlist.New(),
260221
},
261222
TestStepsBundles: []test.TestStepBundle{
262-
s.newStep("echo1_step_label", echo.Name, map[string][]test.Param{
223+
s.NewStep("echo1_step_label", echo.Name, map[string][]test.Param{
263224
"text": {*test.NewParam("hello")},
264225
}),
265-
s.newStep("test_step_label", stateFullStepName, nil),
266-
s.newStep("echo2_step_label", echo.Name, map[string][]test.Param{
226+
s.NewStep("test_step_label", stateFullStepName, nil),
227+
s.NewStep("echo2_step_label", echo.Name, map[string][]test.Param{
267228
"text": {*test.NewParam("world")},
268229
}),
269230
},
@@ -342,7 +303,7 @@ func (s *JobRunnerSuite) TestResumeStateBadJobId() {
342303
TargetManager: targetlist.New(),
343304
},
344305
TestStepsBundles: []test.TestStepBundle{
345-
s.newStep("echo1_step_label", echo.Name, map[string][]test.Param{
306+
s.NewStep("echo1_step_label", echo.Name, map[string][]test.Param{
346307
"text": {*test.NewParam("hello")},
347308
}),
348309
},

pkg/runner/step_runner_test.go

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package runner
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"sync"
7+
"testing"
8+
9+
"github.com/linuxboot/contest/pkg/event/testevent"
10+
"github.com/linuxboot/contest/pkg/target"
11+
"github.com/linuxboot/contest/pkg/test"
12+
"github.com/linuxboot/contest/pkg/xcontext"
13+
"github.com/linuxboot/contest/plugins/teststeps"
14+
"github.com/stretchr/testify/require"
15+
"github.com/stretchr/testify/suite"
16+
)
17+
18+
func TestStepRunnerSuite(t *testing.T) {
19+
suite.Run(t, new(StepRunnerSuite))
20+
}
21+
22+
type StepRunnerSuite struct {
23+
BaseTestSuite
24+
}
25+
26+
func (s *StepRunnerSuite) TestRunningStep() {
27+
targetsReaction := map[string]error{
28+
"TSucc": nil,
29+
"TFail": fmt.Errorf("oops"),
30+
}
31+
32+
var mu sync.Mutex
33+
var obtainedTargets []target.Target
34+
var obtainedResumeState json.RawMessage
35+
36+
err := s.RegisterStateFullStep(
37+
func(ctx xcontext.Context, ch test.TestStepChannels, params test.TestStepParameters, ev testevent.Emitter, resumeState json.RawMessage) (json.RawMessage, error) {
38+
obtainedResumeState = resumeState
39+
_, err := teststeps.ForEachTarget(stateFullStepName, ctx, ch, func(ctx xcontext.Context, target *target.Target) error {
40+
require.NotNil(s.T(), target)
41+
42+
mu.Lock()
43+
defer mu.Unlock()
44+
obtainedTargets = append(obtainedTargets, *target)
45+
return targetsReaction[target.ID]
46+
})
47+
if err != nil {
48+
return nil, err
49+
}
50+
return json.RawMessage("{\"output\": true}"), nil
51+
},
52+
nil,
53+
)
54+
require.NoError(s.T(), err)
55+
56+
stepRunner := NewStepRunner()
57+
require.NotNil(s.T(), stepRunner)
58+
59+
emitterFactory := NewTestStepEventsEmitterFactory(s.internalStorage.StorageEngineVault, 1, 1, testName, 0)
60+
emitter := emitterFactory.New("test_step_label")
61+
62+
inputResumeState := json.RawMessage("{\"some_input\": 42}")
63+
resultChan, err := stepRunner.Run(ctx, s.NewStep("test_step_label", stateFullStepName, nil), emitter, inputResumeState)
64+
require.NoError(s.T(), err)
65+
require.NotNil(s.T(), resultChan)
66+
67+
require.NoError(s.T(), stepRunner.AddTarget(ctx, tgt("TSucc")))
68+
ev, ok := <-resultChan
69+
require.True(s.T(), ok)
70+
require.Equal(s.T(), tgt("TSucc"), ev.Target)
71+
require.NoError(s.T(), ev.Err)
72+
73+
require.NoError(s.T(), stepRunner.AddTarget(ctx, tgt("TFail")))
74+
ev, ok = <-resultChan
75+
require.True(s.T(), ok)
76+
require.Equal(s.T(), tgt("TFail"), ev.Target)
77+
require.Error(s.T(), ev.Err)
78+
79+
stepRunner.Stop()
80+
81+
ev, ok = <-resultChan
82+
require.True(s.T(), ok)
83+
require.Nil(s.T(), ev.Target)
84+
require.NoError(s.T(), ev.Err)
85+
86+
ev, ok = <-resultChan
87+
require.False(s.T(), ok)
88+
89+
closedCtx, cancel := xcontext.WithCancel(ctx)
90+
cancel()
91+
92+
// if step runner has results, it should return them even if input context is closed
93+
res, err := stepRunner.WaitResults(closedCtx)
94+
require.NoError(s.T(), err)
95+
96+
require.Equal(s.T(), json.RawMessage("{\"output\": true}"), res.ResumeState)
97+
require.NoError(s.T(), res.Err)
98+
99+
require.Equal(s.T(), inputResumeState, obtainedResumeState)
100+
}

0 commit comments

Comments
 (0)