1use crate::{Bench, BenchFnArg, BenchFnNamed};
7use std::sync::Arc;
8
9#[derive(Debug, PartialEq, thiserror::Error)]
11pub enum BenchBuilderError {
12 #[error("Repetitions must be greater than 0.")]
14 ZeroRepetitions,
15
16 #[error("The sizes vector must not be empty.")]
18 NoSizes,
19
20 #[error("The functions vector must not be empty.")]
22 NoFunctions,
23}
24
25pub struct BenchBuilder<'a, T, R> {
27 functions: Vec<BenchFnNamed<'a, T, R>>,
28 argfunc: BenchFnArg<T>,
29 sizes: Vec<usize>,
30 repetitions: usize,
31 parallel: bool,
32 assert_equal: bool,
33}
34
35impl<'a, T, R> BenchBuilder<'a, T, R> {
36 pub fn new(
44 functions: Vec<BenchFnNamed<'a, T, R>>,
45 argfunc: BenchFnArg<T>,
46 sizes: Vec<usize>,
47 ) -> Self {
48 Self {
49 functions,
50 argfunc,
51 sizes,
52 repetitions: 1,
53 parallel: false,
54 assert_equal: false,
55 }
56 }
57
58 pub fn repetitions(mut self, repetitions: usize) -> Self {
66 self.repetitions = repetitions;
67 self
68 }
69
70 pub fn parallel(mut self, parallel: bool) -> Self {
74 self.parallel = parallel;
75 self
76 }
77
78 pub fn assert_equal(mut self, assert_equal: bool) -> Self {
88 self.assert_equal = assert_equal;
89 self
90 }
91
92 pub fn build(self) -> Result<Bench<'a, T, R>, BenchBuilderError> {
94 if self.repetitions == 0 {
95 return Err(BenchBuilderError::ZeroRepetitions);
96 }
97 if self.sizes.is_empty() {
98 return Err(BenchBuilderError::NoSizes);
99 }
100 if self.functions.is_empty() {
101 return Err(BenchBuilderError::NoFunctions);
102 }
103 Ok(Bench {
104 functions: self
105 .functions
106 .into_iter()
107 .map(|(func, name)| (Arc::new(func), name))
108 .collect(),
109 argfunc: Arc::new(self.argfunc),
110 sizes: self.sizes,
111 repetitions: self.repetitions,
112 parallel: self.parallel,
113 assert_equal: self.assert_equal,
114 data: Vec::new(),
115 })
116 }
117}
118
119#[cfg(test)]
120mod tests {
121 use super::*;
122
123 fn dummy_bench_fn(_: usize) -> usize {
124 0
125 }
126
127 fn dummy_arg_fn(size: usize) -> usize {
128 size
129 }
130
131 fn create_mandatory_args() -> (
132 Vec<BenchFnNamed<'static, usize, usize>>,
133 BenchFnArg<usize>,
134 Vec<usize>,
135 ) {
136 let functions: Vec<BenchFnNamed<'static, usize, usize>> =
137 vec![(Box::new(dummy_bench_fn), "Dummy Function")];
138 let argfunc: BenchFnArg<usize> = Box::new(dummy_arg_fn);
139 let sizes = vec![10, 20, 30];
140
141 (functions, argfunc, sizes)
142 }
143
144 #[test]
145 fn test_bench_builder_only_mandatory_args() {
146 let (functions, argfunc, sizes) = create_mandatory_args();
147
148 let builder = BenchBuilder::new(functions, argfunc, sizes);
149 let result = builder.build();
150
151 assert!(result.is_ok());
152 }
153
154 #[test]
155 fn test_setting_repetitions() {
156 let (functions, argfunc, sizes) = create_mandatory_args();
157
158 let builder =
159 BenchBuilder::new(functions, argfunc, sizes).repetitions(8);
160 let bench = builder.build().unwrap();
161
162 assert_eq!(bench.repetitions, 8);
163 }
164
165 #[test]
166 fn test_setting_parallel() {
167 let (functions, argfunc, sizes) = create_mandatory_args();
168
169 let builder =
170 BenchBuilder::new(functions, argfunc, sizes).parallel(true);
171 let bench = builder.build().unwrap();
172
173 assert!(bench.parallel);
174 }
175
176 #[test]
177 fn test_assert_equal() {
178 let (functions, argfunc, sizes) = create_mandatory_args();
179
180 let builder =
181 BenchBuilder::new(functions, argfunc, sizes).assert_equal(true);
182 let bench = builder.build().unwrap();
183
184 assert!(bench.assert_equal);
185 }
186
187 #[test]
188 fn test_zero_repetitions() {
189 let (functions, argfunc, sizes) = create_mandatory_args();
190
191 let builder =
192 BenchBuilder::new(functions, argfunc, sizes).repetitions(0);
193 let result = builder.build();
194
195 assert!(matches!(result, Err(BenchBuilderError::ZeroRepetitions)));
196 }
197
198 #[test]
199 fn test_no_sizes() {
200 let functions: Vec<BenchFnNamed<'static, usize, usize>> =
201 vec![(Box::new(dummy_bench_fn), "Dummy Function")];
202 let argfunc: BenchFnArg<usize> = Box::new(dummy_arg_fn);
203
204 let builder = BenchBuilder::new(functions, argfunc, Vec::new());
205 let result = builder.build();
206
207 assert!(matches!(result, Err(BenchBuilderError::NoSizes)));
208 }
209
210 #[test]
211 fn test_no_functions() {
212 let functions: Vec<BenchFnNamed<'static, usize, usize>> = Vec::new();
213 let argfunc: BenchFnArg<usize> = Box::new(dummy_arg_fn);
214 let sizes = vec![10, 20, 30];
215
216 let builder = BenchBuilder::new(functions, argfunc, sizes);
217 let result = builder.build();
218
219 assert!(matches!(result, Err(BenchBuilderError::NoFunctions)));
220 }
221}