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

Run E2E tests also using MySQL #252

Merged
merged 3 commits into from
Aug 9, 2023
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
3 changes: 2 additions & 1 deletion .github/workflows/develop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@ jobs:
- name: Test Coverage
run: cargo llvm-cov nextest
- name: E2E Tests
run: ./docker/bin/run-e2e-tests.sh
run: ./docker/bin/e2e/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
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 = "[email protected]"
reply_to = "[email protected]"
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
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
3 changes: 0 additions & 3 deletions docker/bin/e2e-env-down.sh

This file was deleted.

4 changes: 0 additions & 4 deletions docker/bin/e2e-env-restart.sh

This file was deleted.

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

# Delete the databases and recreate them.

docker compose down

# 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 compose down
./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

45 changes: 41 additions & 4 deletions docker/bin/run-e2e-tests.sh → docker/bin/e2e/run-e2e-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,20 @@ wait_for_container_to_be_healthy() {
return 1
}

# Install tool to create torrent files
# Install tool to create torrent files.
# It's needed by some tests to generate and parse test torrent files.
cargo install imdl || exit 1

# Install app (no docker) that will run the test suite against the E2E testing
# environment (in docker).
cp .env.local .env || exit 1
./bin/install.sh || exit 1

# TEST USING SQLITE
echo "Running E2E tests using SQLite ..."

# Start E2E testing environment
./docker/bin/e2e-env-up.sh || exit 1
./docker/bin/e2e/sqlite/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
Expand All @@ -54,7 +60,38 @@ sleep 20s
docker ps

# Run E2E tests with shared app instance
TORRUST_IDX_BACK_E2E_SHARED=true cargo test || exit 1
TORRUST_IDX_BACK_E2E_SHARED=true TORRUST_IDX_BACK_E2E_CONFIG_PATH="./config-idx-back.sqlite.local.toml" cargo test || exit 1

# Stop E2E testing environment
docker compose down

# TEST USING MYSQL
echo "Running E2E tests using MySQL ..."

# 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-env-down.sh
docker compose down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#!/bin/bash

# Delete the SQLite databases and recreate them.
# Delete the databases and recreate them.

./docker/bin/e2e-env-down.sh
docker compose down

rm -f ./storage/database/torrust_index_backend_e2e_testing.db
rm -f ./storage/database/torrust_tracker_e2e_testing.db
Expand All @@ -23,4 +23,4 @@ if ! [ -f "./storage/database/torrust_tracker_e2e_testing.db" ]; then
echo ";" | sqlite3 ./storage/database/torrust_tracker_e2e_testing.db
fi

./docker/bin/e2e-env-up.sh
./docker/bin/e2e/sqlite/e2e-env-up.sh
4 changes: 4 additions & 0 deletions docker/bin/e2e/sqlite/e2e-env-restart.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash

docker compose down
./docker/bin/e2e/sqlite/e2e-env-up.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ 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.local.toml) \
TORRUST_IDX_BACK_CONFIG=$(cat config-idx-back.sqlite.local.toml) \
TORRUST_TRACKER_CONFIG=$(cat config-tracker.local.toml) \
TORRUST_TRACKER_API_TOKEN=${TORRUST_TRACKER_API_TOKEN:-MyAccessToken} \
docker compose up -d
4 changes: 3 additions & 1 deletion src/databases/mysql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,9 @@ impl Database for Mysql {
.map(|v| i64::try_from(v.last_insert_id()).expect("last ID is larger than i64"))
.map_err(|e| match e {
sqlx::Error::Database(err) => {
if err.message().contains("UNIQUE") {
if err.message().contains("Duplicate entry") {
// Example error message when you try to insert a duplicate category:
// Error: Duplicate entry 'category name SAMPLE_NAME' for key 'torrust_categories.name'
database::Error::CategoryAlreadyExists
} else {
database::Error::Error
Expand Down
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