Skip to content

Commit d95e706

Browse files
committed
pkg/services/servicetest: add RunCfg for customized Run configurations
1 parent 00dd182 commit d95e706

File tree

1 file changed

+77
-16
lines changed
  • pkg/services/servicetest

1 file changed

+77
-16
lines changed

pkg/services/servicetest/run.go

Lines changed: 77 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,7 @@ type TestingT interface {
2727
// Run fails tb if the service fails to start or close.
2828
func Run[R Runnable](tb TestingT, r R) R {
2929
tb.Helper()
30-
require.NoError(tb, r.Start(tests.Context(tb)), "service failed to start: %T", r)
31-
tb.Cleanup(func() {
32-
tb.Helper()
33-
assert.NoError(tb, r.Close(), "error closing service: %T", r)
34-
})
30+
RunCfg{}.run(tb, r)
3531
return r
3632
}
3733

@@ -40,7 +36,79 @@ func Run[R Runnable](tb TestingT, r R) R {
4036
// - if ever ready, then health will be checked at least once, before closing
4137
func RunHealthy[S services.Service](tb TestingT, s S) S {
4238
tb.Helper()
43-
Run(tb, s)
39+
RunCfg{Healthy: true}.Run(tb, s)
40+
return s
41+
}
42+
43+
// RunCfg specifies a test configuration for running a service.
44+
// By default, health checks are not enforced, but Start/Close timeout are.
45+
type RunCfg struct {
46+
// Healthy includes extra checks for whether the service is never ready, or is ever unhealthy (based on periodic checks).
47+
// - after starting, readiness will always be checked at least once, before closing
48+
// - if ever ready, then health will be checked at least once, before closing
49+
Healthy bool
50+
// WaitForReady blocks returning until after Ready() returns nil, after calling Start().
51+
WaitForReady bool
52+
// StartTimeout sets a limit for Start which results in an error if exceeded.
53+
StartTimeout time.Duration
54+
// StartTimeout sets a limit for Close which results in an error if exceeded.
55+
CloseTimeout time.Duration
56+
}
57+
58+
func (cfg RunCfg) Run(tb TestingT, s services.Service) {
59+
tb.Helper()
60+
61+
cfg.run(tb, s)
62+
63+
if cfg.WaitForReady {
64+
ctx := tests.Context(tb)
65+
cfg.waitForReady(tb, s, ctx.Done())
66+
}
67+
68+
if cfg.Healthy {
69+
cfg.healthCheck(tb, s)
70+
}
71+
}
72+
73+
func (cfg RunCfg) run(tb TestingT, s Runnable) {
74+
tb.Helper()
75+
//TODO remove....set from built-ins? or disallow unbounded, so exceptions must be explicit?
76+
if cfg.StartTimeout == 0 {
77+
cfg.StartTimeout = time.Second
78+
}
79+
if cfg.CloseTimeout == 0 {
80+
cfg.CloseTimeout = time.Second
81+
}
82+
83+
start := time.Now()
84+
require.NoError(tb, s.Start(tests.Context(tb)), "service failed to start: %T", s)
85+
if elapsed := time.Since(start); cfg.StartTimeout > 0 && elapsed > cfg.StartTimeout {
86+
tb.Errorf("slow service start: %T.Start() took %s", s, elapsed)
87+
}
88+
89+
tb.Cleanup(func() {
90+
tb.Helper()
91+
start := time.Now()
92+
assert.NoError(tb, s.Close(), "error closing service: %T", s)
93+
if elapsed := time.Since(start); cfg.CloseTimeout > 0 && elapsed > cfg.CloseTimeout {
94+
tb.Errorf("slow service close: %T.Close() took %s", s, elapsed)
95+
}
96+
})
97+
}
98+
99+
func (cfg RunCfg) waitForReady(tb TestingT, s services.Service, done <-chan struct{}) {
100+
for err := s.Ready(); err != nil; err = s.Ready() {
101+
select {
102+
case <-done:
103+
assert.NoError(tb, err, "service never ready")
104+
return
105+
case <-time.After(time.Second):
106+
}
107+
}
108+
}
109+
110+
func (cfg RunCfg) healthCheck(tb TestingT, s services.Service) {
111+
tb.Helper()
44112

45113
done := make(chan struct{})
46114
tb.Cleanup(func() {
@@ -57,15 +125,9 @@ func RunHealthy[S services.Service](tb TestingT, s S) S {
57125
}
58126
return
59127
}
60-
for s.Ready() != nil {
61-
select {
62-
case <-done:
63-
if assert.NoError(tb, s.Ready(), "service never ready") {
64-
assert.NoError(tb, hp(), "service unhealthy")
65-
}
66-
return
67-
case <-time.After(time.Second):
68-
}
128+
if !cfg.WaitForReady {
129+
cfg.waitForReady(tb, s, done)
130+
assert.NoError(tb, hp(), "service unhealthy")
69131
}
70132
for {
71133
select {
@@ -77,5 +139,4 @@ func RunHealthy[S services.Service](tb TestingT, s S) S {
77139
}
78140
}
79141
}()
80-
return s
81142
}

0 commit comments

Comments
 (0)