Skip to content

Commit 627bdcb

Browse files
Fix options parse error code (#15)
# Description Closes #13 `BadUsage` is used in `parseOptions` to produce the correct exit code on parse failure. Added documentation to `ExitStatus` and `StatusFlag`. These types now live in the own `ExitCodes` module. --------- Co-authored-by: Sandy Maguire <sandy@sandymaguire.me>
1 parent 32cdf65 commit 627bdcb

File tree

4 files changed

+85
-36
lines changed

4 files changed

+85
-36
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{-# LANGUAGE LambdaCase #-}
2+
{-# LANGUAGE PatternSynonyms #-}
3+
{-# LANGUAGE ViewPatterns #-}
4+
5+
-- | Custom exit codes to implement the shrinking logic externally.
6+
module ExitCodes (ExitStatus (.., Success), StatusFlag (..), exitWithStatus) where
7+
8+
import Data.Bits (Ior (..))
9+
import Data.Set (Set)
10+
import System.Exit (ExitCode (..), exitWith)
11+
12+
-- | Exit statuses for the test runner. 'Success' is represented
13+
-- by an empty set of 'StatusFlags'.
14+
data ExitStatus = InternalError | BadUsage | Flags (Set StatusFlag)
15+
16+
pattern Success :: ExitStatus
17+
pattern Success <- Flags (null -> True)
18+
where
19+
Success = Flags mempty
20+
21+
-- | A 'ContinueShrinking' flag is returned whenever the 'TestFailed' or got
22+
-- 'Success' with a non-empty shrink index as input, unless no more shrinking
23+
-- on the input is possible. It is intended to signal the user to manually
24+
-- /pump/ the shrinker.
25+
data StatusFlag = TestFailed | ContinueShrinking deriving (Eq, Ord)
26+
27+
exitWithStatus :: ExitStatus -> IO a
28+
exitWithStatus = exitWith . \case
29+
Success -> ExitSuccess
30+
InternalError -> ExitFailure 1
31+
BadUsage -> ExitFailure 2
32+
-- Flags are combined using bit-wise OR.
33+
Flags flags -> ExitFailure $ getIor $ foldMap flagToCode flags
34+
where
35+
flagToCode :: StatusFlag -> Ior Int
36+
flagToCode = Ior . \case
37+
TestFailed -> 4
38+
ContinueShrinking -> 8

ouroboros-consensus-diffusion/app/conformance-test-runner/Main.hs

Lines changed: 4 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,14 @@
1-
{-# LANGUAGE LambdaCase #-}
2-
{-# LANGUAGE PatternSynonyms #-}
3-
{-# LANGUAGE ViewPatterns #-}
4-
51
module Main (main) where
62

73
import Data.Aeson (encode, throwDecode)
8-
import Data.Bits (Ior (..))
94
import qualified Data.ByteString.Lazy.Char8 as BSL8
105
import Data.Coerce
116
import Data.Foldable
127
import Data.Map (Map)
138
import qualified Data.Map as M
14-
import Data.Set (Set)
159
import Data.Traversable
1610
import qualified Network.Socket as Socket
17-
import Options
18-
( Options (..)
19-
, execParser
20-
, options
21-
)
11+
import Options (Options (..), parseOptions)
2212
import Ouroboros.Consensus.Util.IOLike
2313
import Ouroboros.Network.Diffusion.Topology
2414
( LocalRootPeersGroup (..)
@@ -32,31 +22,10 @@ import Ouroboros.Network.PeerSelection (PeerAdvertise (..), PortNumber)
3222
import Ouroboros.Network.PeerSelection.LedgerPeers (RelayAccessPoint (..), UseLedgerPeers (..))
3323
import Ouroboros.Network.PeerSelection.State.LocalRootPeers (HotValency (..), WarmValency (..))
3424
import Server (run)
35-
import System.Exit (ExitCode (..))
25+
import System.Environment (getArgs)
3626
import Test.Consensus.PointSchedule (PointSchedule (..))
3727
import Test.Consensus.PointSchedule.Peers (PeerId (..), Peers (Peers), getPeerIds)
3828

39-
data ExitStatus = InternalError | BadUsage | Flags (Set StatusFlag)
40-
41-
pattern Success :: ExitStatus
42-
pattern Success <- Flags (null -> True)
43-
where
44-
Success = Flags mempty
45-
46-
data StatusFlag = TestFailed | ContinueShrinking deriving (Eq, Ord)
47-
48-
exitStatusToCode :: ExitStatus -> ExitCode
49-
exitStatusToCode = \case
50-
Success -> ExitSuccess
51-
InternalError -> ExitFailure 1
52-
BadUsage -> ExitFailure 2
53-
Flags flags -> ExitFailure $ getIor $ foldMap flagToCode flags
54-
where
55-
flagToCode :: StatusFlag -> Ior Int
56-
flagToCode = \case
57-
TestFailed -> Ior 4
58-
ContinueShrinking -> Ior 8
59-
6029
testPointSchedule :: PointSchedule blk
6130
testPointSchedule =
6231
PointSchedule
@@ -101,7 +70,8 @@ makeTopology ports =
10170

10271
main :: IO ()
10372
main = do
104-
opts <- execParser options
73+
args <- getArgs
74+
opts <- parseOptions args
10575
contents <- BSL8.readFile (optTestFile opts)
10676
pointSchedule <- throwDecode contents :: IO (PointSchedule Bool)
10777
let simPeerMap = buildPeerMap (optPort opts) pointSchedule

ouroboros-consensus-diffusion/app/conformance-test-runner/Options.hs

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,36 @@
22
{-# LANGUAGE RecordWildCards #-}
33

44
-- | Command line argument parser for the test runner.
5-
module Options (execParser, options, Options (..)) where
5+
module Options (parseOptions, Options (..)) where
66

7+
import ExitCodes
78
import Options.Applicative
9+
( CompletionResult (execCompletion)
10+
, Parser
11+
, ParserInfo
12+
, ParserResult (CompletionInvoked, Failure)
13+
, auto
14+
, defaultPrefs
15+
, execParserPure
16+
, fullDesc
17+
, header
18+
, help
19+
, helper
20+
, info
21+
, long
22+
, metavar
23+
, option
24+
, progDesc
25+
, renderFailure
26+
, short
27+
, strArgument
28+
, strOption
29+
, value
30+
, (<**>)
31+
)
32+
import qualified Options.Applicative as O
833
import Ouroboros.Network.PeerSelection (PortNumber)
34+
import System.IO (hPutStrLn, stderr)
935

1036
data Options = Options
1137
{ optTestFile :: FilePath
@@ -31,7 +57,7 @@ options =
3157

3258
optsP :: Parser Options
3359
optsP = do
34-
optTestFile <- argument auto (metavar "TEST_FILE")
60+
optTestFile <- strArgument $ metavar "TEST_FILE"
3561
optOutputTopologyFile <-
3662
strOption
3763
( mconcat
@@ -54,3 +80,17 @@ optsP = do
5480
]
5581
)
5682
pure Options{..}
83+
84+
parseOptions :: [String] -> IO (Options)
85+
parseOptions args =
86+
case execParserPure defaultPrefs options args of
87+
O.Success opts -> pure opts
88+
Failure failure -> do
89+
let (msg, _) = renderFailure failure "conformance-test-runner"
90+
hPutStrLn stderr msg
91+
exitWithStatus BadUsage
92+
CompletionInvoked compl -> do
93+
-- Completion handler
94+
msg <- execCompletion compl "conformance-test-runner"
95+
putStr msg
96+
exitWithStatus Success

ouroboros-consensus-diffusion/ouroboros-consensus-diffusion.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,7 @@ executable conformance-test-runner
334334
hs-source-dirs: app/conformance-test-runner
335335
main-is: Main.hs
336336
other-modules:
337+
ExitCodes
337338
Options
338339
Server
339340
MiniProtocols

0 commit comments

Comments
 (0)