refactor(test): move existing gpodder_sqlite tests into a separate crate
This refactor allows new implementations of the store contract to reuse the same tests, ensuring all implementations support the same behavior.
This commit is contained in:
parent
8954104954
commit
8498fe9661
10 changed files with 89 additions and 89 deletions
9
Cargo.lock
generated
9
Cargo.lock
generated
|
|
@ -837,11 +837,20 @@ dependencies = [
|
||||||
"diesel",
|
"diesel",
|
||||||
"diesel_migrations",
|
"diesel_migrations",
|
||||||
"gpodder",
|
"gpodder",
|
||||||
|
"gpodder_test",
|
||||||
"libsqlite3-sys",
|
"libsqlite3-sys",
|
||||||
"rand",
|
"rand",
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gpodder_test"
|
||||||
|
version = "0.3.0"
|
||||||
|
dependencies = [
|
||||||
|
"chrono",
|
||||||
|
"gpodder",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "half"
|
name = "half"
|
||||||
version = "2.6.0"
|
version = "2.6.0"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,8 @@ resolver = '2'
|
||||||
members = [
|
members = [
|
||||||
'otter',
|
'otter',
|
||||||
'gpodder',
|
'gpodder',
|
||||||
'gpodder_sqlite'
|
'gpodder_sqlite',
|
||||||
|
"gpodder_test"
|
||||||
]
|
]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
|
|
|
||||||
|
|
@ -27,3 +27,4 @@ features = [
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
criterion = "0.5.1"
|
criterion = "0.5.1"
|
||||||
|
gpodder_test = { path = "../gpodder_test" }
|
||||||
|
|
|
||||||
|
|
@ -249,3 +249,32 @@ impl gpodder::GpodderAuthStore for SqliteRepository {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::SqliteRepository;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_create_user() {
|
||||||
|
let store = SqliteRepository::in_memory().unwrap();
|
||||||
|
gpodder_test::auth::test_create_user(store);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_remove_session() {
|
||||||
|
let store = SqliteRepository::in_memory().unwrap();
|
||||||
|
gpodder_test::auth::test_remove_session(store);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_refresh_session() {
|
||||||
|
let store = SqliteRepository::in_memory().unwrap();
|
||||||
|
gpodder_test::auth::test_refresh_session(store);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_remove_old_sessions() {
|
||||||
|
let store = SqliteRepository::in_memory().unwrap();
|
||||||
|
gpodder_test::auth::test_remove_old_sessions(store);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -297,3 +297,14 @@ impl gpodder::GpodderDeviceStore for SqliteRepository {
|
||||||
.map_err(AuthErr::from)
|
.map_err(AuthErr::from)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::SqliteRepository;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_insert_devices() {
|
||||||
|
let store = SqliteRepository::in_memory().unwrap();
|
||||||
|
gpodder_test::device::test_insert_devices(store);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
use gpodder::{GpodderAuthStore, User};
|
|
||||||
use gpodder_sqlite::SqliteRepository;
|
|
||||||
|
|
||||||
use rand::{Rng, distributions::Alphanumeric};
|
|
||||||
|
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
pub fn setup() -> (PathBuf, SqliteRepository, Vec<User>) {
|
|
||||||
let fname: String = rand::thread_rng()
|
|
||||||
.sample_iter(Alphanumeric)
|
|
||||||
.take(10)
|
|
||||||
.map(char::from)
|
|
||||||
.collect();
|
|
||||||
let path = std::env::temp_dir().join(fname);
|
|
||||||
let store = SqliteRepository::from_path(&path).unwrap();
|
|
||||||
let mut users = Vec::new();
|
|
||||||
|
|
||||||
for i in 0..4 {
|
|
||||||
let username = format!("test{}", i + 1);
|
|
||||||
let password_hash = format!("dummyhash{}", i + 1);
|
|
||||||
|
|
||||||
users.push(store.insert_user(&username, &password_hash).unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
(path, store, users)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn teardown(path: PathBuf) {
|
|
||||||
let _ = std::fs::remove_file(path);
|
|
||||||
}
|
|
||||||
9
gpodder_test/Cargo.toml
Normal file
9
gpodder_test/Cargo.toml
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
[package]
|
||||||
|
name = "gpodder_test"
|
||||||
|
version.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
gpodder = { path = "../gpodder" }
|
||||||
|
|
||||||
|
chrono.workspace = true
|
||||||
|
|
@ -1,13 +1,7 @@
|
||||||
mod common;
|
|
||||||
|
|
||||||
use chrono::{SubsecRound, TimeDelta};
|
use chrono::{SubsecRound, TimeDelta};
|
||||||
use gpodder::{GpodderAuthStore, Session};
|
use gpodder::{GpodderAuthStore, Session};
|
||||||
use gpodder_sqlite::SqliteRepository;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_create_user() {
|
|
||||||
let store = SqliteRepository::in_memory().unwrap();
|
|
||||||
|
|
||||||
|
pub fn test_create_user(store: impl GpodderAuthStore) {
|
||||||
let user = store.get_user("test1");
|
let user = store.get_user("test1");
|
||||||
assert!(user.is_ok());
|
assert!(user.is_ok());
|
||||||
assert_eq!(user.unwrap(), None);
|
assert_eq!(user.unwrap(), None);
|
||||||
|
|
@ -26,33 +20,8 @@ fn test_create_user() {
|
||||||
assert_eq!(user.unwrap(), Some(new_user));
|
assert_eq!(user.unwrap(), Some(new_user));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
pub fn test_remove_session(store: impl GpodderAuthStore) {
|
||||||
fn test_create_session() {
|
let users = super::create_test_users(&store);
|
||||||
let (path, store, users) = common::setup();
|
|
||||||
|
|
||||||
let session = store.get_session(123).expect("operation shouldn't fail");
|
|
||||||
assert_eq!(session, None);
|
|
||||||
|
|
||||||
let new_session = Session {
|
|
||||||
id: 123,
|
|
||||||
user_agent: None,
|
|
||||||
last_seen: chrono::Utc::now().trunc_subsecs(0),
|
|
||||||
user: users[0].clone(),
|
|
||||||
};
|
|
||||||
|
|
||||||
store
|
|
||||||
.insert_session(&new_session)
|
|
||||||
.expect("insert session shouldn't fail");
|
|
||||||
|
|
||||||
let session = store.get_session(123).expect("operation shouldn't fail");
|
|
||||||
assert_eq!(session, Some(new_session));
|
|
||||||
|
|
||||||
common::teardown(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_remove_session() {
|
|
||||||
let (path, store, users) = common::setup();
|
|
||||||
|
|
||||||
let new_session = Session {
|
let new_session = Session {
|
||||||
id: 123,
|
id: 123,
|
||||||
|
|
@ -80,13 +49,10 @@ fn test_remove_session() {
|
||||||
.expect("get session shouldn't fail")
|
.expect("get session shouldn't fail")
|
||||||
.is_none()
|
.is_none()
|
||||||
);
|
);
|
||||||
|
|
||||||
common::teardown(path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
pub fn test_refresh_session(store: impl GpodderAuthStore) {
|
||||||
fn test_refresh_session() {
|
let users = super::create_test_users(&store);
|
||||||
let (path, store, users) = common::setup();
|
|
||||||
|
|
||||||
let mut new_session = Session {
|
let mut new_session = Session {
|
||||||
id: 123,
|
id: 123,
|
||||||
|
|
@ -109,13 +75,10 @@ fn test_refresh_session() {
|
||||||
store.get_session(123).expect("get session shouldn't fail"),
|
store.get_session(123).expect("get session shouldn't fail"),
|
||||||
Some(new_session)
|
Some(new_session)
|
||||||
);
|
);
|
||||||
|
|
||||||
common::teardown(path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
pub fn test_remove_old_sessions(store: impl GpodderAuthStore) {
|
||||||
fn test_remove_old_sessions() {
|
let users = super::create_test_users(&store);
|
||||||
let (path, store, users) = common::setup();
|
|
||||||
|
|
||||||
let now = chrono::Utc::now().trunc_subsecs(0);
|
let now = chrono::Utc::now().trunc_subsecs(0);
|
||||||
let timestamps = [
|
let timestamps = [
|
||||||
|
|
@ -153,6 +116,4 @@ fn test_remove_old_sessions() {
|
||||||
user: users[0].clone(),
|
user: users[0].clone(),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
common::teardown(path);
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,10 +1,7 @@
|
||||||
mod common;
|
use gpodder::{DevicePatch, DeviceType, GpodderStore};
|
||||||
|
|
||||||
use gpodder::{DevicePatch, DeviceType, GpodderDeviceStore};
|
pub fn test_insert_devices(store: impl GpodderStore) {
|
||||||
|
let users = super::create_test_users(&store);
|
||||||
#[test]
|
|
||||||
fn test_insert_devices() {
|
|
||||||
let (path, store, users) = common::setup();
|
|
||||||
|
|
||||||
store.devices_for_user(&users[0]).unwrap();
|
store.devices_for_user(&users[0]).unwrap();
|
||||||
|
|
||||||
|
|
@ -30,14 +27,9 @@ fn test_insert_devices() {
|
||||||
)
|
)
|
||||||
.expect("update info shouldn't fail");
|
.expect("update info shouldn't fail");
|
||||||
|
|
||||||
let devices = store.devices_for_user(&users[0]);
|
let devices = store.devices_for_user(&users[0]).unwrap();
|
||||||
assert!(matches!(devices, Ok(_)));
|
|
||||||
|
|
||||||
let devices = devices.unwrap();
|
|
||||||
assert_eq!(devices.len(), 1);
|
assert_eq!(devices.len(), 1);
|
||||||
|
|
||||||
assert_eq!(devices[0].caption, "caption1");
|
assert_eq!(devices[0].caption, "caption1");
|
||||||
assert_eq!(devices[0].r#type, DeviceType::Other);
|
assert_eq!(devices[0].r#type, DeviceType::Other);
|
||||||
|
|
||||||
common::teardown(path);
|
|
||||||
}
|
}
|
||||||
17
gpodder_test/src/lib.rs
Normal file
17
gpodder_test/src/lib.rs
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
use gpodder::{GpodderAuthStore, User};
|
||||||
|
|
||||||
|
pub mod auth;
|
||||||
|
pub mod device;
|
||||||
|
|
||||||
|
fn create_test_users(store: &impl GpodderAuthStore) -> Vec<User> {
|
||||||
|
let mut users = Vec::new();
|
||||||
|
|
||||||
|
for i in 0..4 {
|
||||||
|
let username = format!("test{}", i + 1);
|
||||||
|
let password_hash = format!("dummyhash{}", i + 1);
|
||||||
|
|
||||||
|
users.push(store.insert_user(&username, &password_hash).unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
users
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue