Skip to content

Commit ee6f069

Browse files
committed
Add a coverage test
1 parent a675618 commit ee6f069

File tree

17 files changed

+303
-4
lines changed

17 files changed

+303
-4
lines changed

overlays/haskell.nix

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -537,10 +537,13 @@ final: prev: {
537537
++ (args.modules or [])
538538
++ final.lib.optional (args ? ghc) { ghc.package = args.ghc; };
539539
};
540-
in addProjectAndPackageAttrs {
541-
inherit (pkg-set.config) hsPkgs;
542-
inherit pkg-set;
543-
stack-nix = callProjectResults.projectNix;
540+
project = addProjectAndPackageAttrs {
541+
inherit (pkg-set.config) hsPkgs;
542+
inherit pkg-set;
543+
stack-nix = callProjectResults.projectNix;
544+
};
545+
in project // {
546+
projectCoverageReport = haskellLib.projectCoverageReport (haskellLib.selectProjectPackages project.hsPkgs);
544547
};
545548

546549
stackProject = args: let p = stackProject' args;

test/coverage/cabal.project

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
packages: pkga
2+
pkgb

test/coverage/conduit.hs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
-- https://github.com/snoyberg/conduit#readme
2+
3+
import Conduit
4+
import System.Directory (removeFile)
5+
6+
main = do
7+
-- Pure operations: summing numbers.
8+
print $ runConduitPure $ yieldMany [1..10] .| sumC
9+
10+
-- Exception safe file access: copy a file.
11+
writeFile "input.txt" "This is a test." -- create the source file
12+
runConduitRes $ sourceFileBS "input.txt" .| sinkFile "output.txt" -- actual copying
13+
readFile "output.txt" >>= putStrLn -- prove that it worked
14+
15+
-- Perform transformations.
16+
print $ runConduitPure $ yieldMany [1..10] .| mapC (+ 1) .| sinkList
17+
18+
removeFile "input.txt"
19+
removeFile "output.txt"

