tytanic_core/
dsl.rs

1//! Implementations for the test set DSL. See the language [reference] and
2//! [guide] for more info.
3//!
4//! [reference]: https://typst-community.github.io/tytanic/reference/test-sets/index.html
5//! [guide]: https://typst-community.github.io/tytanic/guides/test-sets.html
6
7use tytanic_filter::ast::Id;
8use tytanic_filter::eval;
9use tytanic_filter::eval::Context;
10use tytanic_filter::eval::Error;
11use tytanic_filter::eval::Func;
12use tytanic_filter::eval::Set;
13use tytanic_filter::eval::Value;
14
15use crate::test::Test;
16
17impl eval::Test for Test {
18    fn id(&self) -> &str {
19        self.id().as_str()
20    }
21}
22
23/// Creates the default context used by Tytanic, this contains bindings for the
24/// constructor functions in [`built_in`].
25pub fn context() -> Context<Test> {
26    type FuncPtr =
27        for<'a, 'b> fn(&'a Context<Test>, &'b [Value<Test>]) -> Result<Value<Test>, Error>;
28
29    let mut ctx = Context::new();
30
31    let functions = [
32        ("all", built_in::all_ctor as FuncPtr),
33        ("none", built_in::none_ctor),
34        ("skip", built_in::skip_ctor),
35        ("unit", built_in::unit_ctor),
36        ("template", built_in::template_ctor),
37        ("compile-only", built_in::compile_only_ctor),
38        ("ephemeral", built_in::ephemeral_ctor),
39        ("persistent", built_in::persistent_ctor),
40    ];
41
42    for (id, func) in functions {
43        ctx.bind(Id(id.into()), Value::Func(Func::new(func)));
44    }
45
46    ctx
47}
48
49/// Function definitions for the Tytanic test set DSL default evaluation
50/// context.
51pub mod built_in {
52    use tytanic_filter::eval::Context;
53    use tytanic_filter::eval::Error;
54    use tytanic_filter::eval::Func;
55    use tytanic_filter::eval::Value;
56
57    use super::*;
58
59    /// The constructor function for the test set returned by [`all`].
60    pub fn all_ctor(ctx: &Context<Test>, args: &[Value<Test>]) -> Result<Value<Test>, Error> {
61        Func::expect_no_args("all", ctx, args)?;
62        Ok(Value::Set(all()))
63    }
64
65    /// Constructor for the `all()` test set. A test set which contains _all_
66    /// tests.
67    pub fn all() -> Set<Test> {
68        Set::new(|_, _| Ok(true))
69    }
70
71    /// The constructor function for the test set returned by [`none`].
72    pub fn none_ctor(ctx: &Context<Test>, args: &[Value<Test>]) -> Result<Value<Test>, Error> {
73        Func::expect_no_args("none", ctx, args)?;
74        Ok(Value::Set(none()))
75    }
76
77    /// Constructor for the `none()` test set. A test set which contains _no_
78    /// tests.
79    pub fn none() -> Set<Test> {
80        Set::new(|_, _| Ok(false))
81    }
82
83    /// The constructor function for the test set returned by [`skip`].
84    pub fn skip_ctor(ctx: &Context<Test>, args: &[Value<Test>]) -> Result<Value<Test>, Error> {
85        Func::expect_no_args("skip", ctx, args)?;
86        Ok(Value::Set(skip()))
87    }
88
89    /// Constructs the `skip()` test set. A test set which contains all tests
90    /// marked with the `skip` annotation.
91    pub fn skip() -> Set<Test> {
92        Set::new(|_, test: &Test| Ok(test.as_unit_test().is_some_and(|unit| unit.is_skip())))
93    }
94
95    /// The constructor function for the test set returned by [`unit`].
96    ///
97    /// [`unit`]: unit()
98    pub fn unit_ctor(ctx: &Context<Test>, args: &[Value<Test>]) -> Result<Value<Test>, Error> {
99        Func::expect_no_args("unit", ctx, args)?;
100        Ok(Value::Set(unit()))
101    }
102
103    /// Constructs the `unit()` test set. A test set which contains all unit tests.
104    pub fn unit() -> Set<Test> {
105        Set::new(|_, test: &Test| Ok(test.as_unit_test().is_some()))
106    }
107
108    /// The constructor function for the test set returned by [`template`].
109    pub fn template_ctor(ctx: &Context<Test>, args: &[Value<Test>]) -> Result<Value<Test>, Error> {
110        Func::expect_no_args("template", ctx, args)?;
111        Ok(Value::Set(template()))
112    }
113
114    /// Constructs the `template()` test set. A test set which contains all
115    /// template tests.
116    pub fn template() -> Set<Test> {
117        Set::new(|_, test: &Test| Ok(test.as_template_test().is_some()))
118    }
119
120    /// The constructor function for the test set returned by [`compile_only`].
121    pub fn compile_only_ctor(
122        ctx: &Context<Test>,
123        args: &[Value<Test>],
124    ) -> Result<Value<Test>, Error> {
125        Func::expect_no_args("compile-only", ctx, args)?;
126        Ok(Value::Set(compile_only()))
127    }
128
129    /// Constructs the `compile-only()` test set. A test set which contains all
130    /// `compile-only` unit tests.
131    pub fn compile_only() -> Set<Test> {
132        Set::new(|_, test: &Test| {
133            Ok(test
134                .as_unit_test()
135                .is_some_and(|unit| unit.kind().is_compile_only()))
136        })
137    }
138
139    /// The constructor function for the test set returned by [`ephemeral`].
140    pub fn ephemeral_ctor(ctx: &Context<Test>, args: &[Value<Test>]) -> Result<Value<Test>, Error> {
141        Func::expect_no_args("ephemeral", ctx, args)?;
142        Ok(Value::Set(ephemeral()))
143    }
144
145    /// Constructs the `ephemeral()` test set. A test set which contains all
146    /// `ephemeral` unit tests.
147    pub fn ephemeral() -> Set<Test> {
148        Set::new(|_, test: &Test| {
149            Ok(test
150                .as_unit_test()
151                .is_some_and(|unit| unit.kind().is_ephemeral()))
152        })
153    }
154
155    /// The constructor function for the test set returned by [`persistent`].
156    pub fn persistent_ctor(
157        ctx: &Context<Test>,
158        args: &[Value<Test>],
159    ) -> Result<Value<Test>, Error> {
160        Func::expect_no_args("persistent", ctx, args)?;
161        Ok(Value::Set(persistent()))
162    }
163
164    /// Constructs the `persistent()` test set. A test set which contains all
165    /// `persistent` unit tests.
166    pub fn persistent() -> Set<Test> {
167        Set::new(|_, test: &Test| {
168            Ok(test
169                .as_unit_test()
170                .is_some_and(|unit| unit.kind().is_persistent()))
171        })
172    }
173}