-
Notifications
You must be signed in to change notification settings - Fork 2
/
h3spec.hs
135 lines (125 loc) · 3.92 KB
/
h3spec.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
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Control.Monad (when)
import Data.List (foldl', intersperse)
import Data.Version (showVersion)
import qualified Network.HTTP3.Client as H3
import Network.QUIC.Internal
import System.Console.GetOpt
import System.Environment (getArgs, withArgs)
import System.Exit (exitFailure, exitSuccess)
import qualified Test.Hspec.Core.Runner as H
import HTTP3Error
import qualified Paths_h3spec as P
import TransportError
data Options = Options
{ optVersion :: Bool
, optDebugLog :: Bool
, optValidate :: Bool
, optMatch :: [String]
, optSkip :: [String]
, optQLogDir :: Maybe FilePath
, optKeyLogFile :: Maybe FilePath
, optTimeout :: Int
}
deriving (Show)
defaultOptions :: Options
defaultOptions =
Options
{ optVersion = False
, optDebugLog = False
, optValidate = True
, optMatch = []
, optSkip = []
, optQLogDir = Nothing
, optKeyLogFile = Nothing
, optTimeout = 2000 -- 2 milliseconds
}
options :: [OptDescr (Options -> Options)]
options =
[ Option
['v']
["version"]
(NoArg (\o -> o{optVersion = True}))
"Print version"
, Option
['d']
["debug"]
(NoArg (\o -> o{optDebugLog = True}))
"print debug info"
, Option
['m']
["match"]
(ReqArg (\m o -> o{optMatch = m : optMatch o}) "<test case description>")
"Select test cases"
, Option
['s']
["skip"]
(ReqArg (\m o -> o{optSkip = m : optSkip o}) "<test case description>")
"Skip test cases"
, Option
['q']
["qlog-dir"]
(ReqArg (\dir o -> o{optQLogDir = Just dir}) "<dir>")
"directory to store qlog"
, Option
['l']
["key-log-file"]
(ReqArg (\file o -> o{optKeyLogFile = Just file}) "<file>")
"a file to store negotiated secrets"
, Option
['t']
["timeout"]
(ReqArg (\ms o -> o{optTimeout = read ms}) "<milliseconds>")
"timeout for each test case (2000)"
, Option
['n']
["no-validate"]
(NoArg (\o -> o{optValidate = False}))
"no validating server certificates"
]
showUsageAndExit :: String -> IO a
showUsageAndExit msg = do
putStrLn msg
putStrLn $ usageInfo usage options
exitFailure
usage :: String
usage = "Usage: h3spec <host> <port>"
main :: IO ()
main = do
args0 <- getArgs
(opts, args) <- case getOpt Permute options args0 of
(o, n, []) -> return (foldl' (flip id) defaultOptions o, n)
(_, _, errs) -> showUsageAndExit $ concat errs
when (optVersion opts) $ do
putStrLn $ "h3spec " ++ showVersion P.version
exitSuccess
(host, port) <- case args of
[h, p] -> return (h, p)
_ -> showUsageAndExit ""
let cc =
defaultClientConfig
{ ccServerName = host
, ccPortName = port
, ccALPN = \_ -> return $ Just ["h3", "h3-29", "hq-interop", "hq-29"]
, ccDebugLog = optDebugLog opts
, ccQLog = optQLogDir opts
, ccKeyLog = getLogger $ optKeyLogFile opts
, ccValidate = optValidate opts
}
qcArgs0
| null (optMatch opts) = []
| otherwise =
"--match" : (intersperse "--match" $ reverse $ optMatch opts)
qcArgs
| null (optSkip opts) = qcArgs0
| otherwise =
"--skip" : (intersperse "--skip" $ reverse $ optSkip opts)
h3cc = H3.ClientConfig "https" host
ms = optTimeout opts
H.readConfig H.defaultConfig qcArgs
>>= withArgs [] . H.runSpec (transportErrorSpec cc ms >> h3ErrorSpec cc h3cc ms)
>>= H.evaluateSummary
getLogger :: Maybe FilePath -> (String -> IO ())
getLogger Nothing = \_ -> return ()
getLogger (Just file) = \msg -> appendFile file (msg ++ "\n")