snix_eval/value/
arbitrary.rs1use proptest::collection::{btree_map, vec};
4use proptest::{prelude::*, strategy::BoxedStrategy};
5use std::ffi::OsString;
6
7use super::{NixAttrs, NixList, NixString, Value, attrs::AttrsRep};
8
9#[derive(Clone)]
10pub enum Parameters {
11 Strategy(BoxedStrategy<Value>),
12 Parameters {
13 generate_internal_values: bool,
14 generate_functions: bool,
15 generate_nested: bool,
16 },
17}
18
19impl Default for Parameters {
20 fn default() -> Self {
21 Self::Parameters {
22 generate_internal_values: false,
23 generate_functions: false,
24 generate_nested: true,
25 }
26 }
27}
28
29impl Arbitrary for NixAttrs {
30 type Parameters = Parameters;
31 type Strategy = BoxedStrategy<Self>;
32
33 fn arbitrary_with(args: Self::Parameters) -> Self::Strategy {
34 prop_oneof![
35 Just(AttrsRep::Empty.into()),
37 (
39 any_with::<Value>(args.clone()),
40 any_with::<Value>(args.clone())
41 )
42 .prop_map(|(name, value)| AttrsRep::KV { name, value }.into()),
43 btree_map(NixString::arbitrary(), Value::arbitrary_with(args), 0..100).prop_map(
45 |map| AttrsRep::Map {
46 attrs: map.into_iter().collect(),
47 pos: None
48 }
49 .into()
50 )
51 ]
52 .boxed()
53 }
54}
55
56impl Arbitrary for NixList {
57 type Parameters = <Value as Arbitrary>::Parameters;
58 type Strategy = BoxedStrategy<Self>;
59
60 fn arbitrary_with(args: Self::Parameters) -> Self::Strategy {
61 vec(<Value as Arbitrary>::arbitrary_with(args), 0..100)
62 .prop_map(NixList::from)
63 .boxed()
64 }
65}
66
67impl Arbitrary for Value {
68 type Parameters = Parameters;
69 type Strategy = BoxedStrategy<Self>;
70
71 fn arbitrary_with(args: Self::Parameters) -> Self::Strategy {
72 match args {
73 Parameters::Strategy(s) => s,
74 Parameters::Parameters {
75 generate_internal_values,
76 generate_functions,
77 generate_nested,
78 } => {
79 if generate_internal_values || generate_functions {
80 todo!("Generating internal values and functions not implemented yet")
81 } else if generate_nested {
82 non_internal_value().boxed()
83 } else {
84 leaf_value().boxed()
85 }
86 }
87 }
88 }
89}
90
91fn leaf_value() -> impl Strategy<Value = Value> {
92 use Value::*;
93
94 prop_oneof![
95 Just(Null),
96 any::<bool>().prop_map(Bool),
97 any::<i64>().prop_map(Integer),
98 any::<f64>().prop_map(Float),
99 any::<NixString>().prop_map(String),
100 any::<OsString>().prop_map(|s| Path(Box::new(s.into()))),
101 ]
102}
103
104fn non_internal_value() -> impl Strategy<Value = Value> {
105 leaf_value().prop_recursive(3, 5, 5, |inner| {
106 prop_oneof![
107 NixAttrs::arbitrary_with(Parameters::Strategy(inner.clone())).prop_map(Value::attrs),
108 any_with::<NixList>(Parameters::Strategy(inner)).prop_map(Value::List)
109 ]
110 })
111}