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:
Jef Roosens 2026-05-06 20:38:04 +02:00
parent 8954104954
commit 8498fe9661
Signed by: Jef Roosens
GPG key ID: 21FD3D77D56BAF49
10 changed files with 89 additions and 89 deletions

9
Cargo.lock generated
View file

@ -837,11 +837,20 @@ dependencies = [
"diesel",
"diesel_migrations",
"gpodder",
"gpodder_test",
"libsqlite3-sys",
"rand",
"tracing",
]
[[package]]
name = "gpodder_test"
version = "0.3.0"
dependencies = [
"chrono",
"gpodder",
]
[[package]]
name = "half"
version = "2.6.0"

View file

@ -3,7 +3,8 @@ resolver = '2'
members = [
'otter',
'gpodder',
'gpodder_sqlite'
'gpodder_sqlite',
"gpodder_test"
]
[workspace.package]

View file

@ -27,3 +27,4 @@ features = [
[dev-dependencies]
criterion = "0.5.1"
gpodder_test = { path = "../gpodder_test" }

View file

@ -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);
}
}

View file

@ -297,3 +297,14 @@ impl gpodder::GpodderDeviceStore for SqliteRepository {
.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);
}
}

View file

@ -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
View file

@ -0,0 +1,9 @@
[package]
name = "gpodder_test"
version.workspace = true
edition.workspace = true
[dependencies]
gpodder = { path = "../gpodder" }
chrono.workspace = true

View file

@ -1,13 +1,7 @@
mod common;
use chrono::{SubsecRound, TimeDelta};
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");
assert!(user.is_ok());
assert_eq!(user.unwrap(), None);
@ -26,33 +20,8 @@ fn test_create_user() {
assert_eq!(user.unwrap(), Some(new_user));
}
#[test]
fn test_create_session() {
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();
pub fn test_remove_session(store: impl GpodderAuthStore) {
let users = super::create_test_users(&store);
let new_session = Session {
id: 123,
@ -80,13 +49,10 @@ fn test_remove_session() {
.expect("get session shouldn't fail")
.is_none()
);
common::teardown(path);
}
#[test]
fn test_refresh_session() {
let (path, store, users) = common::setup();
pub fn test_refresh_session(store: impl GpodderAuthStore) {
let users = super::create_test_users(&store);
let mut new_session = Session {
id: 123,
@ -109,13 +75,10 @@ fn test_refresh_session() {
store.get_session(123).expect("get session shouldn't fail"),
Some(new_session)
);
common::teardown(path);
}
#[test]
fn test_remove_old_sessions() {
let (path, store, users) = common::setup();
pub fn test_remove_old_sessions(store: impl GpodderAuthStore) {
let users = super::create_test_users(&store);
let now = chrono::Utc::now().trunc_subsecs(0);
let timestamps = [
@ -153,6 +116,4 @@ fn test_remove_old_sessions() {
user: users[0].clone(),
})
);
common::teardown(path);
}

View file

@ -1,10 +1,7 @@
mod common;
use gpodder::{DevicePatch, DeviceType, GpodderStore};
use gpodder::{DevicePatch, DeviceType, GpodderDeviceStore};
#[test]
fn test_insert_devices() {
let (path, store, users) = common::setup();
pub fn test_insert_devices(store: impl GpodderStore) {
let users = super::create_test_users(&store);
store.devices_for_user(&users[0]).unwrap();
@ -30,14 +27,9 @@ fn test_insert_devices() {
)
.expect("update info shouldn't fail");
let devices = store.devices_for_user(&users[0]);
assert!(matches!(devices, Ok(_)));
let devices = devices.unwrap();
let devices = store.devices_for_user(&users[0]).unwrap();
assert_eq!(devices.len(), 1);
assert_eq!(devices[0].caption, "caption1");
assert_eq!(devices[0].r#type, DeviceType::Other);
common::teardown(path);
}

17
gpodder_test/src/lib.rs Normal file
View 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
}