Skip to content

Commit 6878b9b

Browse files
authored
Merge pull request #5798 from IntersectMBO/nm/doctesting
Refactor doctesting
2 parents 4f03970 + 4c03bec commit 6878b9b

7 files changed

Lines changed: 96 additions & 39 deletions

File tree

.github/workflows/haskell.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,18 @@ jobs:
169169
path: ${{ steps.install-haskell.outputs.cabal-store }}
170170
key: ${{ steps.restore-cabal-cache.outputs.cache-primary-key }}
171171

172+
# `doctest` needs to be present before building, to avoid `cabal repl` seeing a configuration
173+
# change when `scripts/doctest.sh` runs it
174+
- name: Install doctest
175+
id: install-doctest
176+
if: matrix.ghc == '9.6.7'
177+
run: |
178+
if [[ -z "$(type -t doctest)" ]]
179+
then
180+
cabal install doctest --ignore-project --overwrite-policy=always
181+
cabal path --installdir >> $GITHUB_PATH
182+
fi
183+
172184
- name: Build
173185
run: cabal build all
174186

@@ -189,6 +201,10 @@ jobs:
189201
overwrite: true
190202
retention-days: 1
191203

204+
- name: Run doctests
205+
if: ${{ steps.install-doctest.outcome == 'success' }}
206+
run: scripts/doctest.sh
207+
192208
test:
193209
needs: build
194210

flake.lock

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

flake.nix

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@
146146

