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

Base for Unit tests #66

Draft
wants to merge 14 commits into
base: master
Choose a base branch
from
Draft
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
29 changes: 27 additions & 2 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,24 @@ env:

jobs:
build:

runs-on: ubuntu-latest

services:
postgres:
image: postgres

env:
POSTGRES_PASSWORD: postgres
POSTGRES_USER: postgres
POSTGRES_DB: postgres
TEST_DATABASE_URL: postgres://postgres:postgres@localhost:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432

steps:
- uses: actions/checkout@v3
Expand All @@ -31,7 +47,16 @@ jobs:
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Build env variables
run: |
mv rocket.ci.toml rocket.toml
cat rocket.toml
- name: Build
run: cargo build --verbose
- name: Run tests
run: cargo test --verbose
run: cargo test --verbose
env:
ROCKET_DATABASES: |
{ test_db = { url = postgres://postgres:postgres@localhost:5432 } }
DATABASE_URL: postgres://postgres:postgres@localhost:5432
TEST_DATABASE_URL: postgres://postgres:postgres@localhost:5432
15 changes: 15 additions & 0 deletions rocket.ci.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[default.databases]
test_db = { url = "postgres://postgres:postgres@localhost:5432/postgres"}

[default.limits]
data-form = "32 MiB"

#[default.tls]
#certs = "ssl/localhost.pem"
#key = "ssl/localhost-key.pem"

[release]
test_db = { url = "postgres://postgres:postgres@localhost:5432/postgres"}
log_level="normal"
address = "0.0.0.0"
port = 8000
5 changes: 5 additions & 0 deletions src/db/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,14 @@ pub mod igniter;
pub mod models;
pub mod schema;

#[cfg(not(test))]
#[database("main_db")]
pub struct PostgresConn(pub diesel::PgConnection);

#[cfg(test)]
#[database("test_db")]
pub struct PostgresConn(pub diesel::PgConnection);

impl PostgresConn {
pub async fn find_api_payment(self, payment_request: String) -> Option<ApiPayment> {
self.run(|c| ApiPayment::find_one_by_request(payment_request, c))
Expand Down
19 changes: 11 additions & 8 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#![recursion_limit = "1024"]

#[cfg(test)]
mod tests;
#[macro_use]
extern crate juniper;

Expand Down Expand Up @@ -33,8 +34,8 @@ use app::Schema;
use db::igniter::run_db_migrations;
use dotenv::dotenv;
use juniper::EmptySubscription;
use rocket::Rocket;
use rocket::{fairing::AdHoc, Route};
use rocket::{Build, Rocket};
use routes::{auth::login, file::get_file, utils::graphiql, utils::static_index};
use std::env;

Expand All @@ -60,7 +61,12 @@ async fn main() -> Result<(), rocket::Error> {
dotenv().ok();
config::init();

let _rocket = Rocket::build()
let _rocket = app_build().launch().await.expect("server to launch");
Ok(())
}

fn app_build() -> Rocket<Build> {
let rocket = Rocket::build()
.attach(PostgresConn::fairing())
.attach(Cors)
.attach(AdHoc::try_on_ignite(
Expand All @@ -75,12 +81,9 @@ async fn main() -> Result<(), rocket::Error> {
Mutation,
EmptySubscription::<GQLContext>::new(),
))
.mount("/", routes_builder())
.launch()
.await
.expect("server to launch");
.mount("/", routes_builder());

Ok(())
return rocket;
}

fn routes_builder() -> Vec<Route> {
Expand Down
21 changes: 21 additions & 0 deletions src/rocket.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
pub fn rocket_instance() -> Rocket<Build> {
Rocket::build()
.attach(PostgresConn::fairing())
.attach(Cors)
.attach(AdHoc::try_on_ignite(
"Database Migrations",
run_db_migrations,
))
.manage(Cors)
// .configure(figment)
.register("/", catchers![payment_required])
.manage(Schema::new(
Query,
Mutation,
EmptySubscription::<GQLContext>::new(),
))
.mount("/", routes_builder())
.launch()
.await
.expect("server to launch")
}
82 changes: 82 additions & 0 deletions src/tests/database.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#[cfg(test)]
pub mod tests {

use diesel::{sql_query, Connection, PgConnection, RunQueryDsl};
use diesel_migrations::RunMigrationsError;

pub struct TestDb {
default_db_url: String,
url: String,
name: String,
delete_on_drop: bool,
}
impl TestDb {
pub fn new() -> Self {
let db_name = format!("test_{}", env!("CARGO_PKG_NAME"));
let default_db_url = std::env::var("TEST_DATABASE_URL").expect("TEST_DATABASE_URL");
let conn = PgConnection::establish(&default_db_url).unwrap();

sql_query(format!("DROP DATABASE IF EXISTS {};", &db_name))
.execute(&conn)
.unwrap();

sql_query(format!("CREATE DATABASE {};", db_name))
.execute(&conn)
.unwrap();

let url = format!("{}/{}", &default_db_url, &db_name);

let _migrations = Self::run_migrations(&url);

Self {
default_db_url,
url,
name: db_name,
delete_on_drop: true,
}
}

pub fn _url(&self) -> &str {
&self.url
}

pub fn run_migrations(db_url: &String) -> Result<(), RunMigrationsError> {
let conn = PgConnection::establish(db_url).unwrap();

diesel_migrations::run_pending_migrations(&conn)
}

// For further implementation of fixtures loading in test DB.
// pub fn load_fixtures(&self) -> () {
// let connection = &self.conn();

// }

pub fn conn(&self) -> PgConnection {
PgConnection::establish(&self.url.as_str()).unwrap()
}

pub fn _leak(&mut self) {
self.delete_on_drop = false;
}
}

impl Drop for TestDb {
fn drop(&mut self) {
if !self.delete_on_drop {
warn!("TestDb leaking database {}", self.name);
return;
}
let conn = PgConnection::establish(&self.default_db_url).unwrap();
sql_query(format!(
"SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '{}'",
self.name
))
.execute(&conn)
.unwrap();
sql_query(format!("DROP DATABASE {}", self.name))
.execute(&conn)
.unwrap();
}
}
}
36 changes: 36 additions & 0 deletions src/tests/db/media.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#[cfg(test)]
mod tests {
use diesel::Connection;
use lazy_static::lazy_static;

use crate::tests::database::tests::TestDb;

lazy_static! {
static ref TEST_DB: TestDb = TestDb::new();
}

#[test]
pub fn test_media_insert() -> () {
use crate::db::models::media::*;
use dotenv::dotenv;

dotenv().ok();

// let test_db = TestDb::new();

let conn = &TEST_DB.conn();

let new_media = NewMedia {
uuid: uuid::Uuid::new_v4(),
title: "test".to_string(),
description: Some("description test".to_string()),
absolute_path: "nowhere".to_string(),
published: true,
price: 100,
};

let result = &conn.test_transaction(|| Media::create(new_media, &conn));

assert_eq!("test".to_string(), result.title);
}
}
1 change: 1 addition & 0 deletions src/tests/db/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mod media;
5 changes: 5 additions & 0 deletions src/tests/fixtures/medias.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
use crate::db::models::media::{Media, NewMedia};

pub static Medias: Vec<NewMedia> = [

].to_vec();
1 change: 1 addition & 0 deletions src/tests/fixtures/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// mod medias;
5 changes: 5 additions & 0 deletions src/tests/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
mod database;
mod db;
mod fixtures;
#[cfg(test)]
mod rocket;
43 changes: 43 additions & 0 deletions src/tests/rocket.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#[cfg(test)]
mod tests {

use crate::app_build;
use rocket::http::ContentType;

// Sets environment variables for testing as .env file is not loaded
fn set_test_env_variables() -> () {
std::env::set_var("LND_ADDRESS", "https://umbrel.local:10009");
std::env::set_var("LND_CERTFILE_PATH", "src/lnd/config/lnd.cert");
std::env::set_var("LND_MACAROON_PATH", "src/lnd/config/admin.macaroon");
}

// Tests rocket ignition
#[rocket::async_test]
async fn test_rocket() {
use rocket::local::asynchronous::Client;
let _client = Client::tracked(app_build()).await.unwrap();
}

// This test ensures graphql gets provided through the expected endpoint
#[ignore]
#[rocket::async_test]
async fn test_graphql_http_endpoint() {
use rocket::local::asynchronous::Client;

set_test_env_variables();

let client = Client::tracked(app_build()).await.unwrap();

let request = client
.post(uri!(crate::app::post_graphql_handler))
.header(ContentType::JSON)
.body(r#"{"query":"query IntrospectionQuery {__schema {queryType { name }mutationType { name } subscriptionType { name }}}","operationName":"IntrospectionQuery"}"#);
let response = request.dispatch().await;

let content = response.into_string().await;

assert!(content.is_some());
}

// async fn test_graphql_
}