Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

E2E tests: Improve E2E tests runner #648

Merged
merged 6 commits into from
Jan 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/bin/tracker_checker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ use torrust_tracker::checker::app;

#[tokio::main]
async fn main() {
app::run().await;
app::run().await.expect("Some checks fail");
}
10 changes: 7 additions & 3 deletions src/checker/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,22 @@

use super::config::Configuration;
use super::console::Console;
use super::service::{CheckError, Service};
use crate::checker::config::parse_from_json;
use crate::checker::service::Service;

pub const NUMBER_OF_ARGUMENTS: usize = 2;

/// # Errors
///
/// If some checks fails it will return a vector with all failing checks.
///
/// # Panics
///
/// Will panic if:
///
/// - It can't read the json configuration file.
/// - The configuration file is invalid.
pub async fn run() {
pub async fn run() -> Result<(), Vec<CheckError>> {

Check warning on line 20 in src/checker/app.rs

View check run for this annotation

Codecov / codecov/patch

src/checker/app.rs#L20

Added line #L20 was not covered by tests
let args = parse_arguments();
let config = setup_config(&args);
let console_printer = Console {};
Expand All @@ -22,7 +26,7 @@
console: console_printer,
};

service.run_checks().await;
service.run_checks().await
}

pub struct Arguments {
Expand Down
36 changes: 31 additions & 5 deletions src/checker/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,24 @@
pub(crate) console: Console,
}

#[derive(Debug)]

Check warning on line 17 in src/checker/service.rs

View check run for this annotation

Codecov / codecov/patch

src/checker/service.rs#L17

Added line #L17 was not covered by tests
pub enum CheckError {
UdpError,
HttpError,
HealthCheckError { url: Url },

Check warning on line 21 in src/checker/service.rs

View check run for this annotation

Codecov / codecov/patch

src/checker/service.rs#L21

Added line #L21 was not covered by tests
}

