forked from grafana/k6
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrunner.go
142 lines (117 loc) · 4.05 KB
/
runner.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/*
*
* k6 - a next-generation load testing tool
* Copyright (C) 2016 Load Impact
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package lib
import (
"context"
"github.com/loadimpact/k6/stats"
)
// Ensure MiniRunner conforms to Runner.
var _ Runner = &MiniRunner{}
// A Runner is a factory for VUs. It should precompute as much as possible upon creation (parse
// ASTs, load files into memory, etc.), so that spawning VUs becomes as fast as possible.
// The Runner doesn't actually *do* anything in itself, the Executor is responsible for wrapping
// and scheduling these VUs for execution.
//
// TODO: Rename this to something more obvious? This name made sense a very long time ago.
type Runner interface {
// Creates an Archive of the runner. There should be a corresponding NewFromArchive() function
// that will restore the runner from the archive.
MakeArchive() *Archive
// Spawns a new VU. It's fine to make this function rather heavy, if it means a performance
// improvement at runtime. Remember, this is called once per VU and normally only at the start
// of a test - RunOnce() may be called hundreds of thousands of times, and must be fast.
NewVU() (VU, error)
// Runs pre-test setup, if applicable.
Setup(ctx context.Context) error
// Runs post-test teardown, if applicable.
Teardown(ctx context.Context) error
// Returns the default (root) Group.
GetDefaultGroup() *Group
// Get and set options. The initial value will be whatever the script specifies (for JS,
// `export let options = {}`); cmd/run.go will mix this in with CLI-, config- and env-provided
// values and write it back to the runner.
GetOptions() Options
SetOptions(opts Options)
}
// A VU is a Virtual User, that can be scheduled by an Executor.
type VU interface {
// Runs the VU once. The VU is responsible for handling the Halting Problem, eg. making sure
// that execution actually stops when the context is cancelled.
RunOnce(ctx context.Context) ([]stats.Sample, error)
// Assign the VU a new ID. Called by the Executor upon creation, but may be called multiple
// times if the VU is recycled because the test was scaled down and then back up.
Reconfigure(id int64) error
}
// MiniRunner wraps a function in a runner whose VUs will simply call that function.
type MiniRunner struct {
Fn func(ctx context.Context) ([]stats.Sample, error)
SetupFn func(ctx context.Context) error
TeardownFn func(ctx context.Context) error
Group *Group
Options Options
}
func (r MiniRunner) VU() *MiniRunnerVU {
return &MiniRunnerVU{R: r}
}
func (r MiniRunner) MakeArchive() *Archive {
return nil
}
func (r MiniRunner) NewVU() (VU, error) {
return r.VU(), nil
}
func (r MiniRunner) Setup(ctx context.Context) error {
if fn := r.SetupFn; fn != nil {
return fn(ctx)
}
return nil
}
func (r MiniRunner) Teardown(ctx context.Context) error {
if fn := r.TeardownFn; fn != nil {
return fn(ctx)
}
return nil
}
func (r MiniRunner) GetDefaultGroup() *Group {
if r.Group == nil {
r.Group = &Group{}
}
return r.Group
}
func (r MiniRunner) GetOptions() Options {
return r.Options
}
func (r *MiniRunner) SetOptions(opts Options) {
r.Options = opts
}
// A VU spawned by a MiniRunner.
type MiniRunnerVU struct {
R MiniRunner
ID int64
}
func (vu MiniRunnerVU) RunOnce(ctx context.Context) ([]stats.Sample, error) {
if vu.R.Fn == nil {
return []stats.Sample{}, nil
}
return vu.R.Fn(ctx)
}
func (vu *MiniRunnerVU) Reconfigure(id int64) error {
vu.ID = id
return nil
}