test/coverage/default.nix

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
{ stdenv, cabal-install, cabalProject', stackProject', recurseIntoAttrs, runCommand, testSrc }:
2+
3+
with stdenv.lib;
4+
5+
let
6+
projectArgs = {
7+
src = testSrc "coverage";
8+
modules = [{
9+
# Package has no exposed modules which causes
10+
# haddock: No input file(s)
11+
packages.bytestring-builder.doHaddock = false;
12+
13+
packages.pkga.components.library.doCoverage = true;
14+
packages.pkgb.components.library.doCoverage = true;
15+
}];
16+
};
17+
18+
cabalProject = cabalProject' projectArgs;
19+
stackProject = stackProject' projectArgs;
20+
21+
in recurseIntoAttrs ({
22+
run = stdenv.mkDerivation {
23+
name = "coverage-test";
24+
25+
buildCommand = ''
26+
########################################################################
27+
# test coverage reports with an example project
28+
29+
fileExistsNonEmpty() {
30+
local file=$1
31+
if [ ! -f "$file" ]; then
32+
echo "Missing: $file"
33+
exit 1
34+
fi
35+
local filesize=$(command stat --format '%s' "$file")
36+
if [ $filesize -eq 0 ]; then
37+
echo "File must not be empty: $file"
38+
exit 1
39+
fi
40+
}
41+
findFileExistsNonEmpty() {
42+
local searchDir=$1
43+
local filePattern=$2
44+
45+
local file="$(find $searchDir -name $filePattern -print -quit)"
46+
47+
if [ -z $file ]; then
48+
echo "Couldn't find file \"$filePattern\" in directory \"$searchDir\"."
49+
exit 1
50+
fi
51+
52+
local filesize=$(command stat --format '%s' "$file")
53+
if [ $filesize -eq 0 ]; then
54+
echo "File must not be empty: $file"
55+
exit 1
56+
fi
57+
}
58+
dirExistsEmpty() {
59+
local dir=$1
60+
if [ ! -d "$dir" ]; then
61+
echo "Missing: $dir"
62+
exit 1
63+
fi
64+
if [ "$(ls -A $dir)" ]; then
65+
echo "Dir should be empty: $dir"
66+
exit 1
67+
fi
68+
}
69+
dirExists() {
70+
local dir=$1
71+
if [ ! -d "$dir" ]; then
72+
echo "Missing: $dir"
73+
exit 1
74+
fi
75+
}
76+
77+
${concatStringsSep "\n" (map (project: ''
78+
pkga_basedir="${project.hsPkgs.pkga.coverageReport}/share/hpc/"
79+
findFileExistsNonEmpty "$pkga_basedir/mix/pkga-0.1.0.0/" "PkgA.mix"
80+
dirExistsEmpty "$pkga_basedir/tix/pkga-0.1.0.0"
81+
dirExistsEmpty "$pkga_basedir/html/pkga-0.1.0.0"
82+
83+
pkgb_basedir="${project.hsPkgs.pkgb.coverageReport}/share/hpc/"
84+
testTix="$pkgb_basedir/tix/tests/tests.tix"
85+
libTix="$pkgb_basedir/tix/pkgb-0.1.0.0/pkgb-0.1.0.0.tix"
86+
fileExistsNonEmpty "$testTix"
87+
fileExistsNonEmpty "$libTix"
88+
findFileExistsNonEmpty "$pkgb_basedir/mix/pkgb-0.1.0.0/" "ConduitExample.mix"
89+
findFileExistsNonEmpty "$pkgb_basedir/mix/pkgb-0.1.0.0/" "PkgB.mix"
90+
fileExistsNonEmpty "$pkgb_basedir/mix/tests/Main.mix"
91+
fileExistsNonEmpty "$pkgb_basedir/html/pkgb-0.1.0.0/hpc_index.html"
92+
fileExistsNonEmpty "$pkgb_basedir/html/tests/hpc_index.html"
93+
94+
filesizeTestsTix=$(command stat --format '%s' "$testTix")
95+
filesizeLibTix=$(command stat --format '%s' "$libTix")
96+
if (( filesizeTestsTix <= filesizeLibTix )); then
97+
echo "Filesize of \"$testTix\" ($filesizeTestsTix) should be greather than that of \"$libTix\" ($filesizeLibTix). Did you forget to exclude test modules when creating \"$libTix\"?"
98+
exit 1
99+
fi
100+
101+
project_basedir="${project.projectCoverageReport}/share/hpc/"
102+
fileExistsNonEmpty "$project_basedir/html/index.html"
103+
fileExistsNonEmpty "$project_basedir/tix/all/all.tix"
104+
dirExists "$project_basedir/html/pkga-0.1.0.0"
105+
dirExists "$project_basedir/html/pkgb-0.1.0.0"
106+
dirExists "$project_basedir/html/tests"
107+
dirExists "$project_basedir/mix/pkga-0.1.0.0"
108+
dirExists "$project_basedir/mix/pkgb-0.1.0.0"
109+
dirExists "$project_basedir/mix/tests"
110+
dirExists "$project_basedir/tix/all"
111+
dirExists "$project_basedir/tix/pkga-0.1.0.0"
112+
dirExists "$project_basedir/tix/pkgb-0.1.0.0"
113+
dirExists "$project_basedir/tix/tests"
114+
'') [ cabalProject stackProject ])}
115+
116+
touch $out
117+
'';
118+
119+
meta.platforms = platforms.all;
120+
121+
passthru = {
122+
# Used for debugging with nix repl
123+
inherit cabalProject stackProject;
124+
};
125+
};
126+
})

test/coverage/pkga/MainA.hs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module Main where
2+
3+
main :: IO ()
4+
main = putStrLn "This is MainA"

test/coverage/pkga/PkgA.hs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
module PkgA (decode) where
2+
3+
import Control.Lens
4+
import Data.Text.Lens
5+
import Data.Char
6+
import Data.Text (Text)
7+
8+
decode :: Text -> Text
9+
decode = unpacked . mapped %~ rot 13
10+
11+
rot :: Int -> Char -> Char
12+
rot n c | c >= 'a' && c <= 'z' = r 'a' 'z'
13+
| c >= 'A' && c <= 'Z' = r 'A' 'Z'
14+
| otherwise = c
15+
where
16+
r a b = chr $ ord a + ((ord c - ord a + n) `mod` (ord b - ord a + 1))

test/coverage/pkga/Setup.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import Distribution.Simple
2+
main = defaultMain