147147
# and from nixpkgs or other inputs
148148
nativeBuildInputs = with nixpkgs;
149-
[
149+
with (import nix/doctest.nix { inherit config nixpkgs; }); [
150150
(python3.withPackages (ps:
151151
with ps; [
152152
sphinx
@@ -158,18 +158,9 @@
158158
haskellPackages.implicit-hie
159159
shellcheck
160160
act
161+
doctest
161162
inputs.cardano-ledger-release-tool.packages.${system}.default
162-
] ++ (let
163-
doctest = haskell-nix.hackage-package {
164-
name = "doctest";
165-
version = "0.24.3";
166-
configureArgs = "-f cabal-doctest";
167-
inherit (config) compiler-nix-name;
168-
};
169-
in [
170-
(doctest.getComponent "exe:cabal-doctest")
171-
(doctest.getComponent "exe:doctest")
172-
]);
163+
];
173164
# disable Hoogle until someone request it
174165
withHoogle = false;
175166
# Skip cross compilers for the shell

libs/cardano-ledger-binary/testlib/Test/Cardano/Ledger/Binary/Twiddle.hs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,9 @@ gTwiddleTList v a = TList <$> twiddleL v (from @a @p a)
6464
--
6565
-- For any value `x :: a`, where `a` derives `Twiddle`, and for any version
6666
-- of the decoder, the following property must hold:
67-
-- >>> fmap ((== x) . encodingToTerm version . encCBOR) (twiddle x)
67+
-- prop> \x version -> fmap (== encodingToTerm version (encCBOR x)) (twiddle version (x :: Double))
68+
--
69+
-- Note: this property doesn't hold for some types, hence the type restriction
6870
class Twiddle a where
6971
-- | Given a value of type `a`, generates a CBOR `Term` that can contain
7072
-- slight variations without changing the semantics. After encoding and

libs/cardano-ledger-core/internal/Cardano/Ledger/Internal/Definition/Era.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ class
6767
--
6868
-- Designed to be used with @TypeApplications@:
6969
--
70+
-- >>> :set -XTypeApplications
7071
-- >>> eraName @ByronEra
7172
-- "Byron"
7273
eraName :: String

nix/doctest.nix

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Provide a custom-built doctest that's compatible with haskell.nix
2+
3+
{ config, nixpkgs }:
4+
5+
let
6+
doctest = nixpkgs.haskell-nix.hackage-package {
7+
name = "doctest";
8+
version = "0.24.3";
9+
inherit (config) compiler-nix-name;
10+
modules = [{
11+
packages = {
12+
# This enables doctest to find ghc etc. via environment variables
13+
ghc-paths.patches = nixpkgs.haskellPackages.ghc-paths.patches;
14+
};
15+
}];
16+
};
17+
in { doctest = doctest.getComponent "exe:doctest"; }

scripts/doctest.sh

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@ set -euo pipefail
55
# Packages to run doctests for; defaults to all packages if none are specified
66
PACKAGES=("$@")
77

8-
# Install doctest's Cabal integration, if it's not present already
9-
if [[ -z "$(type -t cabal-doctest)" ]]
8+
# Install doctest, if it's not present already
9+
if [[ -z "$(type -t doctest)" ]]
1010
then
11-
cabal install doctest --flag cabal-doctest --ignore-project --overwrite-policy=always
11+
cabal install doctest --ignore-project --overwrite-policy=always
12+
PATH=$(cabal path --installdir):$PATH
1213
fi
1314

1415
# Ensure doctest and PATH are using the same ghc version
@@ -18,8 +19,18 @@ getExecutablePath()
1819
"$1" -package-env - -e 'import System.Environment' -e 'putStrLn =<< getExecutablePath'
1920
}
2021

22+
lookupVar()
23+
{
24+
ghc -e 'interact $ maybe "" id . lookup "'"$1"'" . read'
25+
}
26+
27+
getPackageDb()
28+
{
29+
readlink -f "$("$1" --info | lookupVar 'Global Package DB')"
30+
}
31+
2132
default_ghc=$(type -p ghc)
22-
doctest_ghc=$(doctest --info | ghc -e 'interact $ maybe "" id . lookup "ghc" . read')
33+
doctest_ghc=$(doctest --info | lookupVar 'ghc')
2334

2435
if [[ "$(getExecutablePath "$default_ghc")" != "$(getExecutablePath "$doctest_ghc")" ]]
2536
then
@@ -29,13 +40,25 @@ then
2940
exit 1
3041
fi
3142

32-
# Ensure the cabal-doctest executable can be found
33-
PATH=$(cabal path --installdir):$PATH
43+
if [[ "$(getPackageDb ghc)" != "$(getPackageDb doctest)" ]]
44+
then
45+
echo "Incompatible package DBs:" >&2
46+
echo " Default DB: $(getPackageDb ghc)" >&2
47+
echo " Doctest DB: $(getPackageDb doctest)" >&2
48+
exit 1
49+
fi
3450

35-
# Ensure other scripts can be found
36-
case "$0" in
37-
*/*) PATH=$(dirname "$(which "$0")"):$PATH;;
38-
esac
51+
# Find packages potentially containing doctests
52+
if [[ ${#PACKAGES[@]} -eq 0 ]]
53+
then
54+
for CABAL_FILE in $(git ls-files '*.cabal')
55+
do
56+
if git grep -qIEe '(>>>|prop>)' "${CABAL_FILE%/*}/*.hs"
57+
then
58+
PACKAGES+=("$(basename "$CABAL_FILE" .cabal)")
59+
fi
60+
done
61+
fi
3962

4063
# Specify additional arguments needed for specific modules
4164
EXTRA_ARGS=$(mktemp)
@@ -44,11 +67,18 @@ cat <<EOF >"$EXTRA_ARGS"
4467
cardano-ledger-api:lib:cardano-ledger-api --build-depends=cardano-ledger-babbage:testlib
4568
EOF
4669

70+
RESULT=0
71+
shopt -s lastpipe # Run the while loop in the current process, to enable setting RESULT=1
72+
4773
# Run the doctests for some or all packages
4874
cleret cabal targets "${PACKAGES[@]}" |
4975
sort | join -t' ' -a1 -j1 - "$EXTRA_ARGS" |
5076
while read -ra ARGS
5177
do
5278
echo "***** cabal doctest ${ARGS[0]} *****"
53-
cabal doctest --repl-options='-w -Wdefault' "${ARGS[@]}"
79+
cabal repl --with-repl=doctest --repl-options='-w -Wdefault' \
80+
--build-depends=QuickCheck --build-depends=template-haskell \
81+
"${ARGS[@]}" || RESULT=1
5482
done
83+
84+
exit "$RESULT"

0 commit comments

Comments
 (0)