about summary refs log tree commit diff
path: root/third_party/bazel/rules_haskell/examples/vector/tests/Tests/Bundle.hs
blob: 09368a19997104dd867da3740aefc8d77d1cda58 (plain) (blame)
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
module Tests.Bundle ( tests ) where

import Boilerplater
import Utilities

import qualified Data.Vector.Fusion.Bundle as S

import Test.QuickCheck

import Test.Framework
import Test.Framework.Providers.QuickCheck2

import Text.Show.Functions ()
import Data.List           (foldl', foldl1', unfoldr, find, findIndex)
import System.Random       (Random)

#define COMMON_CONTEXT(a) \
 VANILLA_CONTEXT(a)

#define VANILLA_CONTEXT(a) \
  Eq a,     Show a,     Arbitrary a,     CoArbitrary a,     TestData a,     Model a ~ a,        EqTest a ~ Property

testSanity :: forall v a. (COMMON_CONTEXT(a)) => S.Bundle v a -> [Test]
testSanity _ = [
        testProperty "fromList.toList == id" prop_fromList_toList,
        testProperty "toList.fromList == id" prop_toList_fromList
    ]
  where
    prop_fromList_toList :: P (S.Bundle v a -> S.Bundle v a)
        = (S.fromList . S.toList) `eq` id
    prop_toList_fromList :: P ([a] -> [a])
        = (S.toList . (S.fromList :: [a] -> S.Bundle v a)) `eq` id