test/coverage/pkga/pkga.cabal

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
cabal-version: 2.2
2+
-- Initial package description 'pkga.cabal' generated by 'cabal init'. For
3+
-- further documentation, see http://haskell.org/cabal/users-guide/
4+
5+
name: pkga
6+
version: 0.1.0.0
7+
-- synopsis:
8+
-- description:
9+
-- bug-reports:
10+
license: LicenseRef-PublicDomain
11+
author: Rodney Lorrimar
12+
maintainer: rodney.lorrimar@iohk.io
13+
category: Testing
14+
15+
library
16+
exposed-modules: PkgA
17+
build-depends: base
18+
, lens
19+
, text
20+
default-language: Haskell2010
21+
22+
executable pkga-exe
23+
main-is: MainA.hs
24+
build-depends: base
25+
hs-source-dirs: .
26+
default-language: Haskell2010

test/coverage/pkgb/Setup.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import Distribution.Simple
2+
main = defaultMain

test/coverage/pkgb/app/Main.hs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
module Main where
2+
3+
import ConduitExample (example)
4+
import PkgB (message)
5+
import qualified Data.Text.IO as T
6+
7+
main :: IO ()
8+
main = do
9+
T.putStrLn message
10+
example

test/coverage/pkgb/app/tests.hs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module Main where
2+
3+
import System.Process
4+
import ConduitExample
5+
6+
main :: IO ()
7+
main = example

test/coverage/pkgb/pkgb.cabal

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
cabal-version: 2.2
2+
-- Initial package description 'pkgb.cabal' generated by 'cabal init'. For
3+
-- further documentation, see http://haskell.org/cabal/users-guide/
4+
5+
name: pkgb
6+
version: 0.1.0.0
7+
-- synopsis:
8+
-- description:
9+
-- bug-reports:
10+
license: LicenseRef-PublicDomain
11+
author: Rodney Lorrimar
12+
maintainer: rodney.lorrimar@iohk.io
13+
category: Testing
14+
15+
library
16+
exposed-modules: ConduitExample
17+
, PkgB
18+
build-depends: base
19+
, pkga
20+
, conduit
21+
, conduit-extra
22+
, directory
23+
, resourcet
24+
hs-source-dirs: src
25+
default-language: Haskell2010
26+
27+
executable pkgb
28+
main-is: Main.hs
29+
build-depends: base
30+
, pkgb
31+
, optparse-applicative
32+
, text
33+
hs-source-dirs: app
34+
default-language: Haskell2010
35+
36+
test-suite tests
37+
type: exitcode-stdio-1.0
38+
main-is: tests.hs
39+
hs-source-dirs: app
40+
build-depends: base
41+
, pkgb
42+
, process
43+
build-tools: pkga
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
-- https://github.com/snoyberg/conduit#readme
2+
3+
module ConduitExample (example) where
4+
5+
import Conduit
6+
import System.Directory (removeFile)
7+
8+
example = do
9+
-- Pure operations: summing numbers.
10+
print $ runConduitPure $ yieldMany [1..10] .| sumC
11+
12+
-- Exception safe file access: copy a file.
13+
writeFile "input.txt" "This is a test." -- create the source file
14+
runConduitRes $ sourceFileBS "input.txt" .| sinkFile "output.txt" -- actual copying
15+
readFile "output.txt" >>= putStrLn -- prove that it worked
16+
17+
-- Perform transformations.
18+
print $ runConduitPure $ yieldMany [1..10] .| mapC (+ 1) .| sinkList
19+
20+
removeFile "input.txt"
21+
removeFile "output.txt"

test/coverage/pkgb/src/PkgB.hs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{-# LANGUAGE OverloadedStrings #-}
2+
3+
module PkgB (message) where
4+
5+
import PkgA (decode)
6+
7+
message = decode "Guvf vf n pnony cebwrpg!"
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module Main where
2+
3+
import ConduitExample
4+
5+
main = example

test/coverage/stack.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
resolver: lts-14.13
2+
3+
packages:
4+
- pkga/
5+
- pkgb/

test/default.nix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ let
178178
compiler-nix-name = callTest ./compiler-nix-name {};
179179
hls-cabal = callTest ./haskell-language-server/cabal.nix {};
180180
hls-stack = callTest ./haskell-language-server/stack.nix {};
181+
coverage = callTest ./coverage {};
181182

182183
unit = unitTests;
183184
} // lib.optionalAttrs (!stdenv.hostPlatform.isGhcjs && pkgs.haskell-nix.defaultCompilerNixName != "ghc8101" ) {

0 commit comments

Comments
 (0)