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
74pub 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}