-
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Changed ERror Handling, Also added testing system
- Loading branch information
1 parent
6a1f851
commit 863e577
Showing
44 changed files
with
648 additions
and
248 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,3 +2,4 @@ target/ | |
.vscode/ | ||
test/ | ||
.env | ||
nr_tests.env |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
use sqlx::{migrate::Migrator, PgPool}; | ||
static MIGRATOR: Migrator = sqlx::migrate!(); | ||
pub async fn run_migrations(pool: &PgPool) -> Result<(), sqlx::Error> { | ||
MIGRATOR.run(pool).await?; | ||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
use std::{collections::HashMap, path::PathBuf}; | ||
|
||
use tracing::{debug, info, instrument}; | ||
#[instrument] | ||
pub fn find_file(dir: PathBuf, file_name: &str) -> Option<PathBuf> { | ||
let env_file = dir.join(file_name); | ||
info!("Checking for file: {:?}", env_file); | ||
if env_file.exists() { | ||
return Some(env_file); | ||
} | ||
let parent = dir.parent()?; | ||
debug!("Checking parent: {:?}", parent); | ||
find_file(parent.to_path_buf(), file_name) | ||
} | ||
#[derive(Debug)] | ||
pub struct EnvFile { | ||
pub file: PathBuf, | ||
pub key_values: HashMap<String, String>, | ||
} | ||
impl EnvFile { | ||
pub fn load(file_name: &str) -> anyhow::Result<Self> { | ||
let current_dir = std::env::current_dir()?; | ||
let file = | ||
find_file(current_dir, file_name).ok_or_else(|| anyhow::anyhow!("File not found"))?; | ||
let file_contents = std::fs::read_to_string(&file)?; | ||
let mut key_values = HashMap::new(); | ||
for line in file_contents.lines() { | ||
let mut parts = line.splitn(2, '='); | ||
let key = parts.next().unwrap(); | ||
let value = parts.next().unwrap(); | ||
key_values.insert(key.to_string(), value.to_string()); | ||
} | ||
Ok(Self { file, key_values }) | ||
} | ||
pub fn get(&self, key: &str) -> Option<String> { | ||
if let Ok(key) = std::env::var(key) { | ||
return Some(key); | ||
} | ||
self.key_values.get(key).map(|s| s.to_owned()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
use std::str::FromStr; | ||
|
||
use env_file::EnvFile; | ||
use sqlx::PgPool; | ||
use tracing::{debug, error, info}; | ||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, Layer}; | ||
pub mod env_file; | ||
|
||
use crate::{ | ||
database::{ | ||
user::{NewUserRequest, UserSafeData, UserType}, | ||
DateTime, | ||
}, | ||
user::{Email, Username}, | ||
}; | ||
/// The password for the test user | ||
pub static TEST_USER_USERNAME: &str = "test_user"; | ||
|
||
pub static TEST_USER_PASSWORD: &str = "password"; | ||
static TEST_USER_PASSWORD_HASHED: &str = | ||
"$argon2id$v=19$m=16,t=2,p=1$b1o5VWFvVFYxRTFhUUJjeA$bpK+ySI4DIDIOh4emBFTqw"; | ||
/// Table Name: `nr_test_environment` | ||
static TEST_INFO_TABLE: &str = include_str!("test_info.sql"); | ||
static LOGGING_INIT: std::sync::Once = std::sync::Once::new(); | ||
|
||
pub struct TestCore { | ||
pub db: PgPool, | ||
} | ||
impl TestCore { | ||
pub async fn new(function_path: String) -> anyhow::Result<(Self, TestInfoEntry)> { | ||
let env_file = env_file::EnvFile::load("nr_tests.env")?; | ||
Self::start_logger(&env_file); | ||
let database = Self::connect(&env_file).await?; | ||
let new = Self { db: database }; | ||
new.init_test_environment().await?; | ||
|
||
let entry = TestInfoEntry::get_or_create(&function_path, &new.db).await?; | ||
Ok((new, entry)) | ||
} | ||
fn start_logger(env_file: &EnvFile) { | ||
let log = env_file.get("LOG"); | ||
if let Some(log) = log { | ||
let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| log.into()); | ||
|
||
LOGGING_INIT.call_once(|| { | ||
let stdout_log = tracing_subscriber::fmt::layer().pretty(); | ||
match tracing_subscriber::registry() | ||
.with(stdout_log.with_filter(env_filter)) | ||
.try_init() | ||
{ | ||
Ok(_) => { | ||
debug!("Logging initialized"); | ||
} | ||
Err(err) => { | ||
eprintln!("Error initializing logging: {}", err); | ||
} | ||
}; | ||
}); | ||
} | ||
} | ||
async fn connect(env_file: &EnvFile) -> anyhow::Result<PgPool> { | ||
let env = env_file.get("DATABASE_URL").unwrap(); | ||
debug!("Connecting to database {}", env); | ||
let db = PgPool::connect(&env).await?; | ||
Ok(db) | ||
} | ||
async fn init_test_environment(&self) -> anyhow::Result<()> { | ||
crate::database::migration::run_migrations(&self.db).await?; | ||
sqlx::query(TEST_INFO_TABLE).execute(&self.db).await?; | ||
Ok(()) | ||
} | ||
|
||
pub async fn get_test_user(&self) -> anyhow::Result<Option<UserSafeData>> { | ||
if let Some(user) = UserSafeData::get_by_id(1, &self.db).await? { | ||
return Ok(Some(user)); | ||
} else { | ||
let user = NewUserRequest { | ||
name: "Test User".to_string(), | ||
username: Username::from_str(TEST_USER_USERNAME)?, | ||
email: Email::from_str("[email protected]")?, | ||
password: Some(TEST_USER_PASSWORD_HASHED.to_owned()), | ||
}; | ||
let user = user.insert_admin(&self.db).await?; | ||
return Ok(Some(user.into())); | ||
} | ||
} | ||
} | ||
#[derive(Debug, Clone, sqlx::FromRow)] | ||
pub struct TestInfoEntry { | ||
pub id: i32, | ||
pub function_path: String, | ||
pub run_successfully: Option<bool>, | ||
pub started_at: Option<DateTime>, | ||
} | ||
impl TestInfoEntry { | ||
pub async fn get_or_create( | ||
function_path: &str, | ||
db: &PgPool, | ||
) -> Result<TestInfoEntry, sqlx::Error> { | ||
let entry = sqlx::query_as::<_, TestInfoEntry>( | ||
r#"INSERT INTO nr_test_environment (function_path) VALUES($1) ON CONFLICT (function_path) DO UPDATE | ||
SET run_successfully = null, started_at = CURRENT_TIMESTAMP | ||
RETURNING *;"#, | ||
) | ||
.bind(function_path.to_owned()) | ||
.fetch_one(db) | ||
.await?; | ||
Ok(entry) | ||
} | ||
|
||
pub async fn set_success(&self, db: &PgPool) -> Result<(), sqlx::Error> { | ||
sqlx::query(r#"UPDATE nr_test_environment SET run_successfully = true WHERE id = $1;"#) | ||
.bind(self.id) | ||
.execute(db) | ||
.await?; | ||
Ok(()) | ||
} | ||
} | ||
|
||
async fn does_table_exist(table_name: &str, db: &PgPool) -> Result<bool, sqlx::Error> { | ||
let table_exists: bool = sqlx::query_scalar( | ||
r#" | ||
SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = $1) AS table_existence;"#, | ||
) | ||
.bind(table_name) | ||
.fetch_one(db) | ||
.await?; | ||
info!("Table {} exists: {}", table_name, table_exists); | ||
Ok(table_exists) | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
#[tokio::test] | ||
pub async fn test_test_core() { | ||
let (core, entry) = super::TestCore::new(format!("{}::test_test_core", module_path!())) | ||
.await | ||
.unwrap(); | ||
let user = core.get_test_user().await.unwrap(); | ||
assert!(user.is_some()); | ||
entry.set_success(&core.db).await.unwrap(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
CREATE TABLE IF NOT EXISTS nr_test_environment ( | ||
id SERIAL PRIMARY KEY, | ||
function_path TEXT NOT NULL, | ||
constraint function_path_unique UNIQUE (function_path), | ||
run_successfully BOOLEAN, | ||
started_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP | ||
); |
Oops, something went wrong.