summaryrefslogtreecommitdiff
path: root/tests/Config.hs
diff options
context:
space:
mode:
Diffstat (limited to 'tests/Config.hs')
-rw-r--r--tests/Config.hs148
1 files changed, 148 insertions, 0 deletions
diff --git a/tests/Config.hs b/tests/Config.hs
new file mode 100644
index 00000000..3dc254a8
--- /dev/null
+++ b/tests/Config.hs
@@ -0,0 +1,148 @@
1{-# LANGUAGE RecordWildCards #-}
2module Config
3 ( -- * Types
4 ClientName
5 , ClientOpts (..)
6 , EnvOpts (..)
7
8 -- * For test suite driver
9 , getOpts
10
11 -- * For item specs
12 , getEnvOpts
13 , getThisOpts
14 , getRemoteOpts
15 , withRemote
16 ) where
17
18import Control.Monad
19import Network
20import Data.Default
21import Data.IORef
22import Data.List as L
23import Data.Maybe
24import Options.Applicative
25import System.Exit
26import System.Environment
27import System.IO.Unsafe
28import Test.Hspec
29
30type ClientName = String
31
32
33instance Read PortNumber where
34 readsPrec = undefined
35
36data ClientOpts = ClientOpts
37 { peerPort :: PortNumber -- tcp port
38 , nodePort :: PortNumber -- udp port
39 }
40
41instance Default ClientOpts where
42 def = ClientOpts
43 { peerPort = 6881
44 , nodePort = 6881
45 }
46
47defRemoteOpts :: ClientOpts
48defRemoteOpts = def
49
50defThisOpts :: ClientOpts
51defThisOpts = def
52 { peerPort = 6882
53 , nodePort = 6882
54 }
55
56clientOptsParser :: Parser ClientOpts
57clientOptsParser = ClientOpts
58 <$> option
59 ( long "peer-port" <> short 'p'
60 <> value 6881 <> showDefault
61 <> metavar "NUM"
62 <> help "port to bind the specified bittorrent client"
63 )
64 <*> option
65 ( long "node-port" <> short 'n'
66 <> value 6881 <> showDefault
67 <> metavar "NUM"
68 <> help "port to bind node of the specified client"
69 )
70
71data EnvOpts = EnvOpts
72 { testClient :: Maybe ClientName
73 , remoteOpts :: ClientOpts
74 , thisOpts :: ClientOpts
75 }
76
77instance Default EnvOpts where
78 def = EnvOpts
79 { testClient = Nothing
80 , remoteOpts = defRemoteOpts
81 , thisOpts = defThisOpts
82 }
83
84findConflicts :: EnvOpts -> [String]
85findConflicts EnvOpts {..}
86 | isNothing testClient = []
87 | peerPort remoteOpts == peerPort thisOpts = ["Peer port the same"]
88 | nodePort remoteOpts == nodePort thisOpts = ["Node port the same"]
89 | otherwise = []
90
91
92envOptsParser :: Parser EnvOpts
93envOptsParser = EnvOpts
94 <$> optional (strOption
95 ( long "bittorrent-client"
96 <> metavar "CLIENT"
97 <> help "torrent client to run"
98 ))
99 <*> clientOptsParser
100 <*> clientOptsParser
101
102envOptsInfo :: ParserInfo EnvOpts
103envOptsInfo = info (helper <*> envOptsParser)
104 ( fullDesc
105 <> progDesc "The bittorrent library testsuite"
106 <> header ""
107 )
108
109-- do not modify this while test suite is running because spec items
110-- can run in parallel
111envOptsRef :: IORef EnvOpts
112envOptsRef = unsafePerformIO (newIORef def)
113
114-- | Should be used from spec items.
115getEnvOpts :: IO EnvOpts
116getEnvOpts = readIORef envOptsRef
117
118getThisOpts :: IO ClientOpts
119getThisOpts = thisOpts <$> getEnvOpts
120
121-- | Return 'Nothing' if remote client is not running.
122getRemoteOpts :: IO (Maybe ClientOpts)
123getRemoteOpts = return Nothing
124
125withRemote :: (ClientOpts -> Expectation) -> Expectation
126withRemote action = do
127 mopts <- getRemoteOpts
128 case mopts of
129 Nothing -> pendingWith "Remote client isn't running"
130 Just opts -> action opts
131
132-- TODO fix EnvOpts parsing
133
134-- | Should be used by test suite driver.
135getOpts :: IO (EnvOpts, [String])
136getOpts = do
137 args <- getArgs
138-- case runParser SkipOpts envOptsParser args) (prefs idm) of
139 case (Right (def, args), ()) of
140 (Left err , _ctx) -> exitFailure
141 (Right (envOpts, hspecOpts), _ctx) -> do
142 let conflicts = findConflicts envOpts
143 unless (L.null conflicts) $ do
144 forM_ conflicts putStrLn
145 exitFailure
146
147 writeIORef envOptsRef envOpts
148 return (envOpts, hspecOpts) \ No newline at end of file