1
- use argh:: FromArgs ;
2
1
use rlua:: { Lua , RegistryKey } ;
3
2
use ureq:: { Agent , AgentBuilder } ;
4
3
use url:: Url ;
@@ -10,6 +9,7 @@ use std::thread;
10
9
use std:: thread:: JoinHandle ;
11
10
use std:: time:: Duration ;
12
11
12
+ mod cli;
13
13
mod config_duration;
14
14
mod grunt;
15
15
mod http_response_table;
@@ -19,55 +19,32 @@ mod pipeline;
19
19
mod pipeline_action;
20
20
mod shared_lua;
21
21
mod situation;
22
+ mod step_combinator;
22
23
mod step_error;
23
24
mod step_goto;
24
25
mod step_http;
25
26
mod step_lua;
27
+ mod step_validator;
26
28
29
+ use crate :: cli:: parse_args;
27
30
use crate :: grunt:: Grunt ;
28
31
use crate :: persona:: Persona ;
29
32
use crate :: pipe_contents:: PipeContents ;
30
33
use crate :: pipeline:: StepCompletion ;
31
34
use crate :: pipeline_action:: { ControlFlow , Http , PipelineAction as PA , Reference } ;
32
- use crate :: situation:: { Situation , SituationSpec } ;
33
- use crate :: step_error:: StepError ;
35
+ use crate :: shared_lua:: attach_seatrial_stdlib;
36
+ use crate :: situation:: Situation ;
37
+ use crate :: step_combinator:: step as do_step_combinator;
38
+ use crate :: step_error:: { StepError , StepResult } ;
34
39
use crate :: step_goto:: step as do_step_goto;
35
40
use crate :: step_http:: {
36
41
step_delete as do_step_http_delete, step_get as do_step_http_get,
37
42
step_head as do_step_http_head, step_post as do_step_http_post, step_put as do_step_http_put,
38
43
} ;
39
44
use crate :: step_lua:: step_function as do_step_lua_function;
40
45
41
- /// situational-mock-based load testing
42
- #[ derive( FromArgs ) ]
43
- struct CmdArgs {
44
- /// integral multiplier for grunt counts (minimum 1)
45
- #[ argh( option, short = 'm' , default = "1" ) ]
46
- multiplier : usize ,
47
-
48
- /// base URL for all situations in this run
49
- #[ argh( positional) ]
50
- base_url : String ,
51
-
52
- // work around https://github.com/google/argh/issues/13 wherein repeatable positional arguments
53
- // (situations, in this struct) allow any vec length 0+, where we require a vec length 1+. this
54
- // could be hacked around with some From magic and a custom Vec, but this is more
55
- // straightforward
56
- /// path to a RON file in seatrial(5) situation config format
57
- #[ argh( positional) ]
58
- req_situation : SituationSpec ,
59
-
60
- /// optional paths to additional RON files in seatrial(5) situation config format
61
- #[ argh( positional) ]
62
- situations : Vec < SituationSpec > ,
63
- }
64
-
65
46
fn main ( ) -> std:: io:: Result < ( ) > {
66
- let args = {
67
- let mut args: CmdArgs = argh:: from_env ( ) ;
68
- args. situations . insert ( 0 , args. req_situation . clone ( ) ) ;
69
- args
70
- } ;
47
+ let args = parse_args ( ) ;
71
48
72
49
// TODO: no unwrap, which will also kill the nasty parens
73
50
let base_url = ( if args. base_url . ends_with ( '/' ) {
@@ -135,7 +112,9 @@ fn grunt_worker(
135
112
grunt : & Grunt ,
136
113
tx : mpsc:: Sender < String > ,
137
114
) {
138
- let lua = Lua :: new ( ) ;
115
+ let lua = Lua :: default ( ) ;
116
+ // TODO: no unwrap
117
+ attach_seatrial_stdlib ( & lua) . unwrap ( ) ;
139
118
140
119
let user_script_registry_key = situation
141
120
. lua_file
@@ -226,8 +205,18 @@ fn grunt_worker(
226
205
Ok ( StepCompletion :: WithWarnings {
227
206
next_index,
228
207
pipe_data,
208
+ warnings,
229
209
} ) => {
230
- // TODO: log event for warnings
210
+ // TODO: in addition to printing, we need to track structured events (not just
211
+ // for these warnings, but for all sorts of pipeline actions)
212
+
213
+ for warning in warnings {
214
+ eprintln ! (
215
+ "[{}] warning issued during pipeline step completion: {}" ,
216
+ grunt. name, warning
217
+ ) ;
218
+ }
219
+
231
220
current_pipe_contents = pipe_data;
232
221
current_pipe_idx = next_index;
233
222
}
@@ -243,6 +232,28 @@ fn grunt_worker(
243
232
eprintln ! ( "[{}] step was: {:?}" , grunt. name, step) ;
244
233
break ;
245
234
}
235
+ Err ( StepError :: Validation ( err) ) => {
236
+ eprintln ! (
237
+ "[{}] aborting due to validation error in pipeline" ,
238
+ grunt. name
239
+ ) ;
240
+ eprintln ! ( "[{}] err was: {}" , grunt. name, err) ;
241
+ eprintln ! ( "[{}] step was: {:?}" , grunt. name, step) ;
242
+ break ;
243
+ }
244
+ // TODO: more details - we're just not plumbing the details around
245
+ Err ( StepError :: ValidationSucceededUnexpectedly ) => {
246
+ eprintln ! (
247
+ "[{}] aborting because a validation succeeded where we expected a failure" ,
248
+ grunt. name
249
+ ) ;
250
+ eprintln ! (
251
+ "[{}] this is an error in seatrial - TODO fix this" ,
252
+ grunt. name
253
+ ) ;
254
+ eprintln ! ( "[{}] step was: {:?}" , grunt. name, step) ;
255
+ break ;
256
+ }
246
257
Err ( StepError :: InvalidActionInContext ) => {
247
258
eprintln ! (
248
259
"[{}] aborting due to invalid action definition in the given context" ,
@@ -328,7 +339,7 @@ fn do_step<'a>(
328
339
agent : & Agent ,
329
340
last : Option < & PipeContents > ,
330
341
goto_counters : & mut HashMap < usize , usize > ,
331
- ) -> Result < StepCompletion , StepError > {
342
+ ) -> StepResult {
332
343
match step {
333
344
PA :: ControlFlow ( ControlFlow :: GoTo { index, max_times } ) => {
334
345
if let Some ( times) = max_times {
@@ -411,6 +422,9 @@ fn do_step<'a>(
411
422
lua,
412
423
)
413
424
}
425
+ PA :: Combinator ( combo) => {
426
+ do_step_combinator ( idx, combo, lua, user_script_registry_key, last)
427
+ }
414
428
// TODO: remove
415
429
_ => Ok ( StepCompletion :: Normal {
416
430
next_index : idx + 1 ,
0 commit comments