More login testing, added reference user factory fn.

This commit is contained in:
Joe Ardent 2023-06-02 17:01:59 -07:00
parent 569b19e837
commit 30169733a0
3 changed files with 64 additions and 20 deletions

View file

@ -15,8 +15,8 @@ use uuid::Uuid;
use crate::User; use crate::User;
const MAX_CONNS: u32 = 100; const MAX_CONNS: u32 = 200;
const MIN_CONNS: u32 = 10; const MIN_CONNS: u32 = 5;
const TIMEOUT: u64 = 11; const TIMEOUT: u64 = 11;
const SESSION_TTL: Duration = Duration::from_secs((365.2422 * 24. * 3600.0) as u64); const SESSION_TTL: Duration = Duration::from_secs((365.2422 * 24. * 3600.0) as u64);
@ -34,6 +34,9 @@ pub async fn get_pool() -> SqlitePool {
use rand_core::RngCore; use rand_core::RngCore;
let mut rng = rand_core::OsRng; let mut rng = rand_core::OsRng;
let id = rng.next_u64(); let id = rng.next_u64();
// see https://www.sqlite.org/inmemorydb.html for meaning of the string;
// it allows each separate test to have its own dedicated memory-backed db that
// will live as long as the whole process
format!("file:testdb-{id}?mode=memory&cache=shared") format!("file:testdb-{id}?mode=memory&cache=shared")
} }
}) })
@ -51,7 +54,7 @@ pub async fn get_pool() -> SqlitePool {
let pool = SqlitePoolOptions::new() let pool = SqlitePoolOptions::new()
.max_connections(MAX_CONNS) .max_connections(MAX_CONNS)
.min_connections(MIN_CONNS) .min_connections(MIN_CONNS)
.idle_timeout(Some(Duration::from_secs(10))) .idle_timeout(Some(Duration::from_secs(30)))
.max_lifetime(Some(Duration::from_secs(3600))) .max_lifetime(Some(Duration::from_secs(3600)))
.connect_with(conn_opts) .connect_with(conn_opts)
.await .await

View file

@ -103,30 +103,38 @@ pub async fn post_logout(mut auth: AuthContext) -> impl IntoResponse {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use std::time::Duration;
use axum::body::Bytes; use axum::body::Bytes;
use axum_test::TestServer; use axum_test::TestServer;
use uuid::Uuid;
use crate::{ use crate::{
db, db,
signup::create_user, signup::create_user,
templates::{LoginGet, LogoutGet, LogoutPost}, templates::{Index, LoginGet, LogoutGet, LogoutPost},
User,
}; };
fn get_user() -> User {
User {
username: "test_user".to_string(),
pwhash: "$argon2id$v=19$m=19456,t=2,p=1$GWsCH1w5RYaP9WWmq+xw0g$hmOEqC+MU+vnEk3bOdkoE+z01mOmmOeX08XyPyjqua8".to_string(),
id: Uuid::nil(),
..Default::default()
}
}
async fn tserver() -> TestServer { async fn tserver() -> TestServer {
let pool = db::get_pool().await; let pool = db::get_pool().await;
let secret = [0u8; 64]; let secret = [0u8; 64];
tokio::time::sleep(Duration::from_secs(2)).await; let user = get_user();
sqlx::query(crate::signup::CREATE_QUERY)
let _user = create_user( .bind(user.id)
"test_user", .bind(&user.username)
&Some("Test User".to_string()), .bind(&user.displayname)
&Some("mail@email".to_string()), .bind(&user.email)
"aaaa".as_bytes(), .bind(&user.pwhash)
&pool, .execute(&pool)
)
.await .await
.unwrap(); .unwrap();
@ -152,7 +160,7 @@ mod test {
async fn post_login_success() { async fn post_login_success() {
let s = tserver().await; let s = tserver().await;
let form = "username=test_user&password=aaaa".to_string(); let form = "username=test_user&password=a".to_string();
let bytes = form.as_bytes(); let bytes = form.as_bytes();
let body = Bytes::copy_from_slice(bytes); let body = Bytes::copy_from_slice(bytes);
@ -182,6 +190,23 @@ mod test {
assert_eq!(resp.status_code(), 200); assert_eq!(resp.status_code(), 200);
} }
#[tokio::test]
async fn post_login_bad_password() {
let s = tserver().await;
let form = "username=test_user&password=bbbb".to_string();
let bytes = form.as_bytes();
let body = Bytes::copy_from_slice(bytes);
let resp = s
.post("/login")
.expect_success()
.content_type("application/x-www-form-urlencoded")
.bytes(body)
.await;
assert_eq!(resp.status_code(), 200);
}
#[tokio::test] #[tokio::test]
async fn get_logout() { async fn get_logout() {
let s = tserver().await; let s = tserver().await;
@ -191,7 +216,7 @@ mod test {
} }
#[tokio::test] #[tokio::test]
async fn post_logout() { async fn post_logout_not_logged_in() {
let s = tserver().await; let s = tserver().await;
let resp = s.post("/logout").await; let resp = s.post("/logout").await;
resp.assert_status_ok(); resp.assert_status_ok();
@ -199,4 +224,20 @@ mod test {
let default = LogoutPost.to_string(); let default = LogoutPost.to_string();
assert_eq!(body, &default); assert_eq!(body, &default);
} }
#[tokio::test]
async fn post_logout_logged_in() {
let s = tserver().await;
// let resp = s
// .post("/login")
// .content_type("x-www-form-urlencoded")
// .text("username=test_user&password=a")
// .await;
let resp = s.post("/logout").await;
resp.assert_status_ok();
let body = std::str::from_utf8(resp.bytes()).unwrap();
let default = LogoutPost.to_string();
assert_eq!(body, &default);
}
} }

View file

@ -14,7 +14,7 @@ use uuid::Uuid;
use crate::{templates::CreateUser, User}; use crate::{templates::CreateUser, User};
const CREATE_QUERY: &str = pub(crate) const CREATE_QUERY: &str =
"insert into witches (id, username, displayname, email, pwhash) values ($1, $2, $3, $4, $5)"; "insert into witches (id, username, displayname, email, pwhash) values ($1, $2, $3, $4, $5)";
const ID_QUERY: &str = "select * from witches where id = $1"; const ID_QUERY: &str = "select * from witches where id = $1";