Skip to content

Commit

Permalink
Add redis support
Browse files Browse the repository at this point in the history
Signed-off-by: Ryan Levick <ryan.levick@fermyon.com>
  • Loading branch information
rylev committed Jan 11, 2024
1 parent a3f46a6 commit 0e81ea5
Show file tree
Hide file tree
Showing 19 changed files with 250 additions and 712 deletions.
22 changes: 19 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ which = "4.2.5"
e2e-testing = { path = "crates/e2e-testing" }
http-body-util = { workspace = true }
testing-framework = { path = "tests/testing-framework" }
redis = "0.24"
runtime-tests = { path = "tests/runtime-tests" }
test-components = { path = "tests/test-components" }
test-codegen-macro = { path = "crates/test-codegen-macro" }
Expand Down
14 changes: 10 additions & 4 deletions tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ mod integration_tests {
"{}/{}",
RUST_HTTP_INTEGRATION_TEST, DEFAULT_MANIFEST_LOCATION
),
|spin| {
|env| {
let spin = env.runtime_mut();
assert_spin_status(spin, "/test/hello", 200)?;
assert_spin_status(spin, "/test/hello/wildcards/should/be/handled", 200)?;
assert_spin_status(spin, "/thisshouldfail", 404)?;
Expand All @@ -56,7 +57,8 @@ mod integration_tests {
fn test_duplicate_rust_local() -> Result<()> {
integration_test(
format!("{}/{}", RUST_HTTP_INTEGRATION_TEST, "double-trouble.toml"),
|spin| {
|env| {
let spin = env.runtime_mut();
assert_spin_status(spin, "/route1", 200)?;
assert_spin_status(spin, "/route2", 200)?;
assert_spin_status(spin, "/thisshouldfail", 404)?;
Expand Down Expand Up @@ -242,7 +244,9 @@ mod integration_tests {

fn integration_test(
manifest_path: impl Into<PathBuf>,
test: impl FnOnce(&mut testing_framework::Spin) -> testing_framework::TestResult<anyhow::Error>
test: impl FnOnce(
&mut testing_framework::TestEnvironment<testing_framework::Spin>,
) -> testing_framework::TestResult<anyhow::Error>
+ 'static,
) -> anyhow::Result<()> {
let manifest_path = manifest_path.into();
Expand All @@ -261,9 +265,11 @@ mod integration_tests {
Ok(())
},
testing_framework::ServicesConfig::none(),
testing_framework::SpinMode::Http,
);
let mut env = testing_framework::TestEnvironment::up(spin)?;
Ok(env.test(test)?)
test(&mut env)?;
Ok(())
}

fn assert_spin_status(
Expand Down
13 changes: 10 additions & 3 deletions tests/runtime-tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,13 @@ impl RuntimeTest<Spin> {
Ok(())
};
let services_config = services_config(&config)?;
let env_config = TestEnvironmentConfig::spin(spin_binary, [], preboot, services_config);
let env_config = TestEnvironmentConfig::spin(
spin_binary,
[],
preboot,
services_config,
testing_framework::SpinMode::Http,
);
let env = TestEnvironment::up(env_config)?;
Ok(Self {
test_path: config.test_path,
Expand All @@ -84,7 +90,7 @@ impl RuntimeTest<Spin> {
}
};
}
let response = self.env.test(test);
let response = test(&mut self.env);
let error_file = self.test_path.join("error.txt");
match response {
Ok(()) if !error_file.exists() => log::info!("Test passed!"),
Expand Down Expand Up @@ -173,7 +179,8 @@ fn copy_manifest<R>(test_dir: &Path, env: &mut TestEnvironment<R>) -> anyhow::Re
Ok(())
}

fn test(runtime: &mut Spin) -> TestResult<RuntimeTestFailure> {
fn test(env: &mut TestEnvironment<Spin>) -> TestResult<RuntimeTestFailure> {
let runtime = env.runtime_mut();
let response = runtime.make_http_request(reqwest::Method::GET, "/")?;
if response.status() == 200 {
return Ok(());
Expand Down
124 changes: 88 additions & 36 deletions tests/spinup_tests.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,25 @@
use anyhow::Context;
use redis::Commands;
use std::path::PathBuf;

#[cfg(feature = "e2e-tests")]
mod testcases;

fn spin_binary() -> PathBuf {
env!("CARGO_BIN_EXE_spin").into()
/// Helper macro to assert that a condition is true eventually
macro_rules! assert_eventually {
($e:expr) => {
let mut i = 0;
loop {
if $e {
break;
} else if i > 20 {
assert!($e);
break;
}
std::thread::sleep(std::time::Duration::from_millis(100));
i += 1;
}
};
}

#[test]
Expand All @@ -14,8 +29,11 @@ fn key_value_cli_flag() -> anyhow::Result<()> {
let test_value = uuid::Uuid::new_v4().to_string();
run_test(
"key-value",
testing_framework::SpinMode::Http,
["--key-value".into(), format!("{test_key}={test_value}")],
move |spin: &mut testing_framework::Spin| {
testing_framework::ServicesConfig::none(),
move |env| {
let spin = env.runtime_mut();
assert_spin_request(
spin,
reqwest::Method::GET,
Expand All @@ -29,36 +47,34 @@ fn key_value_cli_flag() -> anyhow::Result<()> {
}

#[test]
/// Test that basic http trigger support works
fn http_smoke_test() -> anyhow::Result<()> {
run_test(
"smoke-test",
"http-smoke-test",
testing_framework::SpinMode::Http,
[],
move |spin: &mut testing_framework::Spin| {
testing_framework::ServicesConfig::none(),
move |env| {
let spin = env.runtime_mut();
assert_spin_request(
spin,
reqwest::Method::GET,
&format!("/test/hello"),
"/test/hello",
200,
"I'm a teapot",
)?;
assert_spin_request(
spin,
reqwest::Method::GET,
&format!("/test/hello/wildcards/should/be/handled"),
"/test/hello/wildcards/should/be/handled",
200,
"I'm a teapot",
)?;
assert_spin_request(spin, reqwest::Method::GET, "/thishsouldfail", 404, "")?;
assert_spin_request(
spin,
reqwest::Method::GET,
&format!("/thishsouldfail"),
404,
"",
)?;
assert_spin_request(
spin,
reqwest::Method::GET,
&format!("/test/hello/test-placement"),
"/test/hello/test-placement",
200,
"text for test",
)
Expand All @@ -68,14 +84,63 @@ fn http_smoke_test() -> anyhow::Result<()> {
Ok(())
}

#[test]
/// Test that basic redis trigger support works
fn redis_smoke_test() -> anyhow::Result<()> {
run_test(
"redis-smoke-test",
testing_framework::SpinMode::Redis,
[],
testing_framework::ServicesConfig::new(vec!["redis".into()])?,
move |env| {
let redis_port = env
.services_mut()
.get_port(6379)?
.context("no redis port was exposed by test services")?;

let mut redis = redis::Client::open(format!("redis://localhost:{redis_port}"))
.context("could not connect to redis in test")?;
redis
.publish("my-channel", "msg-from-test")
.context("could not publish test message to redis")?;
assert_eventually!({
match env.read_file(".spin/logs/hello_stdout.txt") {
Ok(logs) => {
let logs = String::from_utf8_lossy(&logs);
logs.contains("Got message: 'msg-from-test'")
}
Err(e) if e.kind() == std::io::ErrorKind::NotFound => false,
Err(e) => return Err(anyhow::anyhow!("could not read stdout file: {e}").into()),
}
});
Ok(())
},
)?;

Ok(())
}

/// Run an e2e test
fn run_test(
test_name: impl Into<String>,
mode: testing_framework::SpinMode,
spin_up_args: impl IntoIterator<Item = String>,
test: impl testing_framework::Test<Runtime = testing_framework::Spin, Failure = anyhow::Error>,
services_config: testing_framework::ServicesConfig,
test: impl FnOnce(
&mut testing_framework::TestEnvironment<testing_framework::Spin>,
) -> testing_framework::TestResult<anyhow::Error>
+ 'static,
) -> testing_framework::TestResult<anyhow::Error> {
let config = environment_config(test_name.into(), spin_up_args);
testing_framework::TestEnvironment::up(config)?.test(test)?;
let test_name = test_name.into();
let config = testing_framework::TestEnvironmentConfig::spin(
spin_binary(),
spin_up_args,
move |env| preboot(&test_name, env),
services_config,
mode,
);
let mut env = testing_framework::TestEnvironment::up(config)?;
test(&mut env)?;
Ok(())
}

Expand All @@ -101,19 +166,6 @@ fn assert_spin_request(
Ok(())
}

/// Get the configuration for a test environment
fn environment_config(
test_name: String,
spin_up_args: impl IntoIterator<Item = String>,
) -> testing_framework::TestEnvironmentConfig<testing_framework::Spin> {
testing_framework::TestEnvironmentConfig::spin(
spin_binary(),
spin_up_args,
move |env| preboot(&test_name, env),
testing_framework::ServicesConfig::none(),
)
}

/// Get the test environment ready to run a test
fn preboot(
test: &str,
Expand All @@ -130,6 +182,11 @@ fn preboot(
Ok(())
}

/// Get the spin binary path
fn spin_binary() -> PathBuf {
env!("CARGO_BIN_EXE_spin").into()
}

#[cfg(feature = "e2e-tests")]
mod spinup_tests {
use super::testcases;
Expand Down Expand Up @@ -197,11 +254,6 @@ mod spinup_tests {
testcases::assets_routing_works(CONTROLLER).await
}

#[tokio::test]
async fn head_rust_sdk_redis() {
testcases::head_rust_sdk_redis(CONTROLLER).await
}

#[tokio::test]
async fn llm_works() {
testcases::llm_works(CONTROLLER).await
Expand Down
9 changes: 9 additions & 0 deletions tests/test-components/components/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions tests/test-components/components/redis-smoke-test/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "head-rust-sdk-redis"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib"]

[dependencies]
anyhow = "1"
bytes = "1"
spin-sdk = { path = "../../../../sdk/rust" }
2 changes: 0 additions & 2 deletions tests/testcases/head-rust-sdk-redis/.cargo/config.toml

This file was deleted.

Loading

0 comments on commit 0e81ea5

Please sign in to comment.