slave-framework 0.8.1

Runtime for slave apps (a Laravel-inspired Rust framework for MCP-first apps): server lifecycle, config, logging, a Toasty database (Turso), and OpenID Connect sign-in
//! Test doubles for apps' integration tests: a database ([`TestDatabase`])
//! and an OpenID Connect provider ([`TestIdentityProvider`]).
//!
//! Each [`TestDatabase`] is a fresh Turso database file in its own temporary
//! directory, removed when the test ends, so tests never share data and need
//! no database server.

use std::path::PathBuf;
use std::sync::atomic::{AtomicUsize, Ordering};

use crate::database::{DatabaseConfig, URL_ENV};

mod idp;

pub use idp::{TEST_CLIENT_ID, TestIdentityProvider, TokenSpec};

/// An empty database for one test, deleted when dropped.
pub struct TestDatabase {
    config: DatabaseConfig,
    dir: PathBuf,
}

impl TestDatabase {
    /// Provides an empty database (the file is created on first use).
    pub fn start() -> Self {
        static COUNTER: AtomicUsize = AtomicUsize::new(0);
        let n = COUNTER.fetch_add(1, Ordering::Relaxed);
        let dir = std::env::temp_dir().join(format!("slave-testdb-{}-{n}", std::process::id()));
        let _ = std::fs::remove_dir_all(&dir);
        std::fs::create_dir_all(&dir).expect("create test database directory");
        let config = DatabaseConfig {
            url: format!("turso:{}", dir.join("test.db").display()),
        };
        Self { config, dir }
    }

    pub fn config(&self) -> &DatabaseConfig {
        &self.config
    }

    /// `DATABASE_URL` for processes under test.
    pub fn envs(&self) -> [(&'static str, &str); 1] {
        [(URL_ENV, self.config.url.as_str())]
    }

    /// A pooled handle to this database for `models`.
    pub async fn connect(&self, models: toasty::ModelSet) -> toasty::Db {
        crate::database::connect(models, &self.config)
            .await
            .expect("open the test database")
    }
}

impl Drop for TestDatabase {
    fn drop(&mut self) {
        let _ = std::fs::remove_dir_all(&self.dir);
    }
}