diff --git a/.gitignore b/.gitignore index e7735b0e63..42f63e5115 100755 --- a/.gitignore +++ b/.gitignore @@ -73,4 +73,10 @@ MM2.json [._]sw[a-p] # mergetool -*.orig \ No newline at end of file +*.orig + +# Ignore containers runtime directories for dockerized tests +# This directory contains temporary data used by Docker containers during tests execution. +# It is recreated from container-state data each time test containers are started, +# and should not be tracked in version control. +.docker/container-runtime/ \ No newline at end of file diff --git a/mm2src/mm2_io/src/fs.rs b/mm2src/mm2_io/src/fs.rs index e844086d89..94a323c0b8 100644 --- a/mm2src/mm2_io/src/fs.rs +++ b/mm2src/mm2_io/src/fs.rs @@ -9,7 +9,7 @@ use serde::de::DeserializeOwned; use serde::Serialize; use serde_json::{self as json, Error as JsonError}; use std::ffi::OsStr; -use std::fs::{self, DirEntry}; +use std::fs::{self, create_dir_all, DirEntry}; use std::io::{self, Read, Write}; use std::path::{Path, PathBuf}; use std::time::UNIX_EPOCH; @@ -279,3 +279,18 @@ pub fn json_dir_entries(path: &dyn AsRef) -> Result, String> }) .collect()) } + +/// Helper function to copy directories recursively +pub fn copy_dir_all(src: &dyn AsRef, dst: &dyn AsRef) -> io::Result<()> { + create_dir_all(dst)?; + for entry in fs::read_dir(src)? { + let entry = entry?; + let ty = entry.file_type()?; + if ty.is_dir() { + copy_dir_all(&entry.path(), &dst.as_ref().join(entry.file_name()))?; + } else { + std::fs::copy(entry.path(), dst.as_ref().join(entry.file_name()))?; + } + } + Ok(()) +} diff --git a/mm2src/mm2_main/tests/docker_tests/docker_tests_common.rs b/mm2src/mm2_main/tests/docker_tests/docker_tests_common.rs index 530149eb37..2fe6450810 100644 --- a/mm2src/mm2_main/tests/docker_tests/docker_tests_common.rs +++ b/mm2src/mm2_main/tests/docker_tests/docker_tests_common.rs @@ -352,17 +352,12 @@ pub fn geth_docker_node<'a>(docker: &'a Cli, ticker: &'static str, port: u16) -> } } -pub fn nucleus_node(docker: &'_ Cli) -> DockerNode<'_> { - let nucleus_node_state_dir = { - let mut current_dir = std::env::current_dir().unwrap(); - current_dir.pop(); - current_dir.pop(); - current_dir.join(".docker/container-state/nucleus-testnet-data") - }; - assert!(nucleus_node_state_dir.exists()); +pub fn nucleus_node(docker: &'_ Cli, runtime_dir: PathBuf) -> DockerNode<'_> { + let nucleus_node_runtime_dir = runtime_dir.join("nucleus-testnet-data"); + assert!(nucleus_node_runtime_dir.exists()); let image = GenericImage::new(NUCLEUS_IMAGE, "latest") - .with_volume(nucleus_node_state_dir.to_str().unwrap(), "/root/.nucleus"); + .with_volume(nucleus_node_runtime_dir.to_str().unwrap(), "/root/.nucleus"); let image = RunnableImage::from((image, vec![])).with_network("host"); let container = docker.run(image); @@ -373,17 +368,12 @@ pub fn nucleus_node(docker: &'_ Cli) -> DockerNode<'_> { } } -pub fn atom_node(docker: &'_ Cli) -> DockerNode<'_> { - let atom_node_state_dir = { - let mut current_dir = std::env::current_dir().unwrap(); - current_dir.pop(); - current_dir.pop(); - current_dir.join(".docker/container-state/atom-testnet-data") - }; - assert!(atom_node_state_dir.exists()); +pub fn atom_node(docker: &'_ Cli, runtime_dir: PathBuf) -> DockerNode<'_> { + let atom_node_runtime_dir = runtime_dir.join("atom-testnet-data"); + assert!(atom_node_runtime_dir.exists()); let image = - GenericImage::new(ATOM_IMAGE, "latest").with_volume(atom_node_state_dir.to_str().unwrap(), "/root/.gaia"); + GenericImage::new(ATOM_IMAGE, "latest").with_volume(atom_node_runtime_dir.to_str().unwrap(), "/root/.gaia"); let image = RunnableImage::from((image, vec![])).with_network("host"); let container = docker.run(image); @@ -394,17 +384,12 @@ pub fn atom_node(docker: &'_ Cli) -> DockerNode<'_> { } } -pub fn ibc_relayer_node(docker: &'_ Cli) -> DockerNode<'_> { - let relayer_node_state_dir = { - let mut current_dir = std::env::current_dir().unwrap(); - current_dir.pop(); - current_dir.pop(); - current_dir.join(".docker/container-state/ibc-relayer-data") - }; - assert!(relayer_node_state_dir.exists()); +pub fn ibc_relayer_node(docker: &'_ Cli, runtime_dir: PathBuf) -> DockerNode<'_> { + let relayer_node_runtime_dir = runtime_dir.join("ibc-relayer-data"); + assert!(relayer_node_runtime_dir.exists()); let image = GenericImage::new(IBC_RELAYER_IMAGE, "latest") - .with_volume(relayer_node_state_dir.to_str().unwrap(), "/home/relayer/.relayer"); + .with_volume(relayer_node_runtime_dir.to_str().unwrap(), "/home/relayer/.relayer"); let image = RunnableImage::from((image, vec![])).with_network("host"); let container = docker.run(image); diff --git a/mm2src/mm2_main/tests/docker_tests_main.rs b/mm2src/mm2_main/tests/docker_tests_main.rs index da049d6fd3..8ad39bf7cd 100644 --- a/mm2src/mm2_main/tests/docker_tests_main.rs +++ b/mm2src/mm2_main/tests/docker_tests_main.rs @@ -24,6 +24,7 @@ extern crate serde_json; use std::env; use std::io::{BufRead, BufReader}; +use std::path::PathBuf; use std::process::Command; use test::{test_main, StaticBenchFn, StaticTestFn, TestDescAndFn}; use testcontainers::clients::Cli; @@ -62,9 +63,11 @@ pub fn docker_tests_runner(tests: &[&TestDescAndFn]) { remove_docker_containers(image); } - let nucleus_node = nucleus_node(&docker); - let atom_node = atom_node(&docker); - let ibc_relayer_node = ibc_relayer_node(&docker); + let runtime_dir = prepare_runtime_dir().unwrap(); + + let nucleus_node = nucleus_node(&docker, runtime_dir.clone()); + let atom_node = atom_node(&docker, runtime_dir.clone()); + let ibc_relayer_node = ibc_relayer_node(&docker, runtime_dir); let utxo_node = utxo_asset_docker_node(&docker, "MYCOIN", 7000); let utxo_node1 = utxo_asset_docker_node(&docker, "MYCOIN1", 8000); let qtum_node = qtum_docker_node(&docker, 9000); @@ -143,3 +146,25 @@ fn remove_docker_containers(name: &str) { .expect("Failed to execute docker command"); } } +fn prepare_runtime_dir() -> std::io::Result { + let project_root = { + let mut current_dir = std::env::current_dir().unwrap(); + current_dir.pop(); + current_dir.pop(); + current_dir + }; + + let containers_state_dir = project_root.join(".docker/container-state"); + assert!(containers_state_dir.exists()); + let containers_runtime_dir = project_root.join(".docker/container-runtime"); + + // Remove runtime directory if it exists to copy containers files to a clean directory + if containers_runtime_dir.exists() { + std::fs::remove_dir_all(&containers_runtime_dir).unwrap(); + } + + // Copy container files to runtime directory + mm2_io::fs::copy_dir_all(&containers_state_dir, &containers_runtime_dir).unwrap(); + + Ok(containers_runtime_dir) +}