Skip to content

Commit 7f44069

Browse files
committed
Some small test framework clean up
Signed-off-by: Ryan Levick <[email protected]>
1 parent 275bf8c commit 7f44069

File tree

3 files changed

+85
-81
lines changed

3 files changed

+85
-81
lines changed

tests/testing-framework/src/runtimes/in_process_spin.rs

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use crate::{
44
http::{Request, Response},
5-
Runtime,
5+
Runtime, ServicesConfig, TestEnvironment, TestEnvironmentConfig,
66
};
77
use anyhow::Context as _;
88

@@ -56,3 +56,48 @@ impl Runtime for InProcessSpin {
5656
Ok(())
5757
}
5858
}
59+
60+
impl TestEnvironmentConfig<InProcessSpin> {
61+
pub fn in_process(
62+
services_config: ServicesConfig,
63+
preboot: impl FnOnce(&mut TestEnvironment<InProcessSpin>) -> anyhow::Result<()> + 'static,
64+
) -> Self {
65+
Self {
66+
services_config,
67+
create_runtime: Box::new(|env| {
68+
preboot(env)?;
69+
tokio::runtime::Runtime::new()
70+
.context("failed to start tokio runtime")?
71+
.block_on(async {
72+
use spin_trigger::{
73+
loader::TriggerLoader, HostComponentInitData, RuntimeConfig,
74+
TriggerExecutorBuilder,
75+
};
76+
use spin_trigger_http::HttpTrigger;
77+
let locked_app = spin_loader::from_file(
78+
env.path().join("spin.toml"),
79+
spin_loader::FilesMountStrategy::Direct,
80+
None,
81+
)
82+
.await?;
83+
let json = locked_app.to_json()?;
84+
std::fs::write(env.path().join("locked.json"), json)?;
85+
86+
let loader = TriggerLoader::new(env.path().join(".working_dir"), false);
87+
let mut builder = TriggerExecutorBuilder::<HttpTrigger>::new(loader);
88+
// TODO(rylev): see if we can reuse the builder from spin_trigger instead of duplicating it here
89+
builder.hooks(spin_trigger::network::Network::default());
90+
let trigger = builder
91+
.build(
92+
format!("file:{}", env.path().join("locked.json").display()),
93+
RuntimeConfig::default(),
94+
HostComponentInitData::default(),
95+
)
96+
.await?;
97+
98+
Result::<_, anyhow::Error>::Ok(InProcessSpin::new(trigger))
99+
})
100+
}),
101+
}
102+
}
103+
}

tests/testing-framework/src/runtimes/spin_cli.rs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ use super::SpinAppType;
66
use crate::{
77
http::{Request, Response},
88
io::OutputStream,
9-
Runtime, TestEnvironment,
9+
Runtime, ServicesConfig, TestEnvironment, TestEnvironmentConfig,
1010
};
1111
use std::{
12-
path::Path,
12+
path::{Path, PathBuf},
1313
process::{Command, Stdio},
1414
};
1515

@@ -249,6 +249,31 @@ impl SpinCli {
249249
}
250250
}
251251

252+
impl TestEnvironmentConfig<SpinCli> {
253+
/// Configure a test environment that uses a local Spin binary as a runtime
254+
///
255+
/// * `spin_binary` - the path to the Spin binary
256+
/// * `preboot` - a callback that happens after the services have started but before the runtime is
257+
/// * `test` - a callback that runs the test against the runtime
258+
/// * `services_config` - the services that the test requires
259+
pub fn spin(
260+
spin_binary: PathBuf,
261+
spin_up_args: impl IntoIterator<Item = String>,
262+
preboot: impl FnOnce(&mut TestEnvironment<SpinCli>) -> anyhow::Result<()> + 'static,
263+
services_config: ServicesConfig,
264+
app_type: SpinAppType,
265+
) -> Self {
266+
let spin_up_args = spin_up_args.into_iter().collect();
267+
Self {
268+
services_config,
269+
create_runtime: Box::new(move |env| {
270+
preboot(env)?;
271+
SpinCli::start(&spin_binary, env, spin_up_args, app_type)
272+
}),
273+
}
274+
}
275+
}
276+
252277
impl Drop for SpinCli {
253278
fn drop(&mut self) {
254279
kill_process(&mut self.process);

tests/testing-framework/src/test_environment.rs

Lines changed: 12 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
1-
use std::{
2-
collections::HashMap,
3-
path::{Path, PathBuf},
4-
};
1+
use std::{collections::HashMap, path::Path};
52

63
use crate::{
7-
runtimes::{in_process_spin::InProcessSpin, spin_cli::SpinCli, SpinAppType},
84
services::{Services, ServicesConfig},
95
Runtime,
106
};
@@ -23,6 +19,8 @@ pub struct TestEnvironment<R> {
2319

2420
impl<R: Runtime> TestEnvironment<R> {
2521
/// Spin up a test environment with a runtime
22+
///
23+
/// `config` specifies the services to run and how to create the runtime.
2624
pub fn up(
2725
config: TestEnvironmentConfig<R>,
2826
init_env: impl FnOnce(&mut Self) -> crate::TestResult<anyhow::Error> + 'static,
@@ -33,7 +31,9 @@ impl<R: Runtime> TestEnvironment<R> {
3331
env.start_runtime(runtime)
3432
}
3533

36-
/// Whether an error has occurred
34+
/// Returns an error if the environment is not healthy.
35+
///
36+
/// If a runtime is present, it will also be checked for errors.
3737
fn error(&mut self) -> anyhow::Result<()> {
3838
self.services.healthy()?;
3939
if let Some(runtime) = &mut self.runtime {
@@ -45,6 +45,8 @@ impl<R: Runtime> TestEnvironment<R> {
4545

4646
impl<R> TestEnvironment<R> {
4747
/// Spin up a test environment without a runtime
48+
///
49+
/// `services` specifies the services to run.
4850
pub fn boot(services: &ServicesConfig) -> anyhow::Result<Self> {
4951
let temp = temp_dir::TempDir::new()
5052
.context("failed to produce a temporary directory to run the test in")?;
@@ -61,6 +63,8 @@ impl<R> TestEnvironment<R> {
6163
}
6264

6365
/// Start the runtime
66+
///
67+
/// Will error if the environment is not healthy.
6468
pub fn start_runtime<N: Runtime>(self, runtime: N) -> anyhow::Result<TestEnvironment<N>> {
6569
let mut this = TestEnvironment {
6670
temp: self.temp,
@@ -182,77 +186,7 @@ impl<R> TestEnvironment<R> {
182186
/// Configuration for a test environment
183187
pub struct TestEnvironmentConfig<R> {
184188
/// A callback to create a runtime given a path to a temporary directory
185-
create_runtime: Box<RuntimeCreator<R>>,
189+
pub create_runtime: Box<RuntimeCreator<R>>,
186190
/// The services that the test requires
187-
services_config: ServicesConfig,
188-
}
189-
190-
impl TestEnvironmentConfig<SpinCli> {
191-
/// Configure a test environment that uses a local Spin binary as a runtime
192-
///
193-
/// * `spin_binary` - the path to the Spin binary
194-
/// * `preboot` - a callback that happens after the services have started but before the runtime is
195-
/// * `test` - a callback that runs the test against the runtime
196-
/// * `services_config` - the services that the test requires
197-
pub fn spin(
198-
spin_binary: PathBuf,
199-
spin_up_args: impl IntoIterator<Item = String>,
200-
preboot: impl FnOnce(&mut TestEnvironment<SpinCli>) -> anyhow::Result<()> + 'static,
201-
services_config: ServicesConfig,
202-
app_type: SpinAppType,
203-
) -> Self {
204-
let spin_up_args = spin_up_args.into_iter().collect();
205-
Self {
206-
services_config,
207-
create_runtime: Box::new(move |env| {
208-
preboot(env)?;
209-
SpinCli::start(&spin_binary, env, spin_up_args, app_type)
210-
}),
211-
}
212-
}
213-
}
214-
215-
impl TestEnvironmentConfig<InProcessSpin> {
216-
pub fn in_process(
217-
services_config: ServicesConfig,
218-
preboot: impl FnOnce(&mut TestEnvironment<InProcessSpin>) -> anyhow::Result<()> + 'static,
219-
) -> Self {
220-
Self {
221-
services_config,
222-
create_runtime: Box::new(|env| {
223-
preboot(env)?;
224-
tokio::runtime::Runtime::new()
225-
.context("failed to start tokio runtime")?
226-
.block_on(async {
227-
use spin_trigger::{
228-
loader::TriggerLoader, HostComponentInitData, RuntimeConfig,
229-
TriggerExecutorBuilder,
230-
};
231-
use spin_trigger_http::HttpTrigger;
232-
let locked_app = spin_loader::from_file(
233-
env.path().join("spin.toml"),
234-
spin_loader::FilesMountStrategy::Direct,
235-
None,
236-
)
237-
.await?;
238-
let json = locked_app.to_json()?;
239-
std::fs::write(env.path().join("locked.json"), json)?;
240-
241-
let loader = TriggerLoader::new(env.path().join(".working_dir"), false);
242-
let mut builder = TriggerExecutorBuilder::<HttpTrigger>::new(loader);
243-
// TODO(rylev): see if we can reuse the builder from spin_trigger instead of duplicating it here
244-
builder.hooks(spin_trigger::network::Network::default());
245-
let trigger = builder
246-
.build(
247-
format!("file:{}", env.path().join("locked.json").display()),
248-
RuntimeConfig::default(),
249-
HostComponentInitData::default(),
250-
)
251-
.await?;
252-
253-
Result::<_, anyhow::Error>::Ok(InProcessSpin::new(trigger))
254-
})
255-
}),
256-
}
257-
}
191+
pub services_config: ServicesConfig,
258192
}

0 commit comments

Comments
 (0)