Repository navigation
Expand file tree
/
Copy pathUtils.hs
More file actions
152 lines (127 loc) · 3.81 KB
/
Copy pathUtils.hs
File metadata and controls
152 lines (127 loc) · 3.81 KB
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
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE CPP #-}
-- |
-- Module: Utils
-- Copyright: Copyright © 2014 AlephCloud Systems, Inc.
-- License: MIT
-- Maintainer: Lars Kuhtz <lars@alephcloud.com>
-- Stability: experimental
--
-- Utils for Tests for Haskell AWS bindints
--
module Utils
(
-- * Parameters
testRegion
, testDataPrefix
-- * General Utils
, sshow
, tryT
, retryT
, testData
, evalTestT
, evalTestTM
, eitherTOnceTest0
, eitherTOnceTest1
, eitherTOnceTest2
-- * Generic Tests
, test_jsonRoundtrip
, prop_jsonRoundtrip
) where
import Aws.General
import Control.Concurrent (threadDelay)
import Control.Error
import Control.Monad
import Control.Monad.Identity
import Control.Monad.IO.Class
import Data.Aeson (FromJSON, ToJSON, encode, eitherDecode)
import Data.Monoid
import Data.Proxy
import Data.String
import qualified Data.Text as T
import Data.Typeable
import Test.QuickCheck.Property
import Test.QuickCheck.Monadic
import Test.Tasty
import Test.Tasty.QuickCheck
-- -------------------------------------------------------------------------- --
-- Static Test parameters
--
-- TODO make these configurable
testRegion :: Region
testRegion = UsWest2
-- | This prefix is used for the IDs and names of all entities that are
-- created in the AWS account.
--
testDataPrefix :: IsString a => a
testDataPrefix = "__TEST_AWSHASKELLBINDINGS__"
-- -------------------------------------------------------------------------- --
-- General Utils
tryT :: MonadIO m => IO a -> EitherT T.Text m a
tryT = fmapLT (T.pack . show) . syncIO
testData :: (IsString a, Monoid a) => a -> a
testData a = testDataPrefix <> a
retryT :: MonadIO m => Int -> EitherT T.Text m a -> EitherT T.Text m a
retryT i f = go 1
where
go x
| x >= i = fmapLT (\e -> "error after " <> sshow x <> " retries: " <> e) f
| otherwise = f `catchT` \_ -> do
liftIO $ threadDelay (1000000 * min 60 (2^(x-1)))
go (succ x)
sshow :: (Show a, IsString b) => a -> b
sshow = fromString . show
evalTestTM
:: Functor f
=> String -- ^ test name
-> f (EitherT T.Text IO a) -- ^ test
-> f (PropertyM IO Bool)
evalTestTM name = fmap $
(run . runEitherT) >=> \r -> case r of
Left e ->
fail $ "failed to run test \"" <> name <> "\": " <> show e
Right _ -> return True
evalTestT
:: String -- ^ test name
-> EitherT T.Text IO a -- ^ test
-> PropertyM IO Bool
evalTestT name = runIdentity . evalTestTM name . Identity
eitherTOnceTest0
:: String -- ^ test name
-> EitherT T.Text IO a -- ^ test
-> TestTree
eitherTOnceTest0 name test = testProperty name . once . monadicIO
$ evalTestT name test
eitherTOnceTest1
:: (Arbitrary a, Show a)
=> String -- ^ test name
-> (a -> EitherT T.Text IO b)
-> TestTree
eitherTOnceTest1 name test = testProperty name . once $ monadicIO
. evalTestTM name test
eitherTOnceTest2
:: (Arbitrary a, Show a, Arbitrary b, Show b)
=> String -- ^ test name
-> (a -> b -> EitherT T.Text IO c)
-> TestTree
eitherTOnceTest2 name test = testProperty name . once $ \a b -> monadicIO
$ (evalTestTM name $ uncurry test) (a, b)
-- -------------------------------------------------------------------------- --
-- Generic Tests
test_jsonRoundtrip
:: forall a . (Eq a, Show a, FromJSON a, ToJSON a, Typeable a, Arbitrary a)
=> Proxy a
-> TestTree
test_jsonRoundtrip proxy = testProperty msg (prop_jsonRoundtrip :: a -> Property)
where
msg = "JSON roundtrip for " <> show typ
#if MIN_VERSION_base(4,7,0)
typ = typeRep proxy
#else
typ = typeOf (undefined :: a)
#endif
prop_jsonRoundtrip :: forall a . (Eq a, Show a, FromJSON a, ToJSON a) => a -> Property
prop_jsonRoundtrip a = either (const $ property False) (\(b :: [a]) -> [a] === b) $
eitherDecode $ encode [a]