-
Notifications
You must be signed in to change notification settings - Fork 30
/
Gen.purs
50 lines (40 loc) · 1.47 KB
/
Gen.purs
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
module Data.Argonaut.Gen where
import Prelude
import Control.Lazy (class Lazy, defer)
import Control.Monad.Gen (class MonadGen)
import Control.Monad.Gen as Gen
import Control.Monad.Rec.Class (class MonadRec)
import Data.Argonaut.Core as J
import Data.Array as A
import Data.NonEmpty ((:|))
import Data.String.Gen (genUnicodeString)
import Foreign.Object as Obj
-- | A generator for `Json` values. Especially useful for writing property-based
-- | tests.
genJson :: forall m. MonadGen m => MonadRec m => Lazy (m J.Json) => m J.Json
genJson = Gen.resize (min 5) $ Gen.sized genJson'
where
genJson' :: Int -> m J.Json
genJson' size
| size > 1 = Gen.resize (_ - 1) (Gen.choose genJArray genJObject)
| otherwise = genLeaf
genLeaf :: m J.Json
genLeaf = Gen.oneOf $ pure J.jsonNull :| [genJBoolean, genJNumber, genJString]
genJArray :: m J.Json
genJArray = J.fromArray <$> Gen.unfoldable (defer \_ -> genJson)
genJObject :: m J.Json
genJObject = A.foldM extendJObj J.jsonEmptyObject =<< Gen.unfoldable genUnicodeString
extendJObj :: J.Json -> String -> m J.Json
extendJObj obj k = do
v <- genJson
pure $
J.caseJsonObject
(J.jsonSingletonObject k v)
(J.fromObject <<< Obj.insert k v)
obj
genJBoolean :: m J.Json
genJBoolean = J.fromBoolean <$> Gen.chooseBool
genJNumber :: m J.Json
genJNumber = J.fromNumber <$> Gen.chooseFloat (-1000000.0) 1000000.0
genJString :: m J.Json
genJString = J.fromString <$> genUnicodeString