1 {-# LANGUAGE TemplateHaskell, FlexibleInstances, TypeSynonymInstances #-}
2 {-# OPTIONS_GHC -fno-warn-orphans #-}
4 {-| Unittests for ganeti-htools.
10 Copyright (C) 2009, 2010, 2011, 2012, 2013 Google Inc.
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful, but
18 WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
29 module Test.Ganeti.BasicTypes (testBasicTypes) where
31 import Test.QuickCheck hiding (Result)
32 import Test.QuickCheck.Function
34 import Control.Applicative
37 import Test.Ganeti.TestHelper
38 import Test.Ganeti.TestCommon
40 import Ganeti.BasicTypes
42 -- Since we actually want to test these, don't tell us not to use them :)
44 {-# ANN module "HLint: ignore Functor law" #-}
45 {-# ANN module "HLint: ignore Monad law, left identity" #-}
46 {-# ANN module "HLint: ignore Monad law, right identity" #-}
47 {-# ANN module "HLint: ignore Use >=>" #-}
48 {-# ANN module "HLint: ignore Use ." #-}
50 -- * Arbitrary instances
52 instance (Arbitrary a) => Arbitrary (Result a) where
53 arbitrary = oneof [ Bad <$> arbitrary
59 -- | Tests the functor identity law:
62 prop_functor_id :: Result Int -> Property
66 -- | Tests the functor composition law:
68 -- > fmap (f . g) == fmap f . fmap g
69 prop_functor_composition :: Result Int
70 -> Fun Int Int -> Fun Int Int -> Property
71 prop_functor_composition ri (Fun _ f) (Fun _ g) =
72 fmap (f . g) ri ==? (fmap f . fmap g) ri
74 -- | Tests the applicative identity law:
76 -- > pure id <*> v = v
77 prop_applicative_identity :: Result Int -> Property
78 prop_applicative_identity v =
81 -- | Tests the applicative composition law:
83 -- > pure (.) <*> u <*> v <*> w = u <*> (v <*> w)
84 prop_applicative_composition :: Result (Fun Int Int)
85 -> Result (Fun Int Int)
88 prop_applicative_composition u v w =
91 in pure (.) <*> u' <*> v' <*> w ==? u' <*> (v' <*> w)
93 -- | Tests the applicative homomorphism law:
95 -- > pure f <*> pure x = pure (f x)
96 prop_applicative_homomorphism :: Fun Int Int -> Int -> Property
97 prop_applicative_homomorphism (Fun _ f) x =
98 ((pure f <*> pure x)::Result Int) ==? pure (f x)
100 -- | Tests the applicative interchange law:
102 -- > u <*> pure y = pure ($ y) <*> u
103 prop_applicative_interchange :: Result (Fun Int Int)
105 prop_applicative_interchange f y =
106 let u = fmap apply f -- need to extract the actual function from Fun
107 in u <*> pure y ==? pure ($ y) <*> u
109 -- | Tests the applicative\/functor correspondence:
111 -- > fmap f x = pure f <*> x
112 prop_applicative_functor :: Fun Int Int -> Result Int -> Property
113 prop_applicative_functor (Fun _ f) x =
114 fmap f x ==? pure f <*> x
116 -- | Tests the applicative\/monad correspondence:
121 prop_applicative_monad :: Int -> Result (Fun Int Int) -> Property
122 prop_applicative_monad v f =
123 let v' = pure v :: Result Int
124 f' = fmap apply f -- need to extract the actual function from Fun
125 in v' ==? return v .&&. (f' <*> v') ==? f' `ap` v'
127 -- | Tests the monad laws:
129 -- > return a >>= k == k a
131 -- > m >>= return == m
133 -- > m >>= (\x -> k x >>= h) == (m >>= k) >>= h
134 prop_monad_laws :: Int -> Result Int
135 -> Fun Int (Result Int)
136 -> Fun Int (Result Int)
138 prop_monad_laws a m (Fun _ k) (Fun _ h) =
140 [ printTestCase "return a >>= k == k a" ((return a >>= k) ==? k a)
141 , printTestCase "m >>= return == m" ((m >>= return) ==? m)
142 , printTestCase "m >>= (\\x -> k x >>= h) == (m >>= k) >>= h)"
143 ((m >>= (\x -> k x >>= h)) ==? ((m >>= k) >>= h))
146 -- | Tests the monad plus laws:
148 -- > mzero >>= f = mzero
150 -- > v >> mzero = mzero
151 prop_monadplus_mzero :: Result Int -> Fun Int (Result Int) -> Property
152 prop_monadplus_mzero v (Fun _ f) =
153 printTestCase "mzero >>= f = mzero" ((mzero >>= f) ==? mzero) .&&.
154 -- FIXME: since we have "many" mzeros, we can't test for equality,
155 -- just that we got back a 'Bad' value; I'm not sure if this means
156 -- our MonadPlus instance is not sound or not...
157 printTestCase "v >> mzero = mzero" (isBad (v >> mzero))
159 testSuite "BasicTypes"
161 , 'prop_functor_composition
162 , 'prop_applicative_identity
163 , 'prop_applicative_composition
164 , 'prop_applicative_homomorphism
165 , 'prop_applicative_interchange
166 , 'prop_applicative_functor
167 , 'prop_applicative_monad
169 , 'prop_monadplus_mzero