Skip to content

Commit

Permalink
test: [torrust#223] run E2E with MySQL too
Browse files Browse the repository at this point in the history
E2E tests are only executed with SQLite.
  • Loading branch information
josecelano committed Aug 9, 2023
1 parent 5465e0c commit c6346a5
Show file tree
Hide file tree
Showing 11 changed files with 227 additions and 11 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/develop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 1 addition & 1 deletion compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
3 changes: 1 addition & 2 deletions config-idx-back.local.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
46 changes: 46 additions & 0 deletions config-idx-back.mysql.local.toml
Original file line number Diff line number Diff line change
@@ -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
3 changes: 3 additions & 0 deletions docker/bin/e2e/mysql/e2e-env-down.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/bash

docker compose down
33 changes: 33 additions & 0 deletions docker/bin/e2e/mysql/e2e-env-reset.sh
Original file line number Diff line number Diff line change
@@ -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
4 changes: 4 additions & 0 deletions docker/bin/e2e/mysql/e2e-env-restart.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash

./docker/bin/e2e/mysql/e2e-env-down.sh
./docker/bin/e2e/mysql/e2e-env-up.sh
12 changes: 12 additions & 0 deletions docker/bin/e2e/mysql/e2e-env-up.sh
Original file line number Diff line number Diff line change
@@ -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

70 changes: 70 additions & 0 deletions docker/bin/e2e/mysql/run-e2e-tests.sh
Original file line number Diff line number Diff line change
@@ -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
11 changes: 8 additions & 3 deletions tests/e2e/config.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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";
Expand All @@ -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)
Expand Down
50 changes: 46 additions & 4 deletions tests/e2e/environment.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::env;

use torrust_index_backend::databases::database;
use torrust_index_backend::web::api::Version;

use super::config::{init_shared_env_configuration, ENV_VAR_E2E_SHARED};
Expand Down Expand Up @@ -95,12 +96,53 @@ 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<String> {
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(db_path) = internal_connect_url {
let maybe_db_driver = database::get_driver(&db_path);

return match maybe_db_driver {
Ok(db_driver) => match db_driver {
database::Driver::Sqlite3 => Some(db_path),
database::Driver::Mysql => Some(Self::overwrite_mysql_host(&db_path, "localhost")),
},
Err(_) => None,
};
}
None
}
State::RunningIsolated => internal_connect_url,
State::Stopped => None,
}
}

/// It overrides the "Host" in a `SQLx` database connection URL. For example:
///
/// For:
///
/// `mysql://root:root_secret_password@mysql:3306/torrust_index_backend_e2e_testing`.
///
/// It changes the `mysql` host name to `localhost`:
///
/// `mysql://root:root_secret_password@localhost:3306/torrust_index_backend_e2e_testing`.
///
/// For E2E tests, we use docker compose, internally the backend connects to
/// the database using the "mysql" host, which is the docker compose service
/// name, but tests connects directly to the localhost since the `MySQL`
/// is exposed to the host.
fn overwrite_mysql_host(db_path: &str, new_host: &str) -> String {
db_path.replace("@mysql:", &format!("@{new_host}:"))
}

fn state(&self) -> State {
Expand Down

0 comments on commit c6346a5

Please sign in to comment.