Skip to content

Commit

Permalink
refactor: [torrust#130] configuration for E2E tests
Browse files Browse the repository at this point in the history
Clean code for E2E test env configuration initialization.

And the configuration is loaded from the same config file used to start the
docker container: `config-idx-back.local.toml`.
  • Loading branch information
josecelano committed May 4, 2023
1 parent 87edb36 commit b97da41
Show file tree
Hide file tree
Showing 16 changed files with 288 additions and 189 deletions.
8 changes: 4 additions & 4 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@
/.github
/.gitignore
/.vscode
/data_v2.db*
/data.db*
/bin/
/config-idx-back.toml.local
/config-tracker.toml.local
/config-idx-back.local.toml
/config-tracker.local.toml
/config.toml
/config.toml.local
/cspell.json
/data_v2.db*
/data.db
/data.db*
/docker/
/project-words.txt
/README.md
Expand Down
File renamed without changes.
File renamed without changes.
6 changes: 3 additions & 3 deletions docker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ docker run -it \
### With docker-compose

The docker-compose configuration includes the MySQL service configuration. If you want to use MySQL instead of SQLite you have to change your `config.toml` or `config-idx-back.toml.local` configuration from:
The docker-compose configuration includes the MySQL service configuration. If you want to use MySQL instead of SQLite you have to change your `config.toml` or `config-idx-back.local.toml` configuration from:

```toml
connect_url = "sqlite://storage/database/data.db?mode=rwc"
Expand All @@ -64,8 +64,8 @@ Build and run it locally:

```s
TORRUST_IDX_BACK_USER_UID=${TORRUST_IDX_BACK_USER_UID:-1000} \
TORRUST_IDX_BACK_CONFIG=$(cat config-idx-back.toml.local) \
TORRUST_TRACKER_CONFIG=$(cat config-tracker.toml.local) \
TORRUST_IDX_BACK_CONFIG=$(cat config-idx-back.local.toml) \
TORRUST_TRACKER_CONFIG=$(cat config-tracker.local.toml) \
TORRUST_TRACKER_API_TOKEN=${TORRUST_TRACKER_API_TOKEN:-MyAccessToken} \
docker compose up -d --build
```
Expand Down
4 changes: 2 additions & 2 deletions docker/bin/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.toml.local) \
TORRUST_TRACKER_CONFIG=$(cat config-tracker.toml.local) \
TORRUST_IDX_BACK_CONFIG=$(cat config-idx-back.local.toml) \
TORRUST_TRACKER_CONFIG=$(cat config-tracker.local.toml) \
TORRUST_TRACKER_API_TOKEN=${TORRUST_TRACKER_API_TOKEN:-MyAccessToken} \
docker compose up -d
23 changes: 16 additions & 7 deletions src/bootstrap/config.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
//! Initialize configuration from file or env var.
//!
//! All environment variables are prefixed with `TORRUST_IDX_BACK_`.
use std::env;

pub const CONFIG_PATH: &str = "./config.toml";
pub const CONFIG_ENV_VAR_NAME: &str = "TORRUST_IDX_BACK_CONFIG";
// Environment variables

/// The whole `config.toml` file content. It has priority over the config file.
pub const ENV_VAR_CONFIG: &str = "TORRUST_IDX_BACK_CONFIG";

// Default values

pub const ENV_VAR_DEFAULT_CONFIG_PATH: &str = "./config.toml";

use crate::config::Configuration;

Expand All @@ -11,14 +20,14 @@ use crate::config::Configuration;
///
/// Will panic if configuration is not found or cannot be parsed
pub async fn init_configuration() -> Configuration {
if env::var(CONFIG_ENV_VAR_NAME).is_ok() {
println!("Loading configuration from env var `{}`", CONFIG_ENV_VAR_NAME);
if env::var(ENV_VAR_CONFIG).is_ok() {
println!("Loading configuration from env var `{}`", ENV_VAR_CONFIG);

Configuration::load_from_env_var(CONFIG_ENV_VAR_NAME).unwrap()
Configuration::load_from_env_var(ENV_VAR_CONFIG).unwrap()
} else {
println!("Loading configuration from config file `{}`", CONFIG_PATH);
println!("Loading configuration from config file `{}`", ENV_VAR_DEFAULT_CONFIG_PATH);

match Configuration::load_from_file(CONFIG_PATH).await {
match Configuration::load_from_file(ENV_VAR_DEFAULT_CONFIG_PATH).await {
Ok(config) => config,
Err(error) => {
panic!("{}", error)
Expand Down
7 changes: 5 additions & 2 deletions src/routes/settings.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use actix_web::{web, HttpRequest, HttpResponse, Responder};

use crate::bootstrap::config::CONFIG_PATH;
use crate::bootstrap::config::ENV_VAR_DEFAULT_CONFIG_PATH;
use crate::common::WebAppData;
use crate::config::TorrustConfig;
use crate::errors::{ServiceError, ServiceResult};
Expand Down Expand Up @@ -60,7 +60,10 @@ pub async fn update_settings(
return Err(ServiceError::Unauthorized);
}

let _ = app_data.cfg.update_settings(payload.into_inner(), CONFIG_PATH).await;
let _ = app_data
.cfg
.update_settings(payload.into_inner(), ENV_VAR_DEFAULT_CONFIG_PATH)
.await;

let settings = app_data.cfg.settings.read().await;

Expand Down
125 changes: 108 additions & 17 deletions tests/common/contexts/settings/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,28 @@ pub mod form;
pub mod responses;

use serde::{Deserialize, Serialize};
use torrust_index_backend::config::{
Auth as DomainAuth, Database as DomainDatabase, ImageCache as DomainImageCache, Mail as DomainMail, Network as DomainNetwork,
TorrustConfig as DomainSettings, Tracker as DomainTracker, Website as DomainWebsite,
};

#[derive(Deserialize, Serialize, PartialEq, Debug)]
#[derive(Deserialize, Serialize, PartialEq, Debug, Clone)]
pub struct Settings {
pub website: Website,
pub tracker: Tracker,
pub net: Net,
pub net: Network,
pub auth: Auth,
pub database: Database,
pub mail: Mail,
pub image_cache: ImageCache,
}

#[derive(Deserialize, Serialize, PartialEq, Debug)]
#[derive(Deserialize, Serialize, PartialEq, Debug, Clone)]
pub struct Website {
pub name: String,
}

#[derive(Deserialize, Serialize, PartialEq, Debug)]
#[derive(Deserialize, Serialize, PartialEq, Debug, Clone)]
pub struct Tracker {
pub url: String,
pub mode: String,
Expand All @@ -28,42 +32,129 @@ pub struct Tracker {
pub token_valid_seconds: u64,
}

#[derive(Deserialize, Serialize, PartialEq, Debug)]
pub struct Net {
pub port: u64,
#[derive(Deserialize, Serialize, PartialEq, Debug, Clone)]
pub struct Network {
pub port: u16,
pub base_url: Option<String>,
}

#[derive(Deserialize, Serialize, PartialEq, Debug)]
#[derive(Deserialize, Serialize, PartialEq, Debug, Clone)]
pub struct Auth {
pub email_on_signup: String,
pub min_password_length: u64,
pub max_password_length: u64,
pub min_password_length: usize,
pub max_password_length: usize,
pub secret_key: String,
}

#[derive(Deserialize, Serialize, PartialEq, Debug)]
#[derive(Deserialize, Serialize, PartialEq, Debug, Clone)]
pub struct Database {
pub connect_url: String,
pub torrent_info_update_interval: u64,
}

#[derive(Deserialize, Serialize, PartialEq, Debug)]
#[derive(Deserialize, Serialize, PartialEq, Debug, Clone)]
pub struct Mail {
pub email_verification_enabled: bool,
pub from: String,
pub reply_to: String,
pub username: String,
pub password: String,
pub server: String,
pub port: u64,
pub port: u16,
}

#[derive(Deserialize, Serialize, PartialEq, Debug)]
#[derive(Deserialize, Serialize, PartialEq, Debug, Clone)]
pub struct ImageCache {
pub max_request_timeout_ms: u64,
pub capacity: u64,
pub entry_size_limit: u64,
pub capacity: usize,
pub entry_size_limit: usize,
pub user_quota_period_seconds: u64,
pub user_quota_bytes: u64,
pub user_quota_bytes: usize,
}

impl From<DomainSettings> for Settings {
fn from(settings: DomainSettings) -> Self {
Settings {
website: Website::from(settings.website),
tracker: Tracker::from(settings.tracker),
net: Network::from(settings.net),
auth: Auth::from(settings.auth),
database: Database::from(settings.database),
mail: Mail::from(settings.mail),
image_cache: ImageCache::from(settings.image_cache),
}
}
}

impl From<DomainWebsite> for Website {
fn from(website: DomainWebsite) -> Self {
Website { name: website.name }
}
}

impl From<DomainTracker> for Tracker {
fn from(tracker: DomainTracker) -> Self {
Tracker {
url: tracker.url,
mode: format!("{:?}", tracker.mode),
api_url: tracker.api_url,
token: tracker.token,
token_valid_seconds: tracker.token_valid_seconds,
}
}
}

impl From<DomainNetwork> for Network {
fn from(net: DomainNetwork) -> Self {
Network {
port: net.port,
base_url: net.base_url,
}
}
}

impl From<DomainAuth> for Auth {
fn from(auth: DomainAuth) -> Self {
Auth {
email_on_signup: format!("{:?}", auth.email_on_signup),
min_password_length: auth.min_password_length,
max_password_length: auth.max_password_length,
secret_key: auth.secret_key,
}
}
}

impl From<DomainDatabase> for Database {
fn from(database: DomainDatabase) -> Self {
Database {
connect_url: database.connect_url,
torrent_info_update_interval: database.torrent_info_update_interval,
}
}
}

impl From<DomainMail> for Mail {
fn from(mail: DomainMail) -> Self {
Mail {
email_verification_enabled: mail.email_verification_enabled,
from: mail.from,
reply_to: mail.reply_to,
username: mail.username,
password: mail.password,
server: mail.server,
port: mail.port,
}
}
}

impl From<DomainImageCache> for ImageCache {
fn from(image_cache: DomainImageCache) -> Self {
ImageCache {
max_request_timeout_ms: image_cache.max_request_timeout_ms,
capacity: image_cache.capacity,
entry_size_limit: image_cache.entry_size_limit,
user_quota_period_seconds: image_cache.user_quota_period_seconds,
user_quota_bytes: image_cache.user_quota_bytes,
}
}
}
44 changes: 44 additions & 0 deletions tests/e2e/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//! 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_`.
use std::env;

use torrust_index_backend::config::Configuration;

// Environment variables

/// If present, E2E tests will run against a shared instance of the server
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";

// Default values

pub const ENV_VAR_E2E_DEFAULT_CONFIG_PATH: &str = "./config-idx-back.local.toml";

/// Initialize configuration from file or env var.
///
/// # Panics
///
/// Will panic if configuration is not found or cannot be parsed
pub async fn init_shared_env_configuration() -> Configuration {
if env::var(ENV_VAR_E2E_CONFIG).is_ok() {
println!("Loading configuration for E2E env from env var `{}`", ENV_VAR_E2E_CONFIG);

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
);

match Configuration::load_from_file(ENV_VAR_E2E_DEFAULT_CONFIG_PATH).await {
Ok(config) => config,
Err(error) => {
panic!("{}", error)
}
}
}
}
8 changes: 4 additions & 4 deletions tests/e2e/contexts/settings/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ async fn it_should_allow_guests_to_get_the_public_settings() {
assert_eq!(
res.data,
Public {
website_name: "Torrust".to_string(),
tracker_url: env.tracker_url(),
tracker_mode: "Public".to_string(),
email_on_signup: "Optional".to_string(),
website_name: env.server_settings().unwrap().website.name,
tracker_url: env.server_settings().unwrap().tracker.url,
tracker_mode: env.server_settings().unwrap().tracker.mode,
email_on_signup: env.server_settings().unwrap().auth.email_on_signup,
}
);
if let Some(content_type) = &response.content_type {
Expand Down
4 changes: 2 additions & 2 deletions tests/e2e/contexts/user/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ the mailcatcher API.
// Responses data

#[tokio::test]
async fn it_should_allow_a_guess_user_to_register() {
async fn it_should_allow_a_guest_user_to_register() {
let mut env = TestEnv::new();
env.start().await;
let client = Client::unauthenticated(&env.server_socket_addr().unwrap());
Expand Down Expand Up @@ -175,7 +175,7 @@ mod banned_user_list {
}

#[tokio::test]
async fn it_should_not_allow_guess_to_ban_a_user() {
async fn it_should_not_allow_a_guest_to_ban_a_user() {
let mut env = TestEnv::new();
env.start().await;
let client = Client::unauthenticated(&env.server_socket_addr().unwrap());
Expand Down
Loading

0 comments on commit b97da41

Please sign in to comment.