rune/modules/
test.rs
1use crate as rune;
4use crate::alloc::{try_format, Vec};
5use crate::ast;
6use crate::compile;
7use crate::macros::{quote, FormatArgs, MacroContext, TokenStream};
8use crate::parse::Parser;
9use crate::runtime::Function;
10use crate::{Any, ContextError, Module, T};
11
12#[rune::module(::std::test)]
14pub fn module() -> Result<Module, ContextError> {
15 let mut m = Module::from_meta(self::module_meta)?.with_unique("std::test");
16
17 m.macro_meta(assert)?;
18 m.macro_meta(assert_eq)?;
19 m.macro_meta(assert_ne)?;
20
21 m.ty::<Bencher>()?.docs(docstring! {
22 })?;
26
27 m.function_meta(Bencher::iter)?;
28 Ok(m)
29}
30
31#[derive(Default, Any)]
33#[rune(module = crate, item = ::std::test)]
34pub struct Bencher {
35 fns: Vec<Function>,
36}
37
38impl Bencher {
39 pub fn into_functions(self) -> Vec<Function> {
41 self.fns
42 }
43
44 #[rune::function(vm_result)]
46 fn iter(&mut self, f: Function) {
47 self.fns.try_push(f).vm?;
48 }
49}
50
51#[rune::macro_]
66pub(crate) fn assert(
67 cx: &mut MacroContext<'_, '_, '_>,
68 stream: &TokenStream,
69) -> compile::Result<TokenStream> {
70 use crate as rune;
71
72 let mut p = Parser::from_token_stream(stream, cx.input_span());
73 let expr = p.parse::<ast::Expr>()?;
74
75 let message = if p.parse::<Option<T![,]>>()?.is_some() {
76 p.parse_all::<Option<FormatArgs>>()?
77 } else {
78 None
79 };
80
81 let output = if let Some(message) = &message {
82 let expanded = message.expand(cx)?;
83
84 quote!(if !(#expr) {
85 ::std::panic("assertion failed: " + (#expanded));
86 })
87 } else {
88 let message = try_format!("assertion failed: {}", cx.stringify(&expr)?);
89 let message = cx.lit(&message)?;
90
91 quote!(if !(#expr) {
92 ::std::panic(#message);
93 })
94 };
95
96 Ok(output.into_token_stream(cx)?)
97}
98
99#[rune::macro_]
111pub(crate) fn assert_eq(
112 cx: &mut MacroContext<'_, '_, '_>,
113 stream: &TokenStream,
114) -> compile::Result<TokenStream> {
115 use crate as rune;
116
117 let mut p = Parser::from_token_stream(stream, cx.input_span());
118 let left = p.parse::<ast::Expr>()?;
119 p.parse::<T![,]>()?;
120 let right = p.parse::<ast::Expr>()?;
121
122 let message = if p.parse::<Option<T![,]>>()?.is_some() {
123 p.parse_all::<Option<FormatArgs>>()?
124 } else {
125 None
126 };
127
128 let output = if let Some(message) = &message {
129 let message = message.expand(cx)?;
130
131 quote! {{
132 let left = #left;
133 let right = #right;
134
135 if !(left == right) {
136 let message = #message;
137 message += ::std::fmt::format!("\nleft: {:?}", left);
138 message += ::std::fmt::format!("\nright: {:?}", right);
139 ::std::panic("assertion failed (left == right): " + message);
140 }
141 }}
142 } else {
143 let message = cx.lit("assertion failed (left == right):")?;
144
145 quote! {{
146 let left = #left;
147 let right = #right;
148
149 if !(left == right) {
150 let message = ::std::string::String::from(#message);
151 message += ::std::fmt::format!("\nleft: {:?}", left);
152 message += ::std::fmt::format!("\nright: {:?}", right);
153 ::std::panic(message);
154 }
155 }}
156 };
157
158 Ok(output.into_token_stream(cx)?)
159}
160
161#[rune::macro_]
173pub(crate) fn assert_ne(
174 cx: &mut MacroContext<'_, '_, '_>,
175 stream: &TokenStream,
176) -> compile::Result<TokenStream> {
177 use crate as rune;
178
179 let mut p = Parser::from_token_stream(stream, cx.input_span());
180 let left = p.parse::<ast::Expr>()?;
181 p.parse::<T![,]>()?;
182 let right = p.parse::<ast::Expr>()?;
183
184 let message = if p.parse::<Option<T![,]>>()?.is_some() {
185 p.parse_all::<Option<FormatArgs>>()?
186 } else {
187 None
188 };
189
190 let output = if let Some(message) = &message {
191 let message = message.expand(cx)?;
192
193 quote! {{
194 let left = #left;
195 let right = #right;
196
197 if !(left != right) {
198 let message = #message;
199 message += ::std::fmt::format!("\nleft: {:?}", left);
200 message += ::std::fmt::format!("\nright: {:?}", right);
201 ::std::panic("assertion failed (left != right): " + message);
202 }
203 }}
204 } else {
205 let message = cx.lit("assertion failed (left != right):")?;
206
207 quote! {{
208 let left = #left;
209 let right = #right;
210
211 if !(left != right) {
212 let message = ::std::string::String::from(#message);
213 message += ::std::fmt::format!("\nleft: {:?}", left);
214 message += ::std::fmt::format!("\nright: {:?}", right);
215 ::std::panic(message);
216 }
217 }}
218 };
219
220 Ok(output.into_token_stream(cx)?)
221}