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