summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorJustin Wernick <justin@worthe-it.co.za>2023-03-09 09:37:08 +0200
committerJustin Wernick <justin@worthe-it.co.za>2023-03-09 09:37:08 +0200
commite4de0c976a5546e4398df3689b9fd283ee3fe4d0 (patch)
tree378e1daf9887a90bd2de0dc7e413b1f709e3eed5 /tests
parent7bdbcb6401de165088a2e5be3494926fb320f6ca (diff)
Make docker build only run once even if there are multiple tests using it
Diffstat (limited to 'tests')
-rw-r--r--tests/server_shell.rs71
1 files changed, 51 insertions, 20 deletions
diff --git a/tests/server_shell.rs b/tests/server_shell.rs
index 858f123..ae77a6a 100644
--- a/tests/server_shell.rs
+++ b/tests/server_shell.rs
@@ -1,7 +1,12 @@
-use anyhow::{bail, Result};
-use assert_cmd::{cargo::cargo_bin, Command};
+use anyhow::Result;
+use assert_cmd::cargo::cargo_bin;
use rexpect::session::{spawn_command, PtySession};
+use std::{io, path, sync::Once};
use tempfile::TempDir;
+use thiserror::Error;
+
+static BUILD_DOCKER: Once = Once::new();
+static mut BUILD_DOCKER_RESULT: Result<(), DockerBuildError> = Ok(());
struct TestContext {
workdir: TempDir,
@@ -9,27 +14,53 @@ struct TestContext {
docker_process: PtySession,
}
-fn build_docker_image() -> Result<()> {
- let mut command = std::process::Command::new("docker");
-
- let absolute_shell_path = cargo_bin(env!("CARGO_PKG_NAME"));
- let relative_shell_path = absolute_shell_path.strip_prefix(std::fs::canonicalize(".")?)?;
- command.args([
- "build",
- "--quiet",
- "-t",
- "shackle-server",
- "--build-arg",
- &format!("SHELL={}", relative_shell_path.display()),
- "./",
- ]);
+#[derive(Error, Debug, Clone)]
+pub enum DockerBuildError {
+ #[error(transparent)]
+ StripPrefixError(#[from] path::StripPrefixError),
+ #[error("IO Error: `{0}`")]
+ IoError(String),
+ #[error("Failed to build dockerfile")]
+ CliError,
+}
- let status = command.status()?;
- if !status.success() {
- bail!("Failed to build dockerfile");
+impl From<io::Error> for DockerBuildError {
+ fn from(e: io::Error) -> Self {
+ DockerBuildError::IoError(e.to_string())
}
+}
- Ok(())
+fn build_docker_image() -> Result<(), DockerBuildError> {
+ let build_docker = || {
+ let mut command = std::process::Command::new("docker");
+
+ let absolute_shell_path = cargo_bin(env!("CARGO_PKG_NAME"));
+ let relative_shell_path = absolute_shell_path.strip_prefix(std::fs::canonicalize(".")?)?;
+ command.args([
+ "build",
+ "--quiet",
+ "-t",
+ "shackle-server",
+ "--build-arg",
+ &format!("SHELL={}", relative_shell_path.display()),
+ "./",
+ ]);
+
+ let status = command.status()?;
+ if status.success() {
+ Ok(())
+ } else {
+ Err(DockerBuildError::CliError)
+ }
+ };
+
+ // Based on this example: https://doc.rust-lang.org/std/sync/struct.Once.html#examples-1
+ unsafe {
+ BUILD_DOCKER.call_once(|| {
+ BUILD_DOCKER_RESULT = build_docker();
+ });
+ BUILD_DOCKER_RESULT.clone()
+ }
}
fn spawn_ssh_server() -> Result<TestContext> {