1use fidl_diagnostics_validate::{Action, LazyAction, LinkDisposition, ROOT_ID, Value, ValueType};
6
7pub enum Step {
8    Actions(Vec<Action>),
9    LazyActions(Vec<LazyAction>),
10    ActLazyThreadLocalActions(Vec<LazyAction>),
11    WithMetrics(Vec<Action>, String),
12}
13
14pub struct Trial {
15    pub name: String,
16    pub steps: Vec<Step>,
17}
18
19pub fn real_trials() -> Vec<Trial> {
20    vec![
21        basic_node(),
22        basic_int(),
23        basic_uint(),
24        basic_double(),
25        basic_string(),
26        basic_bytes(),
27        basic_bool(),
28        basic_int_array(),
29        basic_string_array(),
30        basic_uint_array(),
31        basic_double_array(),
32        int_histogram_ops_trial(),
33        uint_histogram_ops_trial(),
34        double_histogram_ops_trial(),
35        deletions_trial(),
36        lazy_nodes_trial(),
37        repeated_names(),
38        act_lazy_thread_local_trial(),
39    ]
40}
41
42fn act_lazy_thread_local_trial() -> Trial {
43    Trial {
44        name: "ActLazyThreadLocal".into(),
45        steps: vec![Step::ActLazyThreadLocalActions(vec![
46            crate::create_lazy_node!(
48                parent: ROOT_ID,
49                id: 1,
50                name: "child",
51                disposition: LinkDisposition::Child,
52                actions: vec![crate::create_bytes_property!(parent: ROOT_ID, id: 1, name: "child_bytes",value: vec!(3u8, 4u8))]
53            ),
54            crate::create_lazy_node!(
55                parent: ROOT_ID,
56                id: 2,
57                name: "child",
58                disposition: LinkDisposition::Child,
59                actions: vec![crate::create_bytes_property!(parent: ROOT_ID, id: 1, name: "child_bytes",value: vec!(3u8, 4u8))]
60            ),
61            crate::delete_lazy_node!(id: 1),
62            crate::delete_lazy_node!(id: 2),
63            crate::create_lazy_node!(
65                parent: ROOT_ID,
66                id: 1,
67                name: "child",
68                disposition: LinkDisposition::Child,
69                actions: vec![crate::create_bytes_property!(parent: ROOT_ID, id: 1, name: "child_bytes_new",value: vec!(1u8, 2u8))]
70            ),
71            crate::delete_lazy_node!(id: 1),
72            crate::create_lazy_node!(
74                parent: ROOT_ID,
75                id: 1,
76                name: "inline_child",
77                disposition: LinkDisposition::Inline,
78                actions: vec![crate::create_bytes_property!(parent: ROOT_ID, id: 1, name: "inline_child",value: vec!(1u8, 2u8))]
79            ),
80            crate::delete_lazy_node!(id: 1),
81        ])],
82    }
83}
84
85fn basic_node() -> Trial {
86    Trial {
87        name: "Basic Node".into(),
88        steps: vec![Step::Actions(vec![
89            crate::create_node!(parent: ROOT_ID, id: 1, name: "child"),
90            crate::create_node!(parent: 1, id: 2, name: "grandchild"),
91            crate::delete_node!( id: 2),
92            crate::delete_node!( id: 1 ),
93            crate::create_node!(parent: ROOT_ID, id: 1, name: "child"),
95            crate::create_node!(parent: 1, id: 2, name: "grandchild"),
96            crate::delete_node!( id: 1),
97            crate::delete_node!( id: 2 ),
98        ])],
99    }
100}
101
102fn basic_string() -> Trial {
103    Trial {
104        name: "Basic String".into(),
105        steps: vec![Step::Actions(vec![
106            crate::create_string_property!(parent: ROOT_ID, id:1, name: "str", value: "foo"),
107            crate::set_string!(id: 1, value: "bar"),
108            crate::set_string!(id: 1, value: "This Is A Longer String"),
109            crate::set_string!(id: 1, value: "."),
110            crate::set_string!(id: 1, value: ["1234567890"; 300].to_vec().join("")),
112            crate::delete_property!(id: 1),
113        ])],
114    }
115}
116
117fn basic_bytes() -> Trial {
118    Trial {
119        name: "Basic bytes".into(),
120        steps: vec![Step::Actions(vec![
121            crate::create_bytes_property!(parent: ROOT_ID, id: 8, name: "bytes", value: vec![1u8, 2u8]),
122            crate::set_bytes!(id: 8, value: vec![3u8, 4, 5, 6, 7]),
123            crate::set_bytes!(id: 8, value: vec![8u8]),
124            crate::delete_property!(id: 8),
125        ])],
126    }
127}
128
129fn basic_bool() -> Trial {
130    Trial {
131        name: "Basic Bool".into(),
132        steps: vec![Step::Actions(vec![
133            crate::create_bool_property!(parent: ROOT_ID, id: 1, name: "bool", value: true),
134            crate::set_bool!(id: 1, value: false),
135            crate::set_bool!(id: 1, value: true),
136            crate::delete_property!(id: 1),
137        ])],
138    }
139}
140
141fn basic_int() -> Trial {
142    Trial {
143        name: "Basic Int".into(),
144        steps: vec![Step::Actions(vec![
145            crate::create_numeric_property!(parent: ROOT_ID, id: 5, name: "int", value: Value::IntT(10)),
146            crate::set_number!(id: 5, value: Value::IntT(i64::MAX)),
147            crate::subtract_number!(id: 5, value: Value::IntT(3)),
148            crate::set_number!(id: 5, value: Value::IntT(i64::MIN)),
149            crate::add_number!(id: 5, value: Value::IntT(2)),
150            crate::delete_property!(id: 5),
151        ])],
152    }
153}
154
155fn basic_uint() -> Trial {
156    Trial {
157        name: "Basic Uint".into(),
158        steps: vec![Step::Actions(vec![
159            crate::create_numeric_property!(parent: ROOT_ID, id: 5, name: "uint", value: Value::UintT(1)),
160            crate::set_number!(id: 5, value: Value::UintT(u64::MAX)),
161            crate::subtract_number!(id: 5, value: Value::UintT(3)),
162            crate::set_number!(id: 5, value: Value::UintT(0)),
163            crate::add_number!(id: 5, value: Value::UintT(2)),
164            crate::delete_property!(id: 5),
165        ])],
166    }
167}
168
169fn basic_double() -> Trial {
170    Trial {
171        name: "Basic Double".into(),
172        steps: vec![Step::Actions(vec![
173            crate::create_numeric_property!(parent: ROOT_ID, id: 5, name: "double",
174                                     value: Value::DoubleT(1.0)),
175            crate::set_number!(id: 5, value: Value::DoubleT(f64::MAX)),
176            crate::subtract_number!(id: 5, value: Value::DoubleT(f64::MAX/10_f64)),
177            crate::set_number!(id: 5, value: Value::DoubleT(f64::MIN)),
178            crate::add_number!(id: 5, value: Value::DoubleT(f64::MAX / 10_f64)),
179            crate::delete_property!(id: 5),
180        ])],
181    }
182}
183
184fn repeated_names() -> Trial {
185    let mut actions = vec![crate::create_node!(parent: ROOT_ID, id: 1, name: "measurements")];
186
187    for i in 100..120 {
188        actions.push(crate::create_node!(parent: 1, id: i, name: format!("{}", i)));
189        actions.push(crate::create_numeric_property!(parent: i, id: i + 1000, name: "count", value: Value::UintT(i as u64 * 2)));
190        actions.push(crate::create_numeric_property!(parent: i, id: i + 2000, name: "time_spent", value: Value::UintT(i as u64 * 1000 + 10)));
191    }
192
193    Trial {
194        name: "Many repeated names".into(),
195        steps: vec![Step::WithMetrics(actions, "Many repeated names".into())],
196    }
197}
198
199fn array_indexes_to_test() -> Vec<u64> {
200    let mut ret: Vec<u64> = (0..10).collect();
201    ret.push(1000);
202    ret.push(10000);
203    ret.push(u64::MAX);
204    ret
205}
206
207fn basic_int_array() -> Trial {
208    let mut actions =
209        vec![crate::create_array_property!(parent: ROOT_ID, id: 5, name: "int", slots: 5,
210                                       type: ValueType::Int)];
211    for index in array_indexes_to_test().iter() {
212        actions.push(crate::array_add!(id: 5, index: *index, value: Value::IntT(7)));
213        actions.push(crate::array_subtract!(id: 5, index: *index, value: Value::IntT(3)));
214        actions.push(crate::array_set!(id: 5, index: *index, value: Value::IntT(19)));
215    }
216    actions.push(crate::delete_property!(id: 5));
217    Trial { name: "Int Array Ops".into(), steps: vec![Step::Actions(actions)] }
218}
219
220fn basic_string_array() -> Trial {
221    const ID: u32 = 5;
222    let mut actions = vec![
223        crate::create_array_property!(parent: ROOT_ID, id: ID, name: "string", slots: 5, type: ValueType::String),
224    ];
225
226    for index in array_indexes_to_test().iter() {
227        if (*index).is_multiple_of(2) {
228            actions
229            .push(crate::array_set!(id: ID, index: *index, value: Value::StringT(format!("string data {}", *index))));
230        } else if (*index).is_multiple_of(3) {
231            actions.push(
232                crate::array_set!(id: ID, index: *index, value: Value::StringT(String::new())),
233            );
234        } else {
235            actions.push(
236                crate::array_set!(id: ID, index: *index, value: Value::StringT("string data".into())),
237            );
238        }
239    }
240
241    for index in array_indexes_to_test().iter() {
242        if (*index).is_multiple_of(2) {
243            actions
244                .push(crate::array_set!(id: ID, index: *index, value: Value::StringT("".into())));
245        }
246    }
247
248    for index in array_indexes_to_test().iter() {
249        if (*index).is_multiple_of(4) {
250            actions.push(
251                crate::array_set!(id: ID, index: *index, value: Value::StringT(format!("{}", *index))),
252            );
253        }
254    }
255
256    actions.push(crate::delete_property!(id: ID));
257    Trial { name: "String Array Ops".into(), steps: vec![Step::Actions(actions)] }
258}
259
260fn basic_uint_array() -> Trial {
261    let mut actions =
262        vec![crate::create_array_property!(parent: ROOT_ID, id: 6, name: "uint", slots: 5,
263                                       type: ValueType::Uint)];
264    for index in array_indexes_to_test().iter() {
265        actions.push(crate::array_add!(id: 6, index: *index, value: Value::UintT(11)));
266        actions.push(crate::array_subtract!(id: 6, index: *index, value: Value::UintT(3)));
267        actions.push(crate::array_set!(id: 6, index: *index, value: Value::UintT(19)));
268    }
269    actions.push(crate::delete_property!(id: 6));
270    Trial { name: "Unt Array Ops".into(), steps: vec![Step::Actions(actions)] }
271}
272
273fn basic_double_array() -> Trial {
274    let mut actions =
275        vec![crate::create_array_property!(parent: ROOT_ID, id: 4, name: "float", slots: 5,
276                                       type: ValueType::Double)];
277    for index in array_indexes_to_test().iter() {
278        actions.push(crate::array_add!(id: 4, index: *index, value: Value::DoubleT(2.0)));
279        actions.push(crate::array_subtract!(id: 4, index: *index, value: Value::DoubleT(3.5)));
280        actions.push(crate::array_set!(id: 4, index: *index, value: Value::DoubleT(19.0)));
281    }
282    actions.push(crate::delete_property!(id: 4));
283    Trial { name: "Int Array Ops".into(), steps: vec![Step::Actions(actions)] }
284}
285
286fn int_histogram_ops_trial() -> Trial {
287    fn push_ops(actions: &mut Vec<Action>, value: i64) {
288        actions.push(crate::insert!(id: 4, value: Value::IntT(value)));
289        actions.push(crate::insert_multiple!(id: 4, value: Value::IntT(value), count: 3));
290        actions.push(crate::insert!(id: 5, value: Value::IntT(value)));
291        actions.push(crate::insert_multiple!(id: 5, value: Value::IntT(value), count: 3));
292    }
293    let mut actions = vec![
294        crate::create_linear_histogram!(parent: ROOT_ID, id: 4, name: "Lhist", floor: -5,
295                                 step_size: 3, buckets: 3, type: IntT),
296        crate::create_exponential_histogram!(parent: ROOT_ID, id: 5, name: "Ehist", floor: -5,
297                                 initial_step: 2, step_multiplier: 4,
298                                 buckets: 3, type: IntT),
299    ];
300    for value in [i64::MIN, i64::MAX, 0] {
301        push_ops(&mut actions, value);
302    }
303    for value in [-10_i64, -5_i64, 0_i64, 3_i64, 100_i64] {
304        push_ops(&mut actions, value);
305    }
306    actions.push(crate::delete_property!(id: 4));
307    actions.push(crate::delete_property!(id: 5));
308    Trial { name: "Int Histogram Ops".into(), steps: vec![Step::Actions(actions)] }
309}
310
311fn uint_histogram_ops_trial() -> Trial {
312    fn push_ops(actions: &mut Vec<Action>, value: u64) {
313        actions.push(crate::insert!(id: 4, value: Value::UintT(value)));
314        actions.push(crate::insert_multiple!(id: 4, value: Value::UintT(value), count: 3));
315        actions.push(crate::insert!(id: 5, value: Value::UintT(value)));
316        actions.push(crate::insert_multiple!(id: 5, value: Value::UintT(value), count: 3));
317    }
318    let mut actions = vec![
319        crate::create_linear_histogram!(parent: ROOT_ID, id: 4, name: "Lhist", floor: 5,
320                                 step_size: 3, buckets: 3, type: UintT),
321        crate::create_exponential_histogram!(parent: ROOT_ID, id: 5, name: "Ehist", floor: 5,
322                                 initial_step: 2, step_multiplier: 4,
323                                 buckets: 3, type: UintT),
324    ];
325    for value in [u64::MAX, 0] {
326        push_ops(&mut actions, value);
327    }
328    for value in [0_u64, 5_u64, 8_u64, 20u64, 200_u64] {
329        push_ops(&mut actions, value);
330    }
331    actions.push(crate::delete_property!(id: 4));
332    actions.push(crate::delete_property!(id: 5));
333    Trial { name: "Uint Histogram Ops".into(), steps: vec![Step::Actions(actions)] }
334}
335
336fn double_histogram_ops_trial() -> Trial {
337    fn push_ops(actions: &mut Vec<Action>, value: f64) {
338        actions.push(crate::insert!(id: 4, value: Value::DoubleT(value)));
339        actions.push(crate::insert_multiple!(id: 4, value: Value::DoubleT(value), count: 3));
340        actions.push(crate::insert!(id: 5, value: Value::DoubleT(value)));
341        actions.push(crate::insert_multiple!(id: 5, value: Value::DoubleT(value), count: 3));
342    }
343    let mut actions = vec![
344        crate::create_exponential_histogram!(parent: ROOT_ID, id: 5, name: "Ehist",
347                                floor: std::f64::consts::PI, initial_step: 2.0,
348                                step_multiplier: 4.0, buckets: 3, type: DoubleT),
349        crate::create_linear_histogram!(parent: ROOT_ID, id: 4, name: "Lhist", floor: 5.0,
350                                 step_size: 3.0, buckets: 3, type: DoubleT),
351    ];
352    for value in &[f64::MIN, f64::MAX, f64::MIN_POSITIVE, 0.0] {
353        push_ops(&mut actions, *value);
354    }
355    for value in [3.0, 3.15, 5.0, 10.0] {
356        push_ops(&mut actions, value);
357    }
358    actions.push(crate::delete_property!(id: 4));
359    actions.push(crate::delete_property!(id: 5));
360    Trial { name: "Double Histogram Ops".into(), steps: vec![Step::Actions(actions)] }
361}
362
363fn deletions_trial() -> Trial {
364    fn n1() -> Action {
367        crate::create_node!(parent: ROOT_ID, id: 1, name: "root_child")
368    }
369    fn n2() -> Action {
370        crate::create_node!(parent: 1, id: 2, name: "parent")
371    }
372    fn n3() -> Action {
373        crate::create_node!(parent: 2, id: 3, name: "child")
374    }
375    fn p1() -> Action {
376        crate::create_numeric_property!(parent: 1, id: 4, name: "root_int", value: Value::IntT(1))
377    }
378    fn p2() -> Action {
379        crate::create_numeric_property!(parent: 2, id: 5, name: "parent_int", value: Value::IntT(2))
380    }
381    fn p3() -> Action {
382        crate::create_numeric_property!(parent: 3, id: 6, name: "child_int", value: Value::IntT(3))
383    }
384    fn create() -> Vec<Action> {
385        vec![n1(), n2(), n3(), p1(), p2(), p3()]
386    }
387    fn create2() -> Vec<Action> {
388        vec![n1(), p1(), n2(), p2(), n3(), p3()]
389    }
390    fn d1() -> Action {
391        crate::delete_node!(id: 1)
392    }
393    fn d2() -> Action {
394        crate::delete_node!(id: 2)
395    }
396    fn d3() -> Action {
397        crate::delete_node!(id: 3)
398    }
399    fn x1() -> Action {
400        crate::delete_property!(id: 4)
401    }
402    fn x2() -> Action {
403        crate::delete_property!(id: 5)
404    }
405    fn x3() -> Action {
406        crate::delete_property!(id: 6)
407    }
408    let steps = vec![
409        Step::Actions(create()),
410        Step::Actions(vec![d3(), d2(), d1(), x3(), x2(), x1()]),
411        Step::Actions(create2()),
412        Step::WithMetrics(vec![d1(), d2()], "Delete Except Grandchild".into()),
413        Step::WithMetrics(vec![d3(), x3(), x2(), x1()], "Deleted Grandchild".into()),
414        Step::Actions(create()),
417        Step::Actions(vec![d1(), d2(), d3(), x3(), x2(), x1()]),
418        Step::Actions(create2()),
419        Step::Actions(vec![d1(), x3(), d2(), x1(), d3(), x2()]),
420        Step::Actions(create()),
421        Step::Actions(vec![d1(), x2(), d3(), x3(), d2(), x1()]),
422        Step::Actions(create2()),
423        Step::Actions(vec![x1(), x3(), d2(), d1(), d3(), x2()]),
424        Step::Actions(create()),
425        Step::Actions(vec![d2(), x3(), x2(), x1(), d3(), d1()]),
426        Step::Actions(create2()),
427        Step::Actions(vec![d3(), x3(), d2(), x1(), d1(), x2()]),
428        Step::Actions(create2()),
429        Step::Actions(vec![x3(), d3(), d1(), x1(), d2(), x2()]),
430        Step::WithMetrics(vec![], "Everything should be gone".into()),
431    ];
432    Trial { name: "Delete With Metrics".into(), steps }
433}
434
435fn lazy_nodes_trial() -> Trial {
436    Trial {
437        name: "Lazy Nodes".into(),
438        steps: vec![Step::LazyActions(vec![
439            crate::create_lazy_node!(
441                parent: ROOT_ID,
442                id: 1,
443                name: "child",
444                disposition: LinkDisposition::Child,
445                actions: vec![crate::create_bytes_property!(parent: ROOT_ID, id: 1, name: "child_bytes",value: vec!(3u8, 4u8))]
446            ),
447            crate::create_lazy_node!(
448                parent: ROOT_ID,
449                id: 2,
450                name: "child",
451                disposition: LinkDisposition::Child,
452                actions: vec![crate::create_bytes_property!(parent: ROOT_ID, id: 1, name: "child_bytes",value: vec!(3u8, 4u8))]
453            ),
454            crate::delete_lazy_node!(id: 1),
455            crate::delete_lazy_node!(id: 2),
456            crate::create_lazy_node!(
458                parent: ROOT_ID,
459                id: 1,
460                name: "child",
461                disposition: LinkDisposition::Child,
462                actions: vec![crate::create_bytes_property!(parent: ROOT_ID, id: 1, name: "child_bytes_new",value: vec!(1u8, 2u8))]
463            ),
464            crate::delete_lazy_node!(id: 1),
465            crate::create_lazy_node!(
467                parent: ROOT_ID,
468                id: 1,
469                name: "inline_child",
470                disposition: LinkDisposition::Inline,
471                actions: vec![crate::create_bytes_property!(parent: ROOT_ID, id: 1, name: "inline_child",value: vec!(1u8, 2u8))]
472            ),
473            crate::delete_lazy_node!(id: 1),
474        ])],
475    }
476}
477
478#[cfg(test)]
479pub(crate) mod tests {
480    use super::*;
481
482    pub fn trial_with_action(name: &str, action: Action) -> Trial {
483        Trial { name: name.into(), steps: vec![Step::Actions(vec![action])] }
484    }
485}