Skip to main content

sofie_testing/
wiring.rs

1use sofie_core::Result;
2use sofie_db::Db;
3use sofie_db::worker::Worker;
4use sofie_http::{App, Module};
5
6use crate::{TestApp, finish_teardown};
7
8pub trait AppWiring<Shape> {
9    const FLAGS: bool;
10
11    fn build(self, db: Db, flags: Option<&Flags>) -> impl Future<Output = Result<App>>;
12}
13
14pub trait WorkerWiring<Shape> {
15    fn build(self, db: Db, flags: Option<&Flags>) -> Worker;
16}
17
18#[cfg(feature = "flags")]
19pub use sofie_flags::Flags;
20
21#[cfg(not(feature = "flags"))]
22pub enum Flags {}
23
24impl<F, Built> AppWiring<fn(Db)> for F
25where
26    F: FnOnce(Db) -> Built,
27    Built: Future<Output = Result<App>>,
28{
29    const FLAGS: bool = false;
30
31    fn build(self, db: Db, _flags: Option<&Flags>) -> impl Future<Output = Result<App>> {
32        self(db)
33    }
34}
35
36impl<F> WorkerWiring<fn(Db)> for F
37where
38    F: FnOnce(Db) -> Worker,
39{
40    fn build(self, db: Db, _flags: Option<&Flags>) -> Worker {
41        self(db)
42    }
43}
44
45#[cfg(feature = "flags")]
46impl<F, Built> AppWiring<fn(Db, Flags)> for F
47where
48    F: FnOnce(Db, Flags) -> Built,
49    Built: Future<Output = Result<App>>,
50{
51    const FLAGS: bool = true;
52
53    fn build(self, db: Db, flags: Option<&Flags>) -> impl Future<Output = Result<App>> {
54        let flags = flags
55            .expect("the flags start before an app that takes them")
56            .clone();
57        self(db, flags)
58    }
59}
60
61#[cfg(feature = "flags")]
62impl<F> WorkerWiring<fn(Db, &Flags)> for F
63where
64    F: FnOnce(Db, &Flags) -> Worker,
65{
66    fn build(self, db: Db, flags: Option<&Flags>) -> Worker {
67        self(
68            db,
69            flags.expect("a worker taking the flags runs beside an app taking them"),
70        )
71    }
72}
73
74/// The runtime is shut down before the database is dropped, so no app connection holds the drop up.
75pub fn run_test_app<AppShape, WorkerShape, Test>(
76    modules: &[Module],
77    app: impl AppWiring<AppShape>,
78    worker: impl WorkerWiring<WorkerShape>,
79    test: impl FnOnce(TestApp) -> Test,
80) where
81    Test: Future<Output = ()>,
82{
83    let runtime = tokio::runtime::Builder::new_current_thread()
84        .enable_all()
85        .build()
86        .expect("building the test's runtime");
87    runtime.block_on(async {
88        let app = crate::start::wired(&sofie_http::migrations(modules), app, worker).await;
89        test(app).await;
90    });
91    drop(runtime);
92    finish_teardown();
93}