-
Notifications
You must be signed in to change notification settings - Fork 2
/
Test.hs
151 lines (124 loc) · 6.22 KB
/
Test.hs
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
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE LambdaCase #-}
module Main where
import qualified Data.HashSet as HashSet
import qualified Data.HashMap.Strict as HashMap
import Data.Word (Word64)
import Data.Text
import Control.Concurrent
import Options.Commander
import Control.Monad
import System.Exit
import Control.Exception
import System.Environment (setEnv)
import Data.Maybe
main :: IO ()
main =
rawTest
>> argTest
>> optTest
>> flagTest
>> bigProgTests
>> optDefTest
>> envTest
>> envOptTest
>> envOptDefTest
>> eitherSwitchTest
rawProg :: ProgramT Raw IO Bool
rawProg = raw (pure True)
testMaybeBool :: Maybe Bool -> IO ()
testMaybeBool = maybe exitFailure (cond (pure ()) exitFailure)
testBool :: Bool -> IO ()
testBool = cond (pure ()) exitFailure
rawTest :: IO ()
rawTest = maybe exitFailure (cond (pure ()) exitFailure) =<< runCommanderT (run rawProg) (State mempty mempty mempty)
argProg :: (String -> Bool) -> ProgramT (Arg "arg" String & Raw) IO Bool
argProg prop = arg \a -> raw (pure (prop a))
cond :: x -> x -> Bool -> x
cond x y True = x
cond x y False = y
argTest :: IO ()
argTest = maybe exitFailure (cond (pure ()) exitFailure) =<< runCommanderT (run (argProg (== "hello"))) (State ["hello"] mempty mempty)
optProg :: (Maybe String -> Bool) -> ProgramT (Opt "opt" "opt" String & Raw) IO Bool
optProg prop = opt \o -> raw (pure (prop o))
optTest :: IO ()
optTest = maybe exitFailure (cond (pure ()) exitFailure) =<< runCommanderT (run (optProg (== Just "hello"))) (State mempty (HashMap.fromList [("opt", "hello")]) mempty)
flagProg :: Monad m => ProgramT (Flag "flag" & Raw) m Bool
flagProg = flag (raw . pure)
flagTest :: IO ()
flagTest = maybe exitFailure (cond (pure ()) exitFailure) =<< runCommanderT (run flagProg) (State mempty mempty (HashSet.fromList ["flag"]))
test :: HasProgram p => ProgramT p IO Bool -> State -> IO (Maybe Bool)
test prog state = runCommanderT (logState $ run prog) state
bigProg :: Monad m => ProgramT ("argument" & Arg "arg" String & Flag "flag" & Raw + Opt "opt" "option-test" Word64 & "option" & Raw) m Bool
bigProg = (sub @"argument" $ arg $ \a -> flag $ \f -> raw $ pure $ f && a == "arg") <+> (opt \o -> sub @"option" $ raw $ pure (o == Just 0))
bigProgTests :: IO ()
bigProgTests = do
testMaybeBool =<< test bigProg (State ["argument", "arg"] mempty (HashSet.singleton "flag"))
testMaybeBool =<< test bigProg (State ["option"] (HashMap.fromList [("opt", "0")]) mempty)
testBool =<< isNothing <$> test bigProg (State ["argument"] mempty mempty)
testBool =<< isNothing <$> test bigProg (State ["argument"] (HashMap.fromList [("opt", "option")]) mempty)
testBool =<< isNothing <$> test bigProg (State ["argument"] (HashMap.fromList [("opt", "option")]) (HashSet.singleton "flag"))
testBool =<< (== Just False) <$> test bigProg (State ["option"] (HashMap.fromList [("opt'", "option")]) mempty)
testBool =<< (== Just False) <$> test bigProg (State ["option"] (HashMap.fromList [("opt", "1")]) (HashSet.singleton "flag"))
optDefProg :: (String -> Bool) -> ProgramT (Opt "o" "opt" String & Raw) IO Bool
optDefProg prop = optDef "Default" \o -> raw (pure (prop o))
optDefTest :: IO ()
optDefTest =
parlay (pure ()) exitFailure (== "Default") (State mempty mempty mempty)
>> parlay (pure ()) exitFailure (== "hello") (State mempty (HashMap.fromList [("o", "hello")]) mempty)
>> parlay exitFailure (pure ()) (== "Default0") (State mempty mempty mempty)
>> parlay exitFailure (pure ()) (== "hello0") (State mempty (HashMap.fromList [("o", "hello")]) mempty)
where
parlay y n prop state = maybe exitFailure (cond y n) =<< runCommanderT (run (optDefProg prop)) state
envProg :: (x -> Bool) -> ProgramT (Env 'Required "ONOGOTTAFINDABIGNAME" x & Raw) IO Bool
envProg prop = env \e -> raw (pure (prop e))
envTest :: IO ()
envTest = do
putStrLn "Testing environment variables"
testBool =<< isNothing <$> test (envProg (== ("POOP" :: String))) (State mempty mempty mempty)
setEnv "ONOGOTTAFINDABIGNAME" "POOP"
testMaybeBool =<< test (envProg (== ("POOP" :: String))) (State mempty mempty mempty)
setEnv "ONOGOTTAFINDABIGNAME" "POP"
testMaybeBool =<< fmap not <$> test (envProg (== ("POOP" :: String))) (State mempty mempty mempty)
envOptProg :: (Maybe x -> Bool) -> ProgramT (Env 'Optional "BIGNAME" x & Raw) IO Bool
envOptProg prop = envOpt \e -> raw (pure (prop e))
envOptProg' :: ProgramT (Env 'Optional "BIGNAME" x & Raw) IO (Maybe x)
envOptProg' = envOpt \e -> raw (pure e)
envOptTest :: IO ()
envOptTest = do
putStrLn "Testing optional environment variables"
testMaybeBool =<< test (envOptProg (== (Nothing @Bool))) (State mempty mempty mempty)
setEnv "BIGNAME" "POP"
testMaybeBool =<< fmap not <$> test (envOptProg (== (Just ("POOP" :: String)))) (State mempty mempty mempty)
testMaybeBool =<< test (envOptProg (== (Just ("POP" :: String)))) (State mempty mempty mempty)
envOptDefProg :: x -> (x -> Bool) -> ProgramT (Env 'Optional "CORPUS" x & Raw) IO Bool
envOptDefProg x prop = envOptDef x \e -> raw (pure (prop e))
envOptDefTest :: IO ()
envOptDefTest = do
putStrLn "Testing optional environment variables with hard-coded defaults"
testMaybeBool =<< test (envOptDefProg (10 :: Int) (== 10)) (State mempty mempty mempty)
testMaybeBool =<< fmap not <$> test (envOptDefProg "POP" (== ("POOP" :: String))) (State mempty mempty mempty)
setEnv "CORPUS" "POOP"
testMaybeBool =<< test (envOptDefProg "POP" (== ("POOP" :: String))) (State mempty mempty mempty)
eitherSwitchProg :: (x -> Bool) -> (y -> Bool) -> ProgramT (Arg "xy" (Either x y) & Raw) IO (Either Bool Bool)
eitherSwitchProg xpred ypred = arg \case { Left x -> raw (pure (Left $ xpred x)); Right y -> raw (pure (Right $ ypred y)) }
eitherSwitchTest :: IO ()
eitherSwitchTest = do
let example = eitherSwitchProg (== (10 :: Int)) (== ("Hello" :: String))
let ploof a c = runCommanderT (run example) (State a mempty mempty) >>= c
ploof ["10"] \case
Just (Left True) -> pure ()
_ -> exitFailure
ploof ["Hello"] \case
Just (Right True) -> pure ()
_ -> exitFailure
ploof ["Poop"] \case
Just (Right False) -> pure ()
_ -> exitFailure
ploof [] \case
Nothing -> pure ()
_ -> exitFailure