impl Service {
pub async fn run_checks(&self) {
/// # Errors
///
/// Will return OK is all checks pass or an array with the check errors.
pub async fn run_checks(&self) -> Result<(), Vec<CheckError>> {

Check warning on line 28 in src/checker/service.rs

View check run for this annotation

Codecov / codecov/patch

src/checker/service.rs#L28

Added line #L28 was not covered by tests
self.console.println("Running checks for trackers ...");

self.check_udp_trackers();
self.check_http_trackers();
self.run_health_checks().await;

self.run_health_checks().await
}

fn check_udp_trackers(&self) {
Expand All @@ -38,11 +50,22 @@
}
}

async fn run_health_checks(&self) {
async fn run_health_checks(&self) -> Result<(), Vec<CheckError>> {

Check warning on line 53 in src/checker/service.rs

View check run for this annotation

Codecov / codecov/patch

src/checker/service.rs#L53

Added line #L53 was not covered by tests
self.console.println("Health checks ...");

let mut check_errors = vec![];

for health_check_url in &self.config.health_checks {
self.run_health_check(health_check_url.clone()).await;
match self.run_health_check(health_check_url.clone()).await {
Ok(()) => {}
Err(err) => check_errors.push(err),
}
}

if check_errors.is_empty() {
Ok(())
} else {
Err(check_errors)
}
}

Expand All @@ -62,22 +85,25 @@
.println(&format!("{} - HTTP tracker at {} is OK (TODO)", "✓".green(), url));
}

async fn run_health_check(&self, url: Url) {
async fn run_health_check(&self, url: Url) -> Result<(), CheckError> {

Check warning on line 88 in src/checker/service.rs

View check run for this annotation

Codecov / codecov/patch

src/checker/service.rs#L88

Added line #L88 was not covered by tests
let client = Client::builder().timeout(Duration::from_secs(5)).build().unwrap();

match client.get(url.clone()).send().await {
Ok(response) => {
if response.status().is_success() {
self.console
.println(&format!("{} - Health API at {} is OK", "✓".green(), url));
Ok(())
} else {
self.console
.eprintln(&format!("{} - Health API at {} failing: {:?}", "✗".red(), url, response));
Err(CheckError::HealthCheckError { url })
}
}
Err(err) => {
self.console
.eprintln(&format!("{} - Health API at {} failing: {:?}", "✗".red(), url, err));
Err(CheckError::HealthCheckError { url })
}
}
}
Expand Down
73 changes: 65 additions & 8 deletions src/e2e/docker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,35 @@
use std::thread::sleep;
use std::time::{Duration, Instant};

use log::debug;
use log::{debug, info};

/// Docker command wrapper.
pub struct Docker {}

#[derive(Clone, Debug)]

Check warning on line 12 in src/e2e/docker.rs

View check run for this annotation

Codecov / codecov/patch

src/e2e/docker.rs#L12

Added line #L12 was not covered by tests
pub struct RunningContainer {
pub image: String,

Check warning on line 14 in src/e2e/docker.rs

View check run for this annotation

Codecov / codecov/patch

src/e2e/docker.rs#L14

Added line #L14 was not covered by tests
pub name: String,
pub output: Output,
}

impl Drop for RunningContainer {
/// Ensures that the temporary container is stopped and removed when the
/// struct goes out of scope.
/// Ensures that the temporary container is stopped when the struct goes out
/// of scope.
fn drop(&mut self) {
let _unused = Docker::stop(self);
let _unused = Docker::remove(&self.name);
info!("Dropping running container: {}", self.name);
if Docker::is_container_running(&self.name) {
let _unused = Docker::stop(self);
}

Check warning on line 26 in src/e2e/docker.rs

View check run for this annotation

Codecov / codecov/patch

src/e2e/docker.rs#L23-L26

Added lines #L23 - L26 were not covered by tests
}
}

/// `docker run` command options.
pub struct RunOptions {
pub env_vars: Vec<(String, String)>,
pub ports: Vec<String>,
}

impl Docker {
/// Builds a Docker image from a given Dockerfile.
///
Expand Down Expand Up @@ -55,7 +65,7 @@
/// # Errors
///
/// Will fail if the docker run command fails.
pub fn run(image: &str, container: &str, env_vars: &[(String, String)], ports: &[String]) -> io::Result<RunningContainer> {
pub fn run(image: &str, container: &str, options: &RunOptions) -> io::Result<RunningContainer> {

Check warning on line 68 in src/e2e/docker.rs

View check run for this annotation

Codecov / codecov/patch

src/e2e/docker.rs#L68

Added line #L68 was not covered by tests
let initial_args = vec![
"run".to_string(),
"--detach".to_string(),
Expand All @@ -65,14 +75,14 @@

// Add environment variables
let mut env_var_args: Vec<String> = vec![];
for (key, value) in env_vars {
for (key, value) in &options.env_vars {

Check warning on line 78 in src/e2e/docker.rs

View check run for this annotation

Codecov / codecov/patch

src/e2e/docker.rs#L78

Added line #L78 was not covered by tests
env_var_args.push("--env".to_string());
env_var_args.push(format!("{key}={value}"));
}

// Add port mappings
let mut port_args: Vec<String> = vec![];
for port in ports {
for port in &options.ports {

Check warning on line 85 in src/e2e/docker.rs

View check run for this annotation

Codecov / codecov/patch

src/e2e/docker.rs#L85

Added line #L85 was not covered by tests
port_args.push("--publish".to_string());
port_args.push(port.to_string());
}
Expand All @@ -85,6 +95,7 @@

if output.status.success() {
Ok(RunningContainer {
image: image.to_owned(),

Check warning on line 98 in src/e2e/docker.rs

View check run for this annotation

Codecov / codecov/patch

src/e2e/docker.rs#L98

Added line #L98 was not covered by tests
name: container.to_owned(),
output,
})
Expand Down Expand Up @@ -174,4 +185,50 @@

false
}

/// Checks if a Docker container is running.
///
/// # Arguments
///
/// * `container` - The name of the Docker container.
///
/// # Returns
///
/// `true` if the container is running, `false` otherwise.
#[must_use]
pub fn is_container_running(container: &str) -> bool {
match Command::new("docker")
.args(["ps", "-f", &format!("name={container}"), "--format", "{{.Names}}"])

Check warning on line 201 in src/e2e/docker.rs

View check run for this annotation

Codecov / codecov/patch

src/e2e/docker.rs#L199-L201

Added lines #L199 - L201 were not covered by tests
.output()
{
Ok(output) => {
let output_str = String::from_utf8_lossy(&output.stdout);
output_str.contains(container)
}
Err(_) => false,

Check warning on line 208 in src/e2e/docker.rs

View check run for this annotation

Codecov / codecov/patch

src/e2e/docker.rs#L204-L208

Added lines #L204 - L208 were not covered by tests
}
}

Check warning on line 210 in src/e2e/docker.rs

View check run for this annotation

Codecov / codecov/patch

src/e2e/docker.rs#L210

Added line #L210 was not covered by tests

/// Checks if a Docker container exists.
///
/// # Arguments
///
/// * `container` - The name of the Docker container.
///
/// # Returns
///
/// `true` if the container exists, `false` otherwise.
#[must_use]
pub fn container_exist(container: &str) -> bool {
match Command::new("docker")
.args(["ps", "-a", "-f", &format!("name={container}"), "--format", "{{.Names}}"])

Check warning on line 224 in src/e2e/docker.rs

View check run for this annotation

Codecov / codecov/patch

src/e2e/docker.rs#L222-L224

Added lines #L222 - L224 were not covered by tests
.output()
{
Ok(output) => {
let output_str = String::from_utf8_lossy(&output.stdout);
output_str.contains(container)
}
Err(_) => false,

Check warning on line 231 in src/e2e/docker.rs

View check run for this annotation

Codecov / codecov/patch

src/e2e/docker.rs#L227-L231

Added lines #L227 - L231 were not covered by tests
}
}

Check warning on line 233 in src/e2e/docker.rs

View check run for this annotation

Codecov / codecov/patch

src/e2e/docker.rs#L233

Added line #L233 was not covered by tests
}
1 change: 1 addition & 0 deletions src/e2e/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ pub mod docker;
pub mod logs_parser;
pub mod runner;
pub mod temp_dir;
pub mod tracker_container;
Loading
Loading