From 15d9e1f3a9747cad46ca3a0928ac6e3ce7917780 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Wed, 9 Aug 2023 14:07:30 +0100 Subject: [PATCH] test: [#223] run E2E with MySQL too E2E tests are only executed with SQLite. --- .github/workflows/develop.yml | 4 +- compose.yaml | 2 +- config-idx-back.local.toml | 3 +- config-idx-back.mysql.local.toml | 46 ++++++++++++++++ docker/bin/e2e/mysql/e2e-env-down.sh | 3 ++ docker/bin/e2e/mysql/e2e-env-reset.sh | 33 ++++++++++++ docker/bin/e2e/mysql/e2e-env-restart.sh | 4 ++ docker/bin/e2e/mysql/e2e-env-up.sh | 12 +++++ docker/bin/e2e/mysql/run-e2e-tests.sh | 70 +++++++++++++++++++++++++ tests/e2e/config.rs | 11 ++-- tests/e2e/environment.rs | 30 +++++++++-- 11 files changed, 207 insertions(+), 11 deletions(-) create mode 100644 config-idx-back.mysql.local.toml create mode 100755 docker/bin/e2e/mysql/e2e-env-down.sh create mode 100755 docker/bin/e2e/mysql/e2e-env-reset.sh create mode 100755 docker/bin/e2e/mysql/e2e-env-restart.sh create mode 100755 docker/bin/e2e/mysql/e2e-env-up.sh create mode 100755 docker/bin/e2e/mysql/run-e2e-tests.sh diff --git a/.github/workflows/develop.yml b/.github/workflows/develop.yml index 2ee931b2..77a621ea 100644 --- a/.github/workflows/develop.yml +++ b/.github/workflows/develop.yml @@ -29,5 +29,7 @@ jobs: - uses: taiki-e/install-action@nextest - name: Test Coverage run: cargo llvm-cov nextest - - name: E2E Tests + - name: E2E Tests with SQLite run: ./docker/bin/run-e2e-tests.sh + - name: E2E Tests with MySQL + run: ./docker/bin/e2e/mysql/run-e2e-tests.sh diff --git a/compose.yaml b/compose.yaml index 2c46d9df..8bf4741e 100644 --- a/compose.yaml +++ b/compose.yaml @@ -87,7 +87,7 @@ services: environment: - MYSQL_ROOT_HOST=% - MYSQL_ROOT_PASSWORD=root_secret_password - - MYSQL_DATABASE=torrust_index_backend + - MYSQL_DATABASE=${TORRUST_IDX_BACK_MYSQL_DATABASE:-torrust_index_backend_e2e_testing} - MYSQL_USER=db_user - MYSQL_PASSWORD=db_user_secret_password networks: diff --git a/config-idx-back.local.toml b/config-idx-back.local.toml index 4b359800..f050b4fb 100644 --- a/config-idx-back.local.toml +++ b/config-idx-back.local.toml @@ -20,8 +20,7 @@ max_password_length = 64 secret_key = "MaxVerstappenWC2021" [database] -connect_url = "sqlite://storage/database/torrust_index_backend_e2e_testing.db?mode=rwc" # SQLite -#connect_url = "mysql://root:root_secret_password@mysql:3306/torrust_index_backend" # MySQL +connect_url = "sqlite://storage/database/torrust_index_backend_e2e_testing.db?mode=rwc" [mail] email_verification_enabled = false diff --git a/config-idx-back.mysql.local.toml b/config-idx-back.mysql.local.toml new file mode 100644 index 00000000..beeda6e8 --- /dev/null +++ b/config-idx-back.mysql.local.toml @@ -0,0 +1,46 @@ +log_level = "info" + +[website] +name = "Torrust" + +[tracker] +url = "udp://tracker:6969" +mode = "Public" +api_url = "http://tracker:1212" +token = "MyAccessToken" +token_valid_seconds = 7257600 + +[net] +port = 3001 + +[auth] +email_on_signup = "Optional" +min_password_length = 6 +max_password_length = 64 +secret_key = "MaxVerstappenWC2021" + +[database] +connect_url = "mysql://root:root_secret_password@mysql:3306/torrust_index_backend_e2e_testing" + +[mail] +email_verification_enabled = false +from = "example@email.com" +reply_to = "noreply@email.com" +username = "" +password = "" +server = "mailcatcher" +port = 1025 + +[image_cache] +max_request_timeout_ms = 1000 +capacity = 128000000 +entry_size_limit = 4000000 +user_quota_period_seconds = 3600 +user_quota_bytes = 64000000 + +[api] +default_torrent_page_size = 10 +max_torrent_page_size = 30 + +[tracker_statistics_importer] +torrent_info_update_interval = 3600 diff --git a/docker/bin/e2e/mysql/e2e-env-down.sh b/docker/bin/e2e/mysql/e2e-env-down.sh new file mode 100755 index 00000000..5e50d101 --- /dev/null +++ b/docker/bin/e2e/mysql/e2e-env-down.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +docker compose down diff --git a/docker/bin/e2e/mysql/e2e-env-reset.sh b/docker/bin/e2e/mysql/e2e-env-reset.sh new file mode 100755 index 00000000..46e690f3 --- /dev/null +++ b/docker/bin/e2e/mysql/e2e-env-reset.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +./docker/bin/e2e/mysql/e2e-env-down.sh + +# Delete the databases and recreate them. + +# Index Backend + +# Database credentials +MYSQL_USER="root" +MYSQL_PASSWORD="root_secret_password" +MYSQL_HOST="localhost" +MYSQL_DATABASE="torrust_index_backend_e2e_testing" + +# Create the MySQL database for the index backend. Assumes MySQL client is installed. +echo "Creating MySQL database $MYSQL_DATABASE for E2E testing ..." +mysql -h $MYSQL_HOST -u $MYSQL_USER -p$MYSQL_PASSWORD -e "DROP DATABASE IF EXISTS $MYSQL_DATABASE; CREATE DATABASE $MYSQL_DATABASE;" + +# Tracker + +# Delete tracker database +rm -f ./storage/database/torrust_tracker_e2e_testing.db + +# Generate storage directory if it does not exist +mkdir -p "./storage/database" + +# Generate the sqlite database for the tracker if it does not exist +if ! [ -f "./storage/database/torrust_tracker_e2e_testing.db" ]; then + touch ./storage/database/torrust_tracker_e2e_testing.db + echo ";" | sqlite3 ./storage/database/torrust_tracker_e2e_testing.db +fi + +./docker/bin/e2e/mysql/e2e-env-up.sh diff --git a/docker/bin/e2e/mysql/e2e-env-restart.sh b/docker/bin/e2e/mysql/e2e-env-restart.sh new file mode 100755 index 00000000..04f9f7ee --- /dev/null +++ b/docker/bin/e2e/mysql/e2e-env-restart.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +./docker/bin/e2e/mysql/e2e-env-down.sh +./docker/bin/e2e/mysql/e2e-env-up.sh diff --git a/docker/bin/e2e/mysql/e2e-env-up.sh b/docker/bin/e2e/mysql/e2e-env-up.sh new file mode 100755 index 00000000..195409b1 --- /dev/null +++ b/docker/bin/e2e/mysql/e2e-env-up.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +TORRUST_IDX_BACK_USER_UID=${TORRUST_IDX_BACK_USER_UID:-1000} \ + docker compose build + +TORRUST_IDX_BACK_USER_UID=${TORRUST_IDX_BACK_USER_UID:-1000} \ + TORRUST_IDX_BACK_CONFIG=$(cat config-idx-back.mysql.local.toml) \ + TORRUST_IDX_BACK_MYSQL_DATABASE="torrust_index_backend_e2e_testing" \ + TORRUST_TRACKER_CONFIG=$(cat config-tracker.local.toml) \ + TORRUST_TRACKER_API_TOKEN=${TORRUST_TRACKER_API_TOKEN:-MyAccessToken} \ + docker compose up -d + diff --git a/docker/bin/e2e/mysql/run-e2e-tests.sh b/docker/bin/e2e/mysql/run-e2e-tests.sh new file mode 100755 index 00000000..14eada4a --- /dev/null +++ b/docker/bin/e2e/mysql/run-e2e-tests.sh @@ -0,0 +1,70 @@ +#!/bin/bash + +CURRENT_USER_NAME=$(whoami) +CURRENT_USER_ID=$(id -u) +echo "User name: $CURRENT_USER_NAME" +echo "User id: $CURRENT_USER_ID" + +TORRUST_IDX_BACK_USER_UID=$CURRENT_USER_ID +TORRUST_TRACKER_USER_UID=$CURRENT_USER_ID +export TORRUST_IDX_BACK_USER_UID +export TORRUST_TRACKER_USER_UID + +wait_for_container_to_be_healthy() { + local container_name="$1" + local max_retries="$2" + local retry_interval="$3" + local retry_count=0 + + while [ $retry_count -lt "$max_retries" ]; do + container_health="$(docker inspect --format='{{json .State.Health}}' "$container_name")" + if [ "$container_health" != "{}" ]; then + container_status="$(echo "$container_health" | jq -r '.Status')" + if [ "$container_status" == "healthy" ]; then + echo "Container $container_name is healthy" + return 0 + fi + fi + + retry_count=$((retry_count + 1)) + echo "Waiting for container $container_name to become healthy (attempt $retry_count of $max_retries)..." + sleep "$retry_interval" + done + + echo "Timeout reached, container $container_name is not healthy" + return 1 +} + +# Install tool to create torrent files +cargo install imdl || exit 1 + +cp .env.local .env || exit 1 +./bin/install.sh || exit 1 + +# Start E2E testing environment +./docker/bin/e2e/mysql/e2e-env-up.sh || exit 1 + +wait_for_container_to_be_healthy torrust-mysql-1 10 3 +# todo: implement healthchecks for tracker and backend and wait until they are healthy +#wait_for_container torrust-tracker-1 10 3 +#wait_for_container torrust-idx-back-1 10 3 +sleep 20s + +# Just to make sure that everything is up and running +docker ps + +# Database credentials +MYSQL_USER="root" +MYSQL_PASSWORD="root_secret_password" +MYSQL_HOST="localhost" +MYSQL_DATABASE="torrust_index_backend_e2e_testing" + +# Create the MySQL database for the index backend. Assumes MySQL client is installed. +echo "Creating MySQL database $MYSQL_DATABASE for for E2E testing ..." +mysql -h $MYSQL_HOST -u $MYSQL_USER -p$MYSQL_PASSWORD -e "CREATE DATABASE IF NOT EXISTS $MYSQL_DATABASE;" + +# Run E2E tests with shared app instance +TORRUST_IDX_BACK_E2E_SHARED=true TORRUST_IDX_BACK_E2E_CONFIG_PATH="./config-idx-back.mysql.local.toml" cargo test || exit 1 + +# Stop E2E testing environment +./docker/bin/e2e/mysql/e2e-env-down.sh diff --git a/tests/e2e/config.rs b/tests/e2e/config.rs index f3179f43..60595c79 100644 --- a/tests/e2e/config.rs +++ b/tests/e2e/config.rs @@ -1,7 +1,7 @@ //! Initialize configuration for the shared E2E tests environment from a //! config file `config.toml` or env var. //! -//! All environment variables are prefixed with `TORRUST_IDX_BACK_`. +//! All environment variables are prefixed with `TORRUST_IDX_BACK_E2E`. use std::env; use torrust_index_backend::config::Configuration; @@ -14,6 +14,9 @@ pub const ENV_VAR_E2E_SHARED: &str = "TORRUST_IDX_BACK_E2E_SHARED"; /// The whole `config.toml` file content. It has priority over the config file. pub const ENV_VAR_E2E_CONFIG: &str = "TORRUST_IDX_BACK_E2E_CONFIG"; +/// The `config.toml` file location. +pub const ENV_VAR_E2E_CONFIG_PATH: &str = "TORRUST_IDX_BACK_E2E_CONFIG_PATH"; + // Default values pub const ENV_VAR_E2E_DEFAULT_CONFIG_PATH: &str = "./config-idx-back.local.toml"; @@ -29,9 +32,11 @@ pub async fn init_shared_env_configuration() -> Configuration { Configuration::load_from_env_var(ENV_VAR_E2E_CONFIG).unwrap() } else { - println!("Loading configuration for E2E env from config file `{ENV_VAR_E2E_DEFAULT_CONFIG_PATH}`"); + let config_path = env::var(ENV_VAR_E2E_CONFIG_PATH).unwrap_or_else(|_| ENV_VAR_E2E_DEFAULT_CONFIG_PATH.to_string()); + + println!("Loading configuration from config file `{config_path}`"); - match Configuration::load_from_file(ENV_VAR_E2E_DEFAULT_CONFIG_PATH).await { + match Configuration::load_from_file(&config_path).await { Ok(config) => config, Err(error) => { panic!("{}", error) diff --git a/tests/e2e/environment.rs b/tests/e2e/environment.rs index d5022785..89d8d226 100644 --- a/tests/e2e/environment.rs +++ b/tests/e2e/environment.rs @@ -95,12 +95,34 @@ impl TestEnv { } } - /// Provides the database connect URL. - /// For example: `sqlite://storage/database/torrust_index_backend_e2e_testing.db?mode=rwc`. + /// Provides a database connect URL to connect to the database. For example: + /// + /// `sqlite://storage/database/torrust_index_backend_e2e_testing.db?mode=rwc`. + /// + /// It's used to run SQL queries against the database needed for some tests. pub fn database_connect_url(&self) -> Option { - self.starting_settings + let internal_connect_url = self + .starting_settings .as_ref() - .map(|settings| settings.database.connect_url.clone()) + .map(|settings| settings.database.connect_url.clone()); + + match self.state() { + State::RunningShared => { + if let Some(internal_connect_url) = internal_connect_url { + if internal_connect_url.starts_with("sqlite") { + return Some("sqlite://storage/database/torrust_index_backend_e2e_testing.db?mode=rwc".to_string()); + } + if internal_connect_url.starts_with("mysql") { + return Some( + "mysql://root:root_secret_password@localhost:3306/torrust_index_backend_e2e_testing".to_string(), + ); + } + } + None + } + State::RunningIsolated => internal_connect_url, + State::Stopped => None, + } } fn state(&self) -> State {