• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

rom8726 / chaoskit / 19556545691

21 Nov 2025 01:10AM UTC coverage: 44.471% (+0.01%) from 44.461%
19556545691

push

github

rom8726
testing package's Run function fix.

0 of 42 new or added lines in 1 file covered. (0.0%)

2 existing lines in 1 file now uncovered.

2051 of 4612 relevant lines covered (44.47%)

733.43 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/testing/testing.go
1
package testing
2

3
import (
4
        "context"
5
        "fmt"
6

7
        "github.com/rom8726/chaoskit"
8
)
9

10
// TestingT is an interface that matches testing.T and similar types
11
type TestingT interface {
12
        Errorf(format string, args ...interface{})
13
        FailNow()
14
        Helper()
15
}
16

17
// ChaosTestOption configures chaos testing
18
type ChaosTestOption func(*chaosTestConfig)
19

20
type chaosTestConfig struct {
21
        repeat         int
22
        failurePolicy  chaoskit.FailurePolicy
23
        executorOpts   []chaoskit.ExecutorOption
24
        skipReport     bool
25
        reportToStderr bool
26
        thresholds     *chaoskit.SuccessThresholds
27
        skipVerdict    bool
28
}
29

30
// WithRepeat sets the number of times to repeat the test scenario
31
func WithRepeat(n int) ChaosTestOption {
×
32
        return func(c *chaosTestConfig) {
×
33
                c.repeat = n
×
34
        }
×
35
}
36

37
// WithFailurePolicy sets how to handle failures (FailFast or ContinueOnFailure)
38
func WithFailurePolicy(policy chaoskit.FailurePolicy) ChaosTestOption {
×
39
        return func(c *chaosTestConfig) {
×
40
                c.failurePolicy = policy
×
41
        }
×
42
}
43

44
// WithExecutorOptions passes options to the underlying executor
45
func WithExecutorOptions(opts ...chaoskit.ExecutorOption) ChaosTestOption {
×
46
        return func(c *chaosTestConfig) {
×
47
                c.executorOpts = append(c.executorOpts, opts...)
×
48
        }
×
49
}
50

51
// WithoutReport skips printing the report after execution
52
func WithoutReport() ChaosTestOption {
×
53
        return func(c *chaosTestConfig) {
×
54
                c.skipReport = true
×
55
        }
×
56
}
57

58
// WithReportToStderr prints the report to stderr instead of stdout
59
func WithReportToStderr() ChaosTestOption {
×
60
        return func(c *chaosTestConfig) {
×
61
                c.reportToStderr = true
×
62
        }
×
63
}
64

65
// WithThresholds sets custom success thresholds for verdict calculation
66
func WithThresholds(thresholds *chaoskit.SuccessThresholds) ChaosTestOption {
×
67
        return func(c *chaosTestConfig) {
×
68
                c.thresholds = thresholds
×
69
        }
×
70
}
71

72
// WithDefaultThresholds uses default success thresholds (95% success rate)
73
func WithDefaultThresholds() ChaosTestOption {
×
74
        return func(c *chaosTestConfig) {
×
75
                c.thresholds = chaoskit.DefaultThresholds()
×
76
        }
×
77
}
78

79
// WithStrictThresholds uses strict success thresholds (100% success rate)
80
func WithStrictThresholds() ChaosTestOption {
×
81
        return func(c *chaosTestConfig) {
×
82
                c.thresholds = chaoskit.StrictThresholds()
×
83
        }
×
84
}
85

86
// WithRelaxedThresholds uses relaxed success thresholds (80% success rate)
87
func WithRelaxedThresholds() ChaosTestOption {
×
88
        return func(c *chaosTestConfig) {
×
89
                c.thresholds = chaoskit.RelaxedThresholds()
×
90
        }
×
91
}
92

93
// WithoutVerdict skips verdict calculation (only basic report)
94
func WithoutVerdict() ChaosTestOption {
×
95
        return func(c *chaosTestConfig) {
×
96
                c.skipVerdict = true
×
97
        }
×
98
}
99

100
// RunChaos creates a chaos test function that uses the full ChaosKit framework.
101
// It creates a scenario using ScenarioBuilder, runs it with an Executor, and validates results.
102
//
103
// The builderFn receives a pre-initialized ScenarioBuilder with the target already set.
104
// You should add steps, injectors, and validators to the builder.
105
//
106
// Usage:
107
//
108
//        func TestWithChaos(t *testing.T) {
109
//            target := &MyTarget{}
110
//
111
//            chaoskit.RunChaos(t, "name", target, func(s *chaoskit.ScenarioBuilder) *chaoskit.ScenarioBuilder {
112
//                return s.
113
//                    Step("step1", func(ctx context.Context, target chaoskit.Target) error {
114
//                        // Your test logic
115
//                        return DoSomething()
116
//                    }).
117
//                    Inject("delay", injectors.RandomDelay(10*time.Millisecond, 50*time.Millisecond)).
118
//                    Assert("goroutines", validators.GoroutineLimit(100))
119
//            },
120
//                WithRepeat(10),
121
//                WithDefaultThresholds(), // Enables verdict with 95% success rate
122
//            )
123
//        }
124
func RunChaos(
125
        t TestingT,
126
        name string,
127
        target chaoskit.Target,
128
        builderFn func(*chaoskit.ScenarioBuilder) *chaoskit.ScenarioBuilder,
129
        opts ...ChaosTestOption,
NEW
130
) {
×
NEW
131
        t.Helper()
×
NEW
132

×
NEW
133
        // Apply options
×
NEW
134
        config := &chaosTestConfig{
×
NEW
135
                repeat:        1,
×
NEW
136
                failurePolicy: chaoskit.FailFast,
×
NEW
137
                thresholds:    chaoskit.DefaultThresholds(), // Use default thresholds
×
NEW
138
        }
×
NEW
139
        for _, opt := range opts {
×
NEW
140
                opt(config)
×
NEW
141
        }
×
142

143
        // Create scenario builder
NEW
144
        builder := chaoskit.NewScenario(name).WithTarget(target)
×
145

×
NEW
146
        // Let user configure the scenario
×
NEW
147
        builder = builderFn(builder)
×
148

×
NEW
149
        // Set repeat count
×
NEW
150
        builder = builder.Repeat(config.repeat)
×
151

×
NEW
152
        // Build scenario
×
NEW
153
        scenario := builder.Build()
×
154

×
NEW
155
        // Create executor with options
×
NEW
156
        executorOpts := append(
×
NEW
157
                []chaoskit.ExecutorOption{chaoskit.WithFailurePolicy(config.failurePolicy)},
×
NEW
158
                config.executorOpts...,
×
NEW
159
        )
×
NEW
160
        executor := chaoskit.NewExecutor(executorOpts...)
×
161

×
NEW
162
        // Run scenario
×
NEW
163
        ctx := context.Background()
×
NEW
164
        if err := executor.Run(ctx, scenario); err != nil {
×
NEW
165
                t.Errorf("chaos test execution failed: %v", err)
×
166

×
NEW
167
                // Print report on failure
×
NEW
168
                if !config.skipReport {
×
NEW
169
                        printReport(t, executor, config)
×
UNCOV
170
                }
×
171

NEW
172
                t.FailNow()
×
NEW
173
                return
×
174
        }
175

176
        // Calculate verdict and print report
NEW
177
        if !config.skipReport || !config.skipVerdict {
×
NEW
178
                verdict := evaluateVerdict(t, executor, config)
×
179

×
NEW
180
                // Fail test if verdict is FAIL
×
NEW
181
                if verdict == chaoskit.VerdictFail {
×
NEW
182
                        t.Errorf("chaos test verdict: FAIL")
×
NEW
183
                        t.FailNow()
×
UNCOV
184
                }
×
185
        }
186
}
187

188
// printReport prints the test report
189
func printReport(t TestingT, executor *chaoskit.Executor, config *chaosTestConfig) {
×
190
        if config.skipVerdict {
×
191
                // Print simple report
×
192
                report := executor.Reporter().GenerateReport()
×
193
                if logger, ok := t.(interface{ Logf(string, ...interface{}) }); ok {
×
194
                        logger.Logf("\n%s", report)
×
195
                }
×
196
        } else {
×
197
                // Print detailed report with verdict
×
198
                report, err := executor.Reporter().GetVerdict(config.thresholds)
×
199
                if err != nil {
×
200
                        if logger, ok := t.(interface{ Logf(string, ...interface{}) }); ok {
×
201
                                logger.Logf("\nFailed to generate verdict: %v", err)
×
202
                                logger.Logf("\n%s", executor.Reporter().GenerateReport())
×
203
                        }
×
204
                        return
×
205
                }
206

207
                textReport := executor.Reporter().GenerateTextReport(report)
×
208
                if logger, ok := t.(interface{ Logf(string, ...interface{}) }); ok {
×
209
                        logger.Logf("\n%s", textReport)
×
210
                }
×
211
        }
212
}
213

214
// evaluateVerdict evaluates the verdict and returns it
215
func evaluateVerdict(t TestingT, executor *chaoskit.Executor, config *chaosTestConfig) chaoskit.Verdict {
×
216
        if config.skipVerdict {
×
217
                return chaoskit.VerdictPass
×
218
        }
×
219

220
        // Get verdict
221
        report, err := executor.Reporter().GetVerdict(config.thresholds)
×
222
        if err != nil {
×
223
                t.Errorf("failed to generate verdict: %v", err)
×
224
                return chaoskit.VerdictFail
×
225
        }
×
226

227
        // Print report
228
        if !config.skipReport {
×
229
                textReport := executor.Reporter().GenerateTextReport(report)
×
230
                if logger, ok := t.(interface{ Logf(string, ...interface{}) }); ok {
×
231
                        logger.Logf("\n%s", textReport)
×
232
                }
×
233
        }
234

235
        return report.Verdict
×
236
}
237

238
// RunChaosSimple is a simplified version that takes steps, injectors, and validators directly.
239
// This is useful when you don't need the full builder flexibility.
240
//
241
// Usage:
242
//
243
//        func TestSimpleChaos(t *testing.T) {
244
//            target := &MyTarget{}
245
//            steps := []chaoskit.StepFunc{
246
//                func(ctx context.Context, target chaoskit.Target) error {
247
//                    return DoSomething()
248
//                },
249
//            }
250
//            injectors := []chaoskit.Injector{
251
//                injectors.RandomDelay(10*time.Millisecond, 50*time.Millisecond),
252
//            }
253
//            validators := []chaoskit.Validator{
254
//                validators.GoroutineLimit(100),
255
//            }
256
//
257
//            chaoskit.RunChaosSimple(t, "name", target, steps, injectors, validators,
258
//                WithRepeat(10),
259
//                WithDefaultThresholds(),
260
//            )
261
//        }
262
func RunChaosSimple(
263
        t TestingT,
264
        name string,
265
        target chaoskit.Target,
266
        steps []func(context.Context, chaoskit.Target) error,
267
        injectors []chaoskit.Injector,
268
        validators []chaoskit.Validator,
269
        opts ...ChaosTestOption,
NEW
270
) {
×
NEW
271
        RunChaos(t, name, target, func(s *chaoskit.ScenarioBuilder) *chaoskit.ScenarioBuilder {
×
272
                // Add steps
×
273
                for i, stepFn := range steps {
×
274
                        s = s.Step(fmt.Sprintf("step-%d", i+1), stepFn)
×
275
                }
×
276

277
                // Add injectors
278
                for i, inj := range injectors {
×
279
                        s = s.Inject(fmt.Sprintf("injector-%d", i+1), inj)
×
280
                }
×
281

282
                // Add validators
283
                for i, val := range validators {
×
284
                        s = s.Assert(fmt.Sprintf("validator-%d", i+1), val)
×
285
                }
×
286

287
                return s
×
288
        }, opts...)
289
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc