1
1
use anyhow:: Context ;
2
2
use std:: path:: { Path , PathBuf } ;
3
3
use testing_framework:: {
4
- EnvTemplate , OnTestError , ServicesConfig , Spin , TestEnvironment , TestEnvironmentConfig ,
5
- TestError , TestResult ,
4
+ EnvTemplate , InMemorySpin , OnTestError , Runtime , ServicesConfig , Spin , SpinConfig ,
5
+ TestEnvironment , TestEnvironmentConfig , TestError , TestResult ,
6
6
} ;
7
7
8
8
/// Configuration for a runtime test
9
- pub struct RuntimeTestConfig {
9
+ pub struct RuntimeTestConfig < R : Runtime > {
10
10
pub test_path : PathBuf ,
11
- pub spin_binary : PathBuf ,
11
+ pub runtime_config : R :: Config ,
12
12
pub on_error : OnTestError ,
13
13
}
14
14
@@ -43,18 +43,20 @@ impl RuntimeTest<Spin> {
43
43
44
44
let config = RuntimeTestConfig {
45
45
test_path : test. path ( ) ,
46
- spin_binary : spin_binary. clone ( ) ,
46
+ runtime_config : SpinConfig {
47
+ binary_path : spin_binary. clone ( ) ,
48
+ } ,
47
49
on_error,
48
50
} ;
49
- RuntimeTest :: bootstrap ( config) ?. run ( ) ;
51
+ Self :: bootstrap ( config) ?. run ( ) ;
50
52
}
51
53
Ok ( ( ) )
52
54
}
53
55
54
- pub fn bootstrap ( config : RuntimeTestConfig ) -> anyhow:: Result < Self > {
56
+ pub fn bootstrap ( config : RuntimeTestConfig < Spin > ) -> anyhow:: Result < Self > {
55
57
log:: info!( "Testing: {}" , config. test_path. display( ) ) ;
56
58
let test_path_clone = config. test_path . to_owned ( ) ;
57
- let spin_binary = config. spin_binary . clone ( ) ;
59
+ let spin_binary = config. runtime_config . binary_path . clone ( ) ;
58
60
let preboot = move |env : & mut TestEnvironment < Spin > | {
59
61
copy_manifest ( & test_path_clone, env) ?;
60
62
Ok ( ( ) )
@@ -77,6 +79,91 @@ impl RuntimeTest<Spin> {
77
79
78
80
/// Run an individual test
79
81
pub fn run ( & mut self ) {
82
+ self . run_test ( |env| {
83
+ let runtime = env. runtime_mut ( ) ;
84
+ let request = testing_framework:: Request :: new ( reqwest:: Method :: GET , "/" ) ;
85
+ let response = runtime. make_http_request ( request) ?;
86
+ if response. status ( ) == 200 {
87
+ return Ok ( ( ) ) ;
88
+ }
89
+ if response. status ( ) != 500 {
90
+ return Err ( anyhow:: anyhow!( "Runtime tests are expected to return either either a 200 or a 500, but it returned a {}" , response. status( ) ) . into ( ) ) ;
91
+ }
92
+ let text = response
93
+ . text ( )
94
+ . context ( "could not get runtime test HTTP response" ) ?;
95
+ if text. is_empty ( ) {
96
+ let stderr = runtime. stderr ( ) ;
97
+ return Err ( anyhow:: anyhow!( "Runtime tests are expected to return a response body, but the response body was empty.\n stderr:\n {stderr}" ) . into ( ) ) ;
98
+ }
99
+
100
+ Err ( TestError :: Failure ( RuntimeTestFailure {
101
+ error : text,
102
+ stderr : runtime. stderr ( ) . to_owned ( ) ,
103
+ } ) )
104
+ } )
105
+ }
106
+ }
107
+
108
+ impl RuntimeTest < InMemorySpin > {
109
+ /// Run the runtime tests suite.
110
+ ///
111
+ /// Error represents an error in bootstrapping the tests. What happens on individual test failures
112
+ /// is controlled by `on_error`.
113
+ pub fn run_all ( tests_path : & Path , on_error : OnTestError ) -> anyhow:: Result < ( ) > {
114
+ for test in std:: fs:: read_dir ( tests_path)
115
+ . with_context ( || format ! ( "failed to read test directory '{}'" , tests_path. display( ) ) ) ?
116
+ {
117
+ let test = test. context ( "I/O error reading entry from test directory" ) ?;
118
+ if !test. file_type ( ) ?. is_dir ( ) {
119
+ log:: debug!(
120
+ "Ignoring non-sub-directory in test directory: {}" ,
121
+ test. path( ) . display( )
122
+ ) ;
123
+ continue ;
124
+ }
125
+
126
+ let config = RuntimeTestConfig {
127
+ test_path : test. path ( ) ,
128
+ runtime_config : ( ) ,
129
+ on_error,
130
+ } ;
131
+ Self :: bootstrap ( config) ?. run ( ) ;
132
+ }
133
+ Ok ( ( ) )
134
+ }
135
+
136
+ pub fn bootstrap ( config : RuntimeTestConfig < InMemorySpin > ) -> anyhow:: Result < Self > {
137
+ log:: info!( "Testing: {}" , config. test_path. display( ) ) ;
138
+ let test_path_clone = config. test_path . to_owned ( ) ;
139
+ let preboot = move |env : & mut TestEnvironment < InMemorySpin > | {
140
+ copy_manifest ( & test_path_clone, env) ?;
141
+ Ok ( ( ) )
142
+ } ;
143
+ let services_config = services_config ( & config) ?;
144
+ let env_config = TestEnvironmentConfig :: in_memory ( services_config, preboot) ;
145
+ let env = TestEnvironment :: up ( env_config) ?;
146
+ Ok ( Self {
147
+ test_path : config. test_path ,
148
+ on_error : config. on_error ,
149
+ env,
150
+ } )
151
+ }
152
+
153
+ fn run ( & mut self ) {
154
+ self . run_test ( |env| {
155
+ let runtime = env. runtime_mut ( ) ;
156
+ todo ! ( )
157
+ } )
158
+ }
159
+ }
160
+
161
+ impl < R > RuntimeTest < R > {
162
+ /// Run an individual test
163
+ pub ( crate ) fn run_test (
164
+ & mut self ,
165
+ test : impl FnOnce ( & mut TestEnvironment < R > ) -> TestResult < RuntimeTestFailure > ,
166
+ ) {
80
167
let on_error = self . on_error ;
81
168
// macro which will look at `on_error` and do the right thing
82
169
macro_rules! error {
@@ -141,7 +228,7 @@ impl RuntimeTest<Spin> {
141
228
}
142
229
}
143
230
144
- fn services_config ( config : & RuntimeTestConfig ) -> anyhow:: Result < ServicesConfig > {
231
+ fn services_config < R : Runtime > ( config : & RuntimeTestConfig < R > ) -> anyhow:: Result < ServicesConfig > {
145
232
let required_services = required_services ( & config. test_path ) ?;
146
233
let services_config = ServicesConfig :: new ( required_services) ?;
147
234
Ok ( services_config)
@@ -179,30 +266,6 @@ fn copy_manifest<R>(test_dir: &Path, env: &mut TestEnvironment<R>) -> anyhow::Re
179
266
Ok ( ( ) )
180
267
}
181
268
182
- fn test ( env : & mut TestEnvironment < Spin > ) -> TestResult < RuntimeTestFailure > {
183
- let runtime = env. runtime_mut ( ) ;
184
- let request = testing_framework:: Request :: new ( reqwest:: Method :: GET , "/" ) ;
185
- let response = runtime. make_http_request ( request) ?;
186
- if response. status ( ) == 200 {
187
- return Ok ( ( ) ) ;
188
- }
189
- if response. status ( ) != 500 {
190
- return Err ( anyhow:: anyhow!( "Runtime tests are expected to return either either a 200 or a 500, but it returned a {}" , response. status( ) ) . into ( ) ) ;
191
- }
192
- let text = response
193
- . text ( )
194
- . context ( "could not get runtime test HTTP response" ) ?;
195
- if text. is_empty ( ) {
196
- let stderr = runtime. stderr ( ) ;
197
- return Err ( anyhow:: anyhow!( "Runtime tests are expected to return a response body, but the response body was empty.\n stderr:\n {stderr}" ) . into ( ) ) ;
198
- }
199
-
200
- Err ( TestError :: Failure ( RuntimeTestFailure {
201
- error : text,
202
- stderr : runtime. stderr ( ) . to_owned ( ) ,
203
- } ) )
204
- }
205
-
206
269
/// A runtime test failure
207
270
struct RuntimeTestFailure {
208
271
/// The error message returned by the runtime
0 commit comments