From 65c107e11115739e557877a35155cdf4914257e0 Mon Sep 17 00:00:00 2001 From: ryutamago Date: Wed, 18 Sep 2024 15:03:24 +0100 Subject: [PATCH] test(jstzd): add container test --- Cargo.lock | 41 +++++++ Cargo.toml | 2 + crates/jstzd/Cargo.toml | 3 + crates/jstzd/src/docker/container.rs | 2 +- crates/jstzd/src/docker/runnable_image.rs | 2 +- crates/jstzd/tests/container.rs | 137 ++++++++++++++++++++++ crates/jstzd/tests/pull_image.rs | 3 +- 7 files changed, 187 insertions(+), 3 deletions(-) create mode 100644 crates/jstzd/tests/container.rs diff --git a/Cargo.lock b/Cargo.lock index 8dc063053..fc9ed13a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2667,6 +2667,7 @@ dependencies = [ "bytes", "futures-util", "log", + "serial_test", "tokio", ] @@ -3871,6 +3872,15 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scc" +version = "2.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c947adb109a8afce5fc9c7bf951f87f146e9147b3a6a58413105628fb1d1e66" +dependencies = [ + "sdd", +] + [[package]] name = "schannel" version = "0.1.22" @@ -3905,6 +3915,12 @@ dependencies = [ "untrusted", ] +[[package]] +name = "sdd" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a7b59a5d9b0099720b417b6325d91a52cbf5b3dcb5041d864be53eefa58abc" + [[package]] name = "security-framework" version = "2.3.1" @@ -4055,6 +4071,31 @@ dependencies = [ "unsafe-libyaml", ] +[[package]] +name = "serial_test" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b4b487fe2acf240a021cf57c6b2b4903b1e78ca0ecd862a71b71d2a51fed77d" +dependencies = [ + "futures", + "log", + "once_cell", + "parking_lot", + "scc", + "serial_test_derive", +] + +[[package]] +name = "serial_test_derive" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82fe9db325bcef1fbcde82e078a5cc4efdf787e96b3b9cf45b50b529f2083d67" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + [[package]] name = "sha1" version = "0.10.6" diff --git a/Cargo.toml b/Cargo.toml index ead1a668d..e355ea77b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -79,6 +79,7 @@ regex = "1" reqwest = { version = "0.11.24", features = ["json"] } reqwest-eventsource = "0.5.0" rustyline = "14.0.0" +serial_test = "3.1.1" serde = { version = "1.0.196", features = ["derive"] } serde-wasm-bindgen = "0.6.5" serde_json = "1.0.107" @@ -103,6 +104,7 @@ wasm-bindgen = "0.2.92" async-dropper = { version = "0.3.1", features = ["tokio", "simple"] } async-trait = "0.1.82" + [workspace.dependencies.tezos-smart-rollup] version = "0.2.2" default-features = false diff --git a/crates/jstzd/Cargo.toml b/crates/jstzd/Cargo.toml index f0e210f31..3c52ebf28 100644 --- a/crates/jstzd/Cargo.toml +++ b/crates/jstzd/Cargo.toml @@ -19,3 +19,6 @@ log.workspace = true name = "jstzd" path = "src/main.rs" + +[dev-dependencies] +serial_test.workspace = true diff --git a/crates/jstzd/src/docker/container.rs b/crates/jstzd/src/docker/container.rs index c4d326199..8e532d640 100644 --- a/crates/jstzd/src/docker/container.rs +++ b/crates/jstzd/src/docker/container.rs @@ -43,7 +43,7 @@ impl Container { self.id )); } - return Err(e.into()); + Err(e.into()) } } } diff --git a/crates/jstzd/src/docker/runnable_image.rs b/crates/jstzd/src/docker/runnable_image.rs index 544cde49f..95889326c 100644 --- a/crates/jstzd/src/docker/runnable_image.rs +++ b/crates/jstzd/src/docker/runnable_image.rs @@ -142,7 +142,7 @@ impl RunnableImage { self.image.image_uri() )); } - return Err(err.into()); + Err(err.into()) } } } diff --git a/crates/jstzd/tests/container.rs b/crates/jstzd/tests/container.rs new file mode 100644 index 000000000..68643416b --- /dev/null +++ b/crates/jstzd/tests/container.rs @@ -0,0 +1,137 @@ +use std::sync::Arc; + +use anyhow::Result; +use bollard::{container::ListContainersOptions, Docker}; +use jstzd::docker::{GenericImage, Image, RunnableImage}; +use serial_test::serial; + +#[tokio::test] +#[serial] +async fn creates_container() -> Result<()> { + let docker = docker(); + let image = image(docker.clone()).await?; + let runnable_image = RunnableImage::new(image.clone(), "test_container1"); + let container = runnable_image.create_container(docker.clone()).await?; + let containers = docker + .list_containers(Some(ListContainersOptions:: { + all: true, + ..Default::default() + })) + .await?; + assert!(containers + .iter() + .any(|c| c.id.as_deref() == Some(&container.id))); + container.cleanup().await?; + Ok(()) +} + +#[tokio::test] +#[serial] +async fn runs_container() -> Result<()> { + let docker = docker(); + let image = image(docker.clone()).await?; + let cmd = vec!["sh".to_string(), "-c".to_string(), "sleep 1".to_string()]; + let runnable_image = + RunnableImage::new(image.clone(), "test_container2").with_overridden_cmd(cmd); + let container = runnable_image.create_container(docker.clone()).await?; + container.start().await?; + let containers = docker + .list_containers(Some(ListContainersOptions:: { + ..Default::default() + })) + .await?; + assert!(containers + .iter() + .any(|c| c.id.as_deref() == Some(&container.id))); + container.cleanup().await?; + Ok(()) +} + +#[tokio::test] +#[serial] +async fn cleans_up_container() -> Result<()> { + let docker = docker(); + let image = image(docker.clone()).await?; + let runnable_image = RunnableImage::new(image.clone(), "test_container3"); + let container = runnable_image.create_container(docker.clone()).await?; + container.cleanup().await?; + let containers = docker + .list_containers(Some(ListContainersOptions:: { + all: true, + ..Default::default() + })) + .await?; + assert!(containers + .iter() + .any(|c| c.id.as_deref() != Some(&container.id))); + Ok(()) +} + +#[tokio::test] +#[serial] +async fn removing_container_twice_fails() -> Result<()> { + let docker = docker(); + let image = image(docker.clone()).await?; + let runnable_image = RunnableImage::new(image.clone(), "test_container4"); + let container = runnable_image.create_container(docker.clone()).await?; + container.start().await?; + container.stop().await?; + container.remove().await?; + let result = container.remove().await; + assert!(result.is_err()); + assert_eq!( + result.err().unwrap().to_string(), + format!("Failed to remove non existent container: {}", container.id) + ); + Ok(()) +} + +#[tokio::test] +#[serial] +async fn removing_running_container_fails() -> Result<()> { + let docker = docker(); + let image = image(docker.clone()).await?; + let cmd = vec!["sh".to_string(), "-c".to_string(), "sleep 1".to_string()]; + let runnable_image = + RunnableImage::new(image.clone(), "test_container5").with_overridden_cmd(cmd); + let container = runnable_image.create_container(docker.clone()).await?; + container.start().await?; + let result = container.remove().await; + assert!(result.is_err()); + assert!(result + .err() + .unwrap() + .to_string() + .contains("stop the container before removing")); + container.cleanup().await?; + Ok(()) +} + +#[tokio::test] +#[serial] +async fn running_container_with_no_image_fails() -> Result<()> { + let docker = docker(); + let image = image(docker.clone()).await?; + docker.remove_image(&image.image_uri(), None, None).await?; + let runnable_image = RunnableImage::new(image.clone(), "test_container6"); + let result = runnable_image.create_container(docker.clone()).await; + assert!(result.is_err()); + assert_eq!( + result.err().unwrap().to_string(), + format!( + "Image: {} not found, please make sure the image is pulled", + image.image_uri() + ) + ); + Ok(()) +} + +fn docker() -> Arc { + Arc::new(Docker::connect_with_socket_defaults().unwrap()) +} + +async fn image(client: Arc) -> Result { + let image = GenericImage::new("busybox").with_tag("stable"); + image.pull_image(client).await?; + Ok(image) +} diff --git a/crates/jstzd/tests/pull_image.rs b/crates/jstzd/tests/pull_image.rs index e7599aecf..ae8bc5706 100644 --- a/crates/jstzd/tests/pull_image.rs +++ b/crates/jstzd/tests/pull_image.rs @@ -3,6 +3,7 @@ use std::{collections::HashMap, sync::Arc}; use anyhow::Result; use bollard::{image::ListImagesOptions, secret::ImageSummary, Docker}; use jstzd::docker::{GenericImage, Image}; +use serial_test::serial; // search image locally async fn search_local_image( @@ -24,8 +25,8 @@ async fn search_local_image( Err(_) => Err(anyhow::anyhow!("Image not found")), } } - #[tokio::test] +#[serial] async fn test_pull_image() -> Result<()> { let docker = Docker::connect_with_socket_defaults().unwrap(); let docker = Arc::new(docker);