Skip to content

Commit

Permalink
feat: cargo make + docker for e2e tests
Browse files Browse the repository at this point in the history
  • Loading branch information
matthew-hagemann committed Sep 1, 2023
1 parent cc51eb6 commit 4133b3c
Show file tree
Hide file tree
Showing 14 changed files with 132 additions and 91 deletions.
52 changes: 52 additions & 0 deletions Makefile.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
[tasks.docker-up]
script = [
"docker compose up --detach",
"sleep 3",
]

[tasks.run-server]
script = [
"cargo run &",
"echo $! > server.pid",
]

[tasks.run-tests]
script = [
"cargo test",
"sleep 1"
]

[tasks.wait-for-server]
script = [
"until nc -z -v -w5 localhost 8080; do",
" echo 'Waiting for server to start on port 8080...'",
" sleep 1",
"done"
]

[tasks.kill-server]
script = [
"kill $(cat server.pid)",
"rm server.pid"
]

[tasks.docker-down]
script = [
"docker compose down"
]

[tasks.full-test]
dependencies = [
"docker-up",
"run-server",
"wait-for-server",
"run-tests",
"kill-server",
"docker-down"
]

[tasks.full-clean]
script = [
"docker rmi ratings-postgres && docker rmi redis",
"cargo clean"
]
12 changes: 9 additions & 3 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,18 @@ version: '3'
services:

postgres:
image: postgres
build: ./docker/database
restart: always
ports:
- 5432:5432
- "5433:5432"
environment:
- POSTGRES_PASSWORD=postgres
POSTGRES_USER: ${DOCKER_POSTGRES_USER}
POSTGRES_PASSWORD: ${DOCKER_POSTGRES_PASSWORD}
MIGRATION_USER: ${DOCKER_MIGRATION_USER}
MIGRATION_PASSWORD: ${DOCKER_MIGRATION_PASSWORD}
SERVICE_USER: ${DOCKER_SERVICE_USER}
SERVICE_PASSWORD: ${DOCKER_SERVICE_PASSWORD}
RATINGS_DB: ${DOCKER_RATINGS_DB}

redis:
image: redis
Expand Down
5 changes: 5 additions & 0 deletions docker/database/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FROM postgres:latest

COPY init.sh /docker-entrypoint-initdb.d/

RUN chmod +x /docker-entrypoint-initdb.d/init.sh
15 changes: 15 additions & 0 deletions docker/database/init.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/bash
set -e

# Create users and databases
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "postgres" <<-EOSQL
CREATE USER $MIGRATION_USER WITH PASSWORD '$MIGRATION_PASSWORD';
CREATE USER $SERVICE_USER WITH PASSWORD '$SERVICE_PASSWORD';
CREATE DATABASE $RATINGS_DB;
EOSQL

# Set permissions on the new database
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$RATINGS_DB" <<-EOSQL
GRANT CONNECT ON DATABASE $RATINGS_DB TO $MIGRATION_USER;
GRANT USAGE, CREATE ON SCHEMA public TO $MIGRATION_USER;
EOSQL
11 changes: 10 additions & 1 deletion example.env
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,13 @@ APP_LOG_LEVEL=info
APP_NAME=ratings
APP_PORT=8080
# Update this with some real PostgreSQL details
APP_POSTGRES_URI=postgresql://username:password@localhost:5432/ratings
APP_POSTGRES_URI=postgresql://service:covfefe!1@localhost:5433/ratings
APP_MIGRATION_POSTGRES_URI=postgresql://migration_user:strongpassword@localhost:5433/ratings

DOCKER_POSTGRES_USER=postgres
DOCKER_POSTGRES_PASSWORD=@1234
DOCKER_MIGRATION_USER=migration_user
DOCKER_MIGRATION_PASSWORD=strongpassword
DOCKER_SERVICE_USER=service
DOCKER_SERVICE_PASSWORD=covfefe!1
DOCKER_RATINGS_DB=ratings
4 changes: 0 additions & 4 deletions sql/bootstrap/roles.down.sql

This file was deleted.

6 changes: 0 additions & 6 deletions sql/bootstrap/roles.up.sql

This file was deleted.

4 changes: 3 additions & 1 deletion src/app/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ use tonic::transport::Server;
use tower::ServiceBuilder;
use tracing::info;

use crate::utils::{Config, Infrastructure};
use crate::utils::{Config, Infrastructure, Migrator};

use super::interfaces::routes::{build_reflection_service, build_servers};
use super::interfaces::{authentication::authentication, middleware::ContextMiddlewareLayer};

pub async fn run(config: Config) -> Result<(), Box<dyn std::error::Error>> {
let migrator = Migrator::new(&config.migration_postgres_uri).await?;
migrator.run().await?;
let infra = Infrastructure::new(&config).await?;
let app_ctx = AppContext::new(&config, infra);

Expand Down
2 changes: 1 addition & 1 deletion src/utils/migrator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::sync::Arc;

use sqlx::{postgres::PgPoolOptions, PgPool};

const MIGRATIONS_PATH: &str = "sql/migrations";
const MIGRATIONS_PATH: &str = "./sql/migrations";

#[derive(Clone)]
pub struct Migrator {
Expand Down
12 changes: 4 additions & 8 deletions tests/app_tests/lifecycle_test.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use futures::FutureExt;
use ratings::{
app::AppContext,
utils::{Config, Infrastructure, Migrator},
utils::{Config, Infrastructure},
};

use super::super::helpers::with_lifecycle::with_lifecycle;
Expand All @@ -19,7 +19,6 @@ async fn app_lifecycle_test() -> Result<(), Box<dyn std::error::Error>> {
let infra = Infrastructure::new(&config).await?;
let app_ctx = AppContext::new(&config, infra);

let migrator = Migrator::new(&config.migration_postgres_uri).await?;
let data = TestData {
user_client: Some(UserClient::new(&config.socket())),
app_ctx,
Expand All @@ -29,12 +28,9 @@ async fn app_lifecycle_test() -> Result<(), Box<dyn std::error::Error>> {
snap_id: Some(data_faker::rnd_id()),
};

with_lifecycle(
async {
vote_once(data.clone()).then(vote_up).await;
},
migrator,
)
with_lifecycle(async {
vote_once(data.clone()).then(vote_up).await;
})
.await;
Ok(())
}
Expand Down
27 changes: 3 additions & 24 deletions tests/helpers/hooks.rs
Original file line number Diff line number Diff line change
@@ -1,32 +1,11 @@
use std::sync::{Arc, Once};

use once_cell::sync::Lazy;
use ratings::utils::Migrator;
use tokio::sync::Mutex;
use std::sync::Once;

static INIT: Once = Once::new();
static TEST_COUNTER: Lazy<Arc<Mutex<i32>>> = Lazy::new(|| Arc::new(Mutex::new(0)));

pub async fn before_all(migrator: Migrator) {
pub async fn before_all() {
INIT.call_once(|| {
tracing_subscriber::fmt().init();
});
if let Err(e) = migrator.run().await {
panic!("{}", e)
}

let counter = Arc::clone(&*TEST_COUNTER);
let mut test_counter = counter.lock().await;
*test_counter += 1;
}

pub async fn after_all(migrator: Migrator) {
let counter = Arc::clone(&*TEST_COUNTER);
let mut test_counter = counter.lock().await;
*test_counter -= 1;
if *test_counter == 0 {
if let Err(e) = migrator.revert().await {
panic!("{}", e)
}
}
}
pub async fn after_all() {}
7 changes: 3 additions & 4 deletions tests/helpers/with_lifecycle.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
use std::future::Future;

use crate::helpers::hooks::{after_all, before_all};
use ratings::utils::Migrator;

pub async fn with_lifecycle<F>(f: F, migrator: Migrator)
pub async fn with_lifecycle<F>(f: F)
where
F: Future<Output = ()>,
{
before_all(migrator.clone()).await;
before_all().await;
f.await;
after_all(migrator.clone()).await;
after_all().await;
}
46 changes: 19 additions & 27 deletions tests/user_tests/reject_invalid_register_test.rs
Original file line number Diff line number Diff line change
@@ -1,50 +1,42 @@
use ratings::utils::{Config, Migrator};
use ratings::utils::Config;
use tonic::Code;

use super::super::helpers::{client_user::UserClient, with_lifecycle::with_lifecycle};

#[tokio::test]
async fn blank() -> Result<(), Box<dyn std::error::Error>> {
let config = Config::load()?;
let migrator = Migrator::new(&config.migration_postgres_uri).await?;

with_lifecycle(
async {
let id = "";
let client = UserClient::new(&config.socket());
with_lifecycle(async {
let id = "";
let client = UserClient::new(&config.socket());

match client.register(id).await {
Ok(response) => panic!("expected Err but got Ok: {response:?}"),
Err(status) => {
assert_eq!(status.code(), Code::InvalidArgument)
}
match client.register(id).await {
Ok(response) => panic!("expected Err but got Ok: {response:?}"),
Err(status) => {
assert_eq!(status.code(), Code::InvalidArgument)
}
},
migrator,
)
}
})
.await;
Ok(())
}

#[tokio::test]
async fn wrong_length() -> Result<(), Box<dyn std::error::Error>> {
let config = Config::load()?;
let migrator = Migrator::new(&config.migration_postgres_uri).await?;

with_lifecycle(
async {
let client_hash = "foobarbazbun";
let client = UserClient::new(&config.socket());
with_lifecycle(async {
let client_hash = "foobarbazbun";
let client = UserClient::new(&config.socket());

match client.register(client_hash).await {
Ok(response) => panic!("expected Err but got Ok: {response:?}"),
Err(status) => {
assert_eq!(status.code(), Code::InvalidArgument)
}
match client.register(client_hash).await {
Ok(response) => panic!("expected Err but got Ok: {response:?}"),
Err(status) => {
assert_eq!(status.code(), Code::InvalidArgument)
}
},
migrator,
)
}
})
.await;
Ok(())
}
20 changes: 8 additions & 12 deletions tests/user_tests/simple_lifecycle_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use super::super::helpers::client_user::UserClient;
use super::super::helpers::with_lifecycle::with_lifecycle;
use futures::FutureExt;
use ratings::app::AppContext;
use ratings::utils::{self, Infrastructure, Migrator};
use ratings::utils::{self, Infrastructure};
use sqlx::Row;

use utils::Config;
Expand All @@ -16,7 +16,6 @@ async fn user_simple_lifecycle_test() -> Result<(), Box<dyn std::error::Error>>
let config = Config::load()?;
let infra = Infrastructure::new(&config).await?;
let app_ctx = AppContext::new(&config, infra);
let migrator = Migrator::new(&config.migration_postgres_uri).await?;

let data = TestData {
user_client: Some(UserClient::new(&config.socket())),
Expand All @@ -27,16 +26,13 @@ async fn user_simple_lifecycle_test() -> Result<(), Box<dyn std::error::Error>>
snap_id: None,
};

with_lifecycle(
async {
register(data.clone())
.then(authenticate)
.then(vote)
.then(delete)
.await;
},
migrator,
)
with_lifecycle(async {
register(data.clone())
.then(authenticate)
.then(vote)
.then(delete)
.await;
})
.await;
Ok(())
}
Expand Down

0 comments on commit 4133b3c

Please sign in to comment.