testPolymorphicFunctions :: forall v a. (COMMON_CONTEXT(a)) => S.Bundle v a -> [Test]
testPolymorphicFunctions _ = $(testProperties [
        'prop_eq,

        'prop_length, 'prop_null,

        'prop_empty, 'prop_singleton, 'prop_replicate,
        'prop_cons, 'prop_snoc, 'prop_append,

        'prop_head, 'prop_last, 'prop_index,

        'prop_extract, 'prop_init, 'prop_tail, 'prop_take, 'prop_drop,

        'prop_map, 'prop_zipWith, 'prop_zipWith3,
        'prop_filter, 'prop_takeWhile, 'prop_dropWhile,

        'prop_elem, 'prop_notElem,
        'prop_find, 'prop_findIndex,

        'prop_foldl, 'prop_foldl1, 'prop_foldl', 'prop_foldl1',
        'prop_foldr, 'prop_foldr1,

        'prop_prescanl, 'prop_prescanl',
        'prop_postscanl, 'prop_postscanl',
        'prop_scanl, 'prop_scanl', 'prop_scanl1, 'prop_scanl1',

        'prop_concatMap,
        'prop_unfoldr
    ])
  where
    -- Prelude
    prop_eq :: P (S.Bundle v a -> S.Bundle v a -> Bool) = (==) `eq` (==)

    prop_length :: P (S.Bundle v a -> Int)     = S.length `eq` length
    prop_null   :: P (S.Bundle v a -> Bool)    = S.null `eq` null
    prop_empty  :: P (S.Bundle v a)            = S.empty `eq` []
    prop_singleton :: P (a -> S.Bundle v a)    = S.singleton `eq` singleton
    prop_replicate :: P (Int -> a -> S.Bundle v a)
              = (\n _ -> n < 1000) ===> S.replicate `eq` replicate
    prop_cons      :: P (a -> S.Bundle v a -> S.Bundle v a) = S.cons `eq` (:)
    prop_snoc      :: P (S.Bundle v a -> a -> S.Bundle v a) = S.snoc `eq` snoc
    prop_append    :: P (S.Bundle v a -> S.Bundle v a -> S.Bundle v a) = (S.++) `eq` (++)

    prop_head      :: P (S.Bundle v a -> a) = not . S.null ===> S.head `eq` head
    prop_last      :: P (S.Bundle v a -> a) = not . S.null ===> S.last `eq` last
    prop_index        = \xs ->
                        not (S.null xs) ==>
                        forAll (choose (0, S.length xs-1)) $ \i ->
                        unP prop xs i
      where
        prop :: P (S.Bundle v a -> Int -> a) = (S.!!) `eq` (!!)

    prop_extract      = \xs ->
                        forAll (choose (0, S.length xs))     $ \i ->
                        forAll (choose (0, S.length xs - i)) $ \n ->
                        unP prop i n xs
      where
        prop :: P (Int -> Int -> S.Bundle v a -> S.Bundle v a) = S.slice `eq` slice

    prop_tail :: P (S.Bundle v a -> S.Bundle v a) = not . S.null ===> S.tail `eq` tail
    prop_init :: P (S.Bundle v a -> S.Bundle v a) = not . S.null ===> S.init `eq` init
    prop_take :: P (Int -> S.Bundle v a -> S.Bundle v a) = S.take `eq` take
    prop_drop :: P (Int -> S.Bundle v a -> S.Bundle v a) = S.drop `eq` drop

    prop_map :: P ((a -> a) -> S.Bundle v a -> S.Bundle v a) = S.map `eq` map
    prop_zipWith :: P ((a -> a -> a) -> S.Bundle v a -> S.Bundle v a -> S.Bundle v a) = S.zipWith `eq` zipWith
    prop_zipWith3 :: P ((a -> a -> a -> a) -> S.Bundle v a -> S.Bundle v a -> S.Bundle v a -> S.Bundle v a)
             = S.zipWith3 `eq` zipWith3

    prop_filter :: P ((a -> Bool) -> S.Bundle v a -> S.Bundle v a) = S.filter `eq` filter
    prop_takeWhile :: P ((a -> Bool) -> S.Bundle v a -> S.Bundle v a) = S.takeWhile `eq` takeWhile
    prop_dropWhile :: P ((a -> Bool) -> S.Bundle v a -> S.Bundle v a) = S.dropWhile `eq` dropWhile

    prop_elem    :: P (a -> S.Bundle v a -> Bool) = S.elem `eq` elem
    prop_notElem :: P (a -> S.Bundle v a -> Bool) = S.notElem `eq` notElem
    prop_find    :: P ((a -> Bool) -> S.Bundle v a -> Maybe a) = S.find `eq` find
    prop_findIndex :: P ((a -> Bool) -> S.Bundle v a -> Maybe Int)
      = S.findIndex `eq` findIndex

    prop_foldl :: P ((a -> a -> a) -> a -> S.Bundle v a -> a) = S.foldl `eq` foldl
    prop_foldl1 :: P ((a -> a -> a) -> S.Bundle v a -> a)     = notNullS2 ===>
                        S.foldl1 `eq` foldl1
    prop_foldl' :: P ((a -> a -> a) -> a -> S.Bundle v a -> a) = S.foldl' `eq` foldl'
    prop_foldl1' :: P ((a -> a -> a) -> S.Bundle v a -> a)     = notNullS2 ===>
                        S.foldl1' `eq` foldl1'
    prop_foldr :: P ((a -> a -> a) -> a -> S.Bundle v a -> a) = S.foldr `eq` foldr
    prop_foldr1 :: P ((a -> a -> a) -> S.Bundle v a -> a)     = notNullS2 ===>
                        S.foldr1 `eq` foldr1

    prop_prescanl :: P ((a -> a -> a) -> a -> S.Bundle v a -> S.Bundle v a)
                = S.prescanl `eq` prescanl
    prop_prescanl' :: P ((a -> a -> a) -> a -> S.Bundle v a -> S.Bundle v a)
                = S.prescanl' `eq` prescanl
    prop_postscanl :: P ((a -> a -> a) -> a -> S.Bundle v a -> S.Bundle v a)
                = S.postscanl `eq` postscanl
    prop_postscanl' :: P ((a -> a -> a) -> a -> S.Bundle v a -> S.Bundle v a)
                = S.postscanl' `eq` postscanl
    prop_scanl :: P ((a -> a -> a) -> a -> S.Bundle v a -> S.Bundle v a)
                = S.scanl `eq` scanl
    prop_scanl' :: P ((a -> a -> a) -> a -> S.Bundle v a -> S.Bundle v a)
               = S.scanl' `eq` scanl
    prop_scanl1 :: P ((a -> a -> a) -> S.Bundle v a -> S.Bundle v a) = notNullS2 ===>
                 S.scanl1 `eq` scanl1
    prop_scanl1' :: P ((a -> a -> a) -> S.Bundle v a -> S.Bundle v a) = notNullS2 ===>
                 S.scanl1' `eq` scanl1
 
    prop_concatMap    = forAll arbitrary $ \xs ->
                        forAll (sized (\n -> resize (n `div` S.length xs) arbitrary)) $ \f -> unP prop f xs
      where
        prop :: P ((a -> S.Bundle v a) -> S.Bundle v a -> S.Bundle v a) = S.concatMap `eq` concatMap

    limitUnfolds f (theirs, ours) | ours >= 0
                                  , Just (out, theirs') <- f theirs = Just (out, (theirs', ours - 1))
                                  | otherwise                       = Nothing
    prop_unfoldr :: P (Int -> (Int -> Maybe (a,Int)) -> Int -> S.Bundle v a)
         = (\n f a -> S.unfoldr (limitUnfolds f) (a, n))
           `eq` (\n f a -> unfoldr (limitUnfolds f) (a, n))

testBoolFunctions :: forall v. S.Bundle v Bool -> [Test]
testBoolFunctions _ = $(testProperties ['prop_and, 'prop_or ])
  where
    prop_and :: P (S.Bundle v Bool -> Bool) = S.and `eq` and
    prop_or  :: P (S.Bundle v Bool -> Bool) = S.or `eq` or

testBundleFunctions = testSanity (undefined :: S.Bundle v Int)
                      ++ testPolymorphicFunctions (undefined :: S.Bundle v Int)
                      ++ testBoolFunctions (undefined :: S.Bundle v Bool)

tests = [ testGroup "Data.Vector.Fusion.Bundle" testBundleFunctions ]