Skip to content

Commit 67558d6

Browse files
committed
Work in progress on property-based tests
1 parent dc50f42 commit 67558d6

File tree

1 file changed

+141
-3
lines changed

1 file changed

+141
-3
lines changed
Lines changed: 141 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
import Linleios
2+
import LSpec
23
import Std.Data.HashMap
34

5+
open LSpec
46
open Std.HashMap (singleton_eq_insert)
57

68

9+
-- Lemmas, in lieu of tests
10+
711
/--
812
The genesis state starts with zero counts.
913
-/
@@ -14,11 +18,145 @@ theorem genesis : (default : State).clock = 0 ∧ (default : State).rbCount = 0
1418
rfl
1519
rfl
1620

17-
/-
18-
The initial probability is unity.
21+
22+
-- Generators
23+
24+
structure RangedNat (lo hi : Nat) where
25+
value: Nat
26+
deriving Repr
27+
28+
instance {lo hi : Nat} : SlimCheck.Shrinkable (RangedNat lo hi) where
29+
shrink _ := []
30+
31+
instance {lo hi : Nat} : SlimCheck.SampleableExt (RangedNat lo hi) :=
32+
SlimCheck.SampleableExt.mkSelfContained $
33+
RangedNat.mk <$> SlimCheck.Gen.choose Nat lo hi
34+
35+
instance : SlimCheck.Random Float where
36+
randomR lo hi :=
37+
do
38+
let res := 1000
39+
let lo' := (lo * res).ceil.toUInt16.toNat
40+
let hi' := (hi * res).floor.toUInt16.toNat
41+
let i ← SlimCheck.Random.randomR lo' hi'
42+
pure $ i.toFloat / res
43+
44+
structure RangedFloat (lo hi : Float) where
45+
value: Float
46+
deriving Repr
47+
48+
instance {lo hi : Float} : SlimCheck.Shrinkable (RangedFloat lo hi) where
49+
shrink _ := []
50+
51+
instance {lo hi : Float} : SlimCheck.SampleableExt (RangedFloat lo hi) :=
52+
SlimCheck.SampleableExt.mkSelfContained $
53+
RangedFloat.mk <$> SlimCheck.Gen.choose Float lo hi
54+
55+
instance : SlimCheck.Shrinkable Environment where
56+
shrink _ := []
57+
58+
instance : SlimCheck.SampleableExt Environment :=
59+
SlimCheck.SampleableExt.mkSelfContained $
60+
do
61+
let Lheader : Nat ← SlimCheck.Gen.choose Nat 1 3
62+
let Lvote ← SlimCheck.Gen.choose Nat 2 6
63+
let Ldiff ← SlimCheck.Gen.choose Nat 0 8
64+
let activeSlotCoefficient : Float ← SlimCheck.Gen.choose Float 0.01 0.05
65+
let committeeSize ← SlimCheck.Gen.choose Nat 100 800
66+
let τ ← SlimCheck.Gen.choose Float 0.51 0.99
67+
let pRbHeaderArrives ← SlimCheck.Gen.choose Float 0.90 1.00
68+
let pEbValidates ← SlimCheck.Gen.choose Float 0.85 1.00
69+
let pEbUnvalidated ← SlimCheck.Gen.choose Float 0.00 0.15
70+
let fAdversary ← SlimCheck.Gen.choose Float 0.00 0.49
71+
pure $
72+
makeEnvironment
73+
Lheader Lvote Ldiff
74+
activeSlotCoefficient
75+
committeeSize.toFloat τ
76+
pRbHeaderArrives pEbValidates pEbUnvalidated
77+
fAdversary
78+
79+
instance : SlimCheck.Shrinkable State where
80+
shrink _ := []
81+
82+
instance : SlimCheck.SampleableExt State :=
83+
SlimCheck.SampleableExt.mkSelfContained $
84+
do
85+
let clock ← SlimCheck.Gen.choose Nat 0 1000
86+
let rbCount ← SlimCheck.Gen.choose Nat 0 clock
87+
let ebCount ← SlimCheck.Gen.choose Nat 0 rbCount
88+
let hasRb ← SlimCheck.Gen.chooseAny Bool
89+
let canCertify ← Bool.and hasRb <$> SlimCheck.Gen.chooseAny Bool
90+
pure $ State.mk clock rbCount ebCount hasRb canCertify
91+
92+
93+
-- Property-based tests.
94+
95+
/--
96+
Tolerance for floating-point operations.
1997
-/
20-
#guard totalProbability (default : Probabilities) == 1
98+
private def ε := 1e-6
2199

100+
/--
101+
Check that a probability is close to unity.
102+
-/
103+
private def nearUnity (x : Float) : Bool := (x - 1).abs < ε
22104

105+
/--
106+
Check that the total outcome is near unity.
107+
-/
108+
private def outcomeNearUnity (os : Outcomes) : Bool :=
109+
nearUnity $ os.foldl (fun acc sp ↦ acc + sp.snd) 0
110+
111+
#lspec
112+
group "Probabilities" (
113+
test "Initial probability is unity" (
114+
totalProbability (default : Probabilities) == 1
115+
)
116+
)
117+
$ group "Stake distribution" (
118+
check "Stake fractions are positive" (
119+
∀ nPools : RangedNat 500 5000,
120+
((stakeDistribution nPools.value).map (fun x ↦ decide $ x > 0)).and
121+
)
122+
$ check "Stake fractions sum to unity" (
123+
∀ nPools : RangedNat 500 5000,
124+
(nearUnity $ (stakeDistribution nPools.value).sum)
125+
)
126+
)
127+
$ group "Quorum" (
128+
check "All voters vote and all votes are received" (
129+
∀ τ : RangedFloat 1 999,
130+
∀ committeeSize : RangedNat 100 nPools,
131+
(nearUnity $ pQuorum 1 committeeSize.value.toFloat τ.value)
132+
)
133+
)
134+
$ group "Conservation of probability" (
135+
check "Forging RB" (
136+
∀ env : Environment,
137+
∀ state : State,
138+
(outcomeNearUnity $ @forgeRb env state)
139+
)
140+
$ check "Certifying" (
141+
∀ env : Environment,
142+
∀ state : State,
143+
(outcomeNearUnity $ @certify env state)
144+
)
145+
$ check "Forging EB" (
146+
∀ env : Environment,
147+
∀ state : State,
148+
(outcomeNearUnity $ @forgeEb env state)
149+
)
150+
$ check "Voting" (
151+
∀ env : Environment,
152+
∀ state : State,
153+
(outcomeNearUnity $ @vote env state)
154+
)
155+
)
156+
157+
158+
/--
159+
Testing is done elsewhere in this file.
160+
-/
23161
def main : IO Unit :=
24162
pure ()

0 commit comments

Comments
 (0)