Skip to content

Commit 14da19e

Browse files
committed
Add doctestWith / doctestWithResult
1 parent cfa77ba commit 14da19e

File tree

9 files changed

+92
-56
lines changed

9 files changed

+92
-56
lines changed

.ghci

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
:set -DTEST -isrc -itest -packageghc -XHaskell2010
2+
:set -XNamedFieldPuns
3+
:set -XRecordWildCards

doctest.cabal

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ maintainer: Simon Hengel <[email protected]>
1616

1717
github: sol/doctest
1818

19+
default-extensions:
20+
- NamedFieldPuns
21+
- RecordWildCards
22+
1923
extra-source-files:
2024
- example/**/*
2125
- test/parse/**/*

src/Language/Haskell/GhciWrapper.hs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
{-# LANGUAGE RecordWildCards #-}
21
module Language.Haskell.GhciWrapper (
32
Interpreter
43
, Config(..)

src/Options.hs

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
module Options (
44
Result(..)
55
, Run(..)
6+
, Config(..)
7+
, defaultConfig
68
, parseOptions
79
#ifdef TEST
810
, defaultRun
@@ -49,13 +51,25 @@ type Warning = String
4951

5052
data Run = Run {
5153
runWarnings :: [Warning]
52-
, runOptions :: [String]
5354
, runMagicMode :: Bool
54-
, runFastMode :: Bool
55-
, runPreserveIt :: Bool
56-
, runVerbose :: Bool
55+
, runConfig :: Config
5756
} deriving (Eq, Show)
5857

58+
data Config = Config {
59+
ghcOptions :: [String]
60+
, fastMode :: Bool
61+
, preserveIt :: Bool
62+
, verbose :: Bool
63+
} deriving (Eq, Show)
64+
65+
defaultConfig :: Config
66+
defaultConfig = Config {
67+
ghcOptions = []
68+
, fastMode = False
69+
, preserveIt = False
70+
, verbose = False
71+
}
72+
5973
nonInteractiveGhcOptions :: [String]
6074
nonInteractiveGhcOptions = [
6175
"--numeric-version"
@@ -72,30 +86,27 @@ nonInteractiveGhcOptions = [
7286
defaultRun :: Run
7387
defaultRun = Run {
7488
runWarnings = []
75-
, runOptions = []
7689
, runMagicMode = False
77-
, runFastMode = False
78-
, runPreserveIt = False
79-
, runVerbose = False
90+
, runConfig = defaultConfig
8091
}
8192

8293
modifyWarnings :: ([String] -> [String]) -> Run -> Run
8394
modifyWarnings f run = run { runWarnings = f (runWarnings run) }
8495

8596
setOptions :: [String] -> Run -> Run
86-
setOptions opts run = run { runOptions = opts }
97+
setOptions ghcOptions run@Run{..} = run { runConfig = runConfig { ghcOptions } }
8798

8899
setMagicMode :: Bool -> Run -> Run
89100
setMagicMode magic run = run { runMagicMode = magic }
90101

91102
setFastMode :: Bool -> Run -> Run
92-
setFastMode fast run = run { runFastMode = fast }
103+
setFastMode fastMode run@Run{..} = run { runConfig = runConfig { fastMode } }
93104

94105
setPreserveIt :: Bool -> Run -> Run
95-
setPreserveIt preserveIt run = run { runPreserveIt = preserveIt }
106+
setPreserveIt preserveIt run@Run{..} = run { runConfig = runConfig { preserveIt } }
96107

97108
setVerbose :: Bool -> Run -> Run
98-
setVerbose verbose run = run { runVerbose = verbose }
109+
setVerbose verbose run@Run{..} = run { runConfig = runConfig { verbose } }
99110

100111
parseOptions :: [String] -> Result Run
101112
parseOptions args

src/Run.hs

Lines changed: 36 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,25 @@
11
{-# LANGUAGE CPP #-}
22
module Run (
33
doctest
4+
5+
, Config(..)
6+
, defaultConfig
7+
, doctestWith
8+
9+
, Summary(..)
10+
, isSuccess
11+
, evaluateSummary
12+
, doctestWithResult
13+
414
#ifdef TEST
5-
, doctestWithOptions
6-
, Summary
715
, expandDirs
816
#endif
917
) where
1018

1119
import Prelude ()
1220
import Prelude.Compat
1321

14-
import Control.Monad (when, unless)
22+
import Control.Monad
1523
import System.Directory (doesFileExist, doesDirectoryExist, getDirectoryContents)
1624
import System.Environment (getEnvironment)
1725
import System.Exit (exitFailure, exitSuccess)
@@ -32,6 +40,7 @@ import PackageDBs
3240
import Parse
3341
import Options
3442
import Runner
43+
import Location
3544
import qualified Interpreter
3645

3746
-- | Run doctest with given list of arguments.
@@ -51,7 +60,7 @@ doctest :: [String] -> IO ()
5160
doctest args0 = case parseOptions args0 of
5261
ProxyToGhc args -> rawSystem Interpreter.ghc args >>= E.throwIO
5362
Output s -> putStr s
54-
Result (Run warnings args_ magicMode fastMode preserveIt verbose) -> do
63+
Result (Run warnings magicMode config) -> do
5564
mapM_ (hPutStrLn stderr) warnings
5665
hFlush stderr
5766

@@ -60,22 +69,14 @@ doctest args0 = case parseOptions args0 of
6069
hPutStrLn stderr "WARNING: GHC does not support --interactive, skipping tests"
6170
exitSuccess
6271

63-
args <- case magicMode of
64-
False -> return args_
72+
opts <- case magicMode of
73+
False -> return (ghcOptions config)
6574
True -> do
66-
expandedArgs <- concat <$> mapM expandDirs args_
75+
expandedArgs <- concat <$> mapM expandDirs (ghcOptions config)
6776
packageDBArgs <- getPackageDBArgs
6877
addDistArgs <- getAddDistArgs
6978
return (addDistArgs $ packageDBArgs ++ expandedArgs)
70-
71-
r <- doctestWithOptions fastMode preserveIt verbose args `E.catch` \e -> do
72-
case fromException e of
73-
Just (UsageError err) -> do
74-
hPutStrLn stderr ("doctest: " ++ err)
75-
hPutStrLn stderr "Try `doctest --help' for more information."
76-
exitFailure
77-
_ -> E.throwIO e
78-
when (not $ isSuccess r) exitFailure
79+
doctestWith config{ghcOptions = opts}
7980

8081
-- | Expand a reference to a directory to all .hs and .lhs files within it.
8182
expandDirs :: String -> IO [String]
@@ -128,14 +129,26 @@ getAddDistArgs = do
128129
else id) rest
129130
else return id
130131

132+
doctestWith :: Config -> IO ()
133+
doctestWith = doctestWithResult >=> evaluateSummary
134+
131135
isSuccess :: Summary -> Bool
132136
isSuccess s = sErrors s == 0 && sFailures s == 0
133137

134-
doctestWithOptions :: Bool -> Bool -> Bool -> [String] -> IO Summary
135-
doctestWithOptions fastMode preserveIt verbose args = do
136-
137-
-- get examples from Haddock comments
138-
modules <- getDocTests args
139-
140-
Interpreter.withInterpreter args $ \repl -> withCP65001 $ do
138+
evaluateSummary :: Summary -> IO ()
139+
evaluateSummary r = when (not $ isSuccess r) exitFailure
140+
141+
doctestWithResult :: Config -> IO Summary
142+
doctestWithResult config = do
143+
(getDocTests (ghcOptions config) >>= runDocTests config) `E.catch` \e -> do
144+
case fromException e of
145+
Just (UsageError err) -> do
146+
hPutStrLn stderr ("doctest: " ++ err)
147+
hPutStrLn stderr "Try `doctest --help' for more information."
148+
exitFailure
149+
_ -> E.throwIO e
150+
151+
runDocTests :: Config -> [Module [Located DocTest]] -> IO Summary
152+
runDocTests Config{..} modules = do
153+
Interpreter.withInterpreter ghcOptions $ \repl -> withCP65001 $ do
141154
runModules fastMode preserveIt verbose repl modules

test/MainSpec.hs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import Test.HUnit (assertEqual, Assertion)
88
import Control.Exception
99
import System.Directory (getCurrentDirectory, setCurrentDirectory)
1010
import System.FilePath
11-
import Runner (Summary(..))
1211
import Run hiding (doctest)
1312
import System.IO.Silently
1413
import System.IO
@@ -24,11 +23,11 @@ doctest :: HasCallStack => FilePath -> [String] -> Summary -> Assertion
2423
doctest = doctestWithPreserveIt False
2524

2625
doctestWithPreserveIt :: HasCallStack => Bool -> FilePath -> [String] -> Summary -> Assertion
27-
doctestWithPreserveIt preserveIt workingDir args expected = do
28-
actual <- withCurrentDirectory ("test/integration" </> workingDir) (hSilence [stderr] $ doctestWithOptions False preserveIt False args)
26+
doctestWithPreserveIt preserveIt workingDir ghcOptions expected = do
27+
actual <- withCurrentDirectory ("test/integration" </> workingDir) (hSilence [stderr] $ doctestWithResult defaultConfig {ghcOptions, preserveIt})
2928
assertEqual label expected actual
3029
where
31-
label = workingDir ++ " " ++ show args
30+
label = workingDir ++ " " ++ show ghcOptions
3231

3332
cases :: Int -> Summary
3433
cases n = Summary n n 0 0

test/OptionsSpec.hs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import Prelude.Compat
55
import Data.List.Compat
66

77
import Test.Hspec
8-
import Test.QuickCheck
8+
import Test.QuickCheck hiding (verbose)
99

1010
import Options
1111

@@ -20,10 +20,10 @@ spec = do
2020
describe "parseOptions" $ do
2121
let
2222
run :: [String] -> Run
23-
run options = defaultRun {
23+
run ghcOptions = defaultRun {
2424
runWarnings = ["WARNING: --optghc is deprecated, doctest now accepts arbitrary GHC options\ndirectly."]
25-
, runOptions = options
2625
, runMagicMode = True
26+
, runConfig = defaultConfig { ghcOptions }
2727
}
2828

2929
it "strips --optghc" $
@@ -45,10 +45,10 @@ spec = do
4545
runMagicMode <$> parseOptions options `shouldBe` Result False
4646

4747
it "filters out --interactive" $ do
48-
runOptions <$> parseOptions options `shouldBe` Result ["--foo", "--bar"]
48+
ghcOptions . runConfig <$> parseOptions options `shouldBe` Result ["--foo", "--bar"]
4949

5050
it "accepts --fast" $ do
51-
runFastMode <$> parseOptions ("--fast" : options) `shouldBe` Result True
51+
fastMode . runConfig <$> parseOptions ("--fast" : options) `shouldBe` Result True
5252

5353
describe "--no-magic" $ do
5454
context "without --no-magic" $ do
@@ -62,20 +62,20 @@ spec = do
6262
describe "--fast" $ do
6363
context "without --fast" $ do
6464
it "disables fast mode" $ do
65-
runFastMode <$> parseOptions [] `shouldBe` Result False
65+
fastMode . runConfig <$> parseOptions [] `shouldBe` Result False
6666

6767
context "with --fast" $ do
6868
it "enabled fast mode" $ do
69-
runFastMode <$> parseOptions ["--fast"] `shouldBe` Result True
69+
fastMode . runConfig <$> parseOptions ["--fast"] `shouldBe` Result True
7070

7171
describe "--preserve-it" $ do
7272
context "without --preserve-it" $ do
7373
it "does not preserve the `it` variable" $ do
74-
runPreserveIt <$> parseOptions [] `shouldBe` Result False
74+
preserveIt . runConfig <$> parseOptions [] `shouldBe` Result False
7575

7676
context "with --preserve-it" $ do
7777
it "preserves the `it` variable" $ do
78-
runPreserveIt <$> parseOptions ["--preserve-it"] `shouldBe` Result True
78+
preserveIt . runConfig <$> parseOptions ["--preserve-it"] `shouldBe` Result True
7979

8080
context "with --help" $ do
8181
it "outputs usage information" $ do
@@ -92,8 +92,8 @@ spec = do
9292
describe "--verbose" $ do
9393
context "without --verbose" $ do
9494
it "is not verbose by default" $ do
95-
runVerbose <$> parseOptions [] `shouldBe` Result False
95+
verbose . runConfig <$> parseOptions [] `shouldBe` Result False
9696

9797
context "with --verbose" $ do
9898
it "parses verbose option" $ do
99-
runVerbose <$> parseOptions ["--verbose"] `shouldBe` Result True
99+
verbose . runConfig <$> parseOptions ["--verbose"] `shouldBe` Result True

test/RunSpec.hs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,6 @@ import qualified Options
1919

2020
import Run
2121

22-
doctestWithDefaultOptions :: [String] -> IO Summary
23-
doctestWithDefaultOptions = doctestWithOptions False False False
24-
2522
withCurrentDirectory :: FilePath -> IO a -> IO a
2623
withCurrentDirectory workingDir action = do
2724
E.bracket getCurrentDirectory setCurrentDirectory $ \_ -> do
@@ -119,9 +116,11 @@ spec = do
119116
hSilence [stderr] $ doctest ["-fdiagnostics-color=always", "test/integration/color/Foo.hs"]
120117
#endif
121118

122-
describe "doctestWithOptions" $ do
119+
describe "doctestWithResult" $ do
123120
context "on parse error" $ do
124-
let action = withCurrentDirectory "test/integration/parse-error" (doctestWithDefaultOptions ["Foo.hs"])
121+
let
122+
action = withCurrentDirectory "test/integration/parse-error" $ do
123+
doctestWithResult defaultConfig { ghcOptions = ["Foo.hs"] }
125124

126125
it "aborts with (ExitFailure 1)" $ do
127126
hSilence [stderr] action `shouldThrow` (== ExitFailure 1)

0 commit comments

Comments
 (0)