Skip to content
This repository was archived by the owner on Jan 26, 2025. It is now read-only.

Commit bc037c3

Browse files
committed
lib: Stabilize a subset of the test_set API
This stabilizes most of the `eval` mdoule and some shared types between that and `parse`, but not `parse` itself because the internal generated `Rule` type must be kept out of the public API. This also fixes parts of the CLI where the lack of this API made it impossible or hard to correctly handle tests like in update which need the additional persistence constraint or in general when tests are passed as literal identifiers. Closes #78.
1 parent 773e5a2 commit bc037c3

File tree

17 files changed

+604
-514
lines changed

17 files changed

+604
-514
lines changed

crates/typst-test-lib/src/test/suite.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ mod tests {
185185
use super::*;
186186
use crate::_dev;
187187
use crate::test::{Annotation, Kind};
188+
use crate::test_set::eval;
188189

189190
#[test]
190191
fn test_collect() {
@@ -212,7 +213,11 @@ mod tests {
212213
},
213214
|root| {
214215
let paths = Paths::new(root, None);
215-
let suite = Suite::collect(&paths, &TestSet::all()).unwrap();
216+
let suite = Suite::collect(
217+
&paths,
218+
&TestSet::new(eval::Context::empty(), eval::Set::built_in_all()),
219+
)
220+
.unwrap();
216221

217222
let tests = [
218223
("compile-only", Kind::CompileOnly, eco_vec![]),

crates/typst-test-lib/src/test_set/eval/func.rs

Lines changed: 105 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
use std::fmt::{self, Debug};
22
use std::sync::Arc;
33

4-
use super::value::TryFromValue;
5-
use super::{Context, Error, Set, Value};
4+
use ecow::eco_vec;
5+
6+
use super::{Context, Error, Set, TryFromValue, Type, Value};
67

78
/// The backing implementation for a [`Func`].
89
type FuncImpl = Arc<dyn Fn(&Context, &[Value]) -> Result<Value, Error>>;
@@ -35,150 +36,167 @@ impl Debug for Func {
3536
impl Func {
3637
/// Constructor for [`Set::built_in_all`].
3738
pub fn built_in_all(ctx: &Context, args: &[Value]) -> Result<Value, Error> {
38-
expect_no_args("all", ctx, args)?;
39+
Self::expect_no_args("all", ctx, args)?;
3940
Ok(Value::Set(Set::built_in_all()))
4041
}
4142

4243
/// Constructor for [`Set::built_in_none`].
4344
pub fn built_in_none(ctx: &Context, args: &[Value]) -> Result<Value, Error> {
44-
expect_no_args("none", ctx, args)?;
45+
Self::expect_no_args("none", ctx, args)?;
4546
Ok(Value::Set(Set::built_in_none()))
4647
}
4748

4849
/// Constructor for [`Set::built_in_skip`].
4950
pub fn built_in_skip(ctx: &Context, args: &[Value]) -> Result<Value, Error> {
50-
expect_no_args("skip", ctx, args)?;
51+
Self::expect_no_args("skip", ctx, args)?;
5152
Ok(Value::Set(Set::built_in_skip()))
5253
}
5354

5455
/// Constructor for [`Set::built_in_compile_only`].
5556
pub fn built_in_compile_only(ctx: &Context, args: &[Value]) -> Result<Value, Error> {
56-
expect_no_args("compile-only", ctx, args)?;
57+
Self::expect_no_args("compile-only", ctx, args)?;
5758
Ok(Value::Set(Set::built_in_compile_only()))
5859
}
5960

6061
/// Constructor for [`Set::built_in_ephemeral`].
6162
pub fn built_in_ephemeral(ctx: &Context, args: &[Value]) -> Result<Value, Error> {
62-
expect_no_args("ephemeral", ctx, args)?;
63+
Self::expect_no_args("ephemeral", ctx, args)?;
6364
Ok(Value::Set(Set::built_in_ephemeral()))
6465
}
6566

6667
/// Constructor for [`Set::built_in_persistent`].
6768
pub fn built_in_persistent(ctx: &Context, args: &[Value]) -> Result<Value, Error> {
68-
expect_no_args("persistent", ctx, args)?;
69+
Self::expect_no_args("persistent", ctx, args)?;
6970
Ok(Value::Set(Set::built_in_persistent()))
7071
}
7172
}
7273

73-
/// Ensure there are no args.
74-
pub fn expect_no_args(id: &str, _ctx: &Context, args: &[Value]) -> Result<(), Error> {
75-
if args.is_empty() {
76-
Ok(())
77-
} else {
78-
Err(Error::InvalidArgumentCount {
79-
func: id.into(),
80-
expected: 0,
81-
is_min: false,
82-
found: args.len(),
83-
})
74+
impl Func {
75+
/// Ensure there are no args.
76+
pub fn expect_no_args(id: &str, _ctx: &Context, args: &[Value]) -> Result<(), Error> {
77+
if args.is_empty() {
78+
Ok(())
79+
} else {
80+
Err(Error::InvalidArgumentCount {
81+
func: id.into(),
82+
expected: 0,
83+
is_min: false,
84+
found: args.len(),
85+
})
86+
}
8487
}
85-
}
8688

87-
// TODO(tinger): see test_set module todo
88-
89-
/// Extract an exact number of values from the given arguments. Validates the
90-
/// types of all arguments.
91-
#[allow(dead_code)]
92-
pub fn expect_args_exact<T: TryFromValue + Debug, const N: usize>(
93-
func: &str,
94-
_ctx: &Context,
95-
args: &[Value],
96-
) -> Result<[T; N], Error> {
97-
if args.len() < N {
98-
return Err(Error::InvalidArgumentCount {
99-
func: func.into(),
100-
expected: N,
101-
is_min: false,
102-
found: args.len(),
103-
});
89+
/// Extract an exact number of values from the given arguments. Validates the
90+
/// types of all arguments.
91+
pub fn expect_args_exact<T: TryFromValue + Debug, const N: usize>(
92+
func: &str,
93+
_ctx: &Context,
94+
args: &[Value],
95+
) -> Result<[T; N], Error> {
96+
if args.len() < N {
97+
return Err(Error::InvalidArgumentCount {
98+
func: func.into(),
99+
expected: N,
100+
is_min: false,
101+
found: args.len(),
102+
});
103+
}
104+
105+
Ok(args
106+
.iter()
107+
.take(N)
108+
.map(T::try_from_value)
109+
.collect::<Result<Vec<_>, _>>()?
110+
.try_into()
111+
.expect("we checked both min and max of the args"))
104112
}
105113

106-
Ok(args
107-
.iter()
108-
.take(N)
109-
.map(T::try_from_value)
110-
.collect::<Result<Vec<_>, _>>()?
111-
.try_into()
112-
.expect("we checked both min and max of the args"))
114+
/// Extract a variadic number of values with a minimum amount given arguments.
115+
/// Validates the types of all arguments.
116+
pub fn expect_args_min<T: TryFromValue + Debug, const N: usize>(
117+
func: &str,
118+
_ctx: &Context,
119+
args: &[Value],
120+
) -> Result<([T; N], Vec<T>), Error> {
121+
if args.len() < N {
122+
return Err(Error::InvalidArgumentCount {
123+
func: func.into(),
124+
expected: N,
125+
is_min: true,
126+
found: args.len(),
127+
});
128+
}
129+
130+
let min = args
131+
.iter()
132+
.take(N)
133+
.map(T::try_from_value)
134+
.collect::<Result<Vec<_>, _>>()?
135+
.try_into()
136+
.expect("we checked both min and max of the args");
137+
138+
Ok((
139+
min,
140+
args[N..]
141+
.iter()
142+
.map(T::try_from_value)
143+
.collect::<Result<_, _>>()?,
144+
))
145+
}
113146
}
114147

115-
/// Extract a variadic number of values with a minimum amount given arguments.
116-
/// Validates the types of all arguments.
117-
#[allow(dead_code)]
118-
pub fn expect_args_min<T: TryFromValue + Debug, const N: usize>(
119-
func: &str,
120-
_ctx: &Context,
121-
args: &[Value],
122-
) -> Result<([T; N], Vec<T>), Error> {
123-
if args.len() < N {
124-
return Err(Error::InvalidArgumentCount {
125-
func: func.into(),
126-
expected: N,
127-
is_min: true,
128-
found: args.len(),
129-
});
148+
impl TryFromValue for Func {
149+
fn try_from_value(value: &Value) -> Result<Self, Error> {
150+
Ok(match value {
151+
Value::Func(set) => set.clone(),
152+
_ => {
153+
return Err(Error::TypeMismatch {
154+
expected: eco_vec![Type::Func],
155+
found: value.as_type(),
156+
})
157+
}
158+
})
130159
}
131-
132-
let min = args
133-
.iter()
134-
.take(N)
135-
.map(T::try_from_value)
136-
.collect::<Result<Vec<_>, _>>()?
137-
.try_into()
138-
.expect("we checked both min and max of the args");
139-
140-
Ok((
141-
min,
142-
args[N..]
143-
.iter()
144-
.map(T::try_from_value)
145-
.collect::<Result<_, _>>()?,
146-
))
147160
}
148161

149162
#[cfg(test)]
150163
mod tests {
151164
use super::*;
152-
use crate::test_set::parse::Num;
153165

154-
const NUM: Num = Num(0);
166+
const NUM: usize = 0;
155167
const VAL: Value = Value::Num(NUM);
156168

157169
#[test]
158170
fn test_expect_args_variadic_min_length() {
159-
let ctx = Context::new();
171+
let ctx = Context::empty();
160172

161173
assert_eq!(
162-
expect_args_min::<Num, 0>("f", &ctx, &[]).unwrap(),
174+
Func::expect_args_min::<usize, 0>("f", &ctx, &[]).unwrap(),
163175
([], vec![]),
164176
);
165-
assert_eq!(expect_args_min("f", &ctx, &[VAL]).unwrap(), ([], vec![NUM]),);
166177
assert_eq!(
167-
expect_args_min("f", &ctx, &[VAL, VAL]).unwrap(),
178+
Func::expect_args_min("f", &ctx, &[VAL]).unwrap(),
179+
([], vec![NUM]),
180+
);
181+
assert_eq!(
182+
Func::expect_args_min("f", &ctx, &[VAL, VAL]).unwrap(),
168183
([], vec![NUM, NUM]),
169184
);
170185

171-
assert!(expect_args_min::<Num, 1>("f", &ctx, &[]).is_err());
172-
assert_eq!(expect_args_min("f", &ctx, &[VAL]).unwrap(), ([NUM], vec![]),);
186+
assert!(Func::expect_args_min::<usize, 1>("f", &ctx, &[]).is_err());
187+
assert_eq!(
188+
Func::expect_args_min("f", &ctx, &[VAL]).unwrap(),
189+
([NUM], vec![]),
190+
);
173191
assert_eq!(
174-
expect_args_min("f", &ctx, &[VAL, VAL]).unwrap(),
192+
Func::expect_args_min("f", &ctx, &[VAL, VAL]).unwrap(),
175193
([NUM], vec![NUM]),
176194
);
177195

178-
assert!(expect_args_min::<Num, 2>("f", &ctx, &[]).is_err());
179-
assert!(expect_args_min::<Num, 2>("f", &ctx, &[VAL]).is_err(),);
196+
assert!(Func::expect_args_min::<usize, 2>("f", &ctx, &[]).is_err());
197+
assert!(Func::expect_args_min::<usize, 2>("f", &ctx, &[VAL]).is_err(),);
180198
assert_eq!(
181-
expect_args_min("f", &ctx, &[VAL, VAL]).unwrap(),
199+
Func::expect_args_min("f", &ctx, &[VAL, VAL]).unwrap(),
182200
([NUM, NUM], vec![]),
183201
);
184202
}

0 commit comments

Comments
 (0)