Use Haskell based test driver

Replace bin/test.sh with a Haskell implementation
This commit is contained in:
Harendra Kumar 2022-04-27 11:59:49 +05:30
parent 326bcda0d6
commit 5435aa1b16
11 changed files with 383 additions and 72 deletions

View File

@ -120,7 +120,7 @@ jobs:
- name: Run benchmarks and append
run: |
cabal run report --project-file=cabal.project.report -- --benchmarks "$CI_BENCHMARKS" --raw --append
cabal run report --project-file=cabal.project.report -- --targets "$CI_BENCHMARKS" --raw --append
# -----------------------------------------------------------------
# -- Compare
@ -128,7 +128,7 @@ jobs:
- name: List all benchmarks
run: |
cabal run report --project-file=cabal.project.report -- --benchmarks "$CI_BENCHMARKS" --no-measure
cabal run report --project-file=cabal.project.report -- --targets "$CI_BENCHMARKS" --no-measure
- name: Compare benchmarks
run: |
@ -146,7 +146,7 @@ jobs:
echo
echo "Checking $bname for regressions greater than $cutoff percent"
! cabal run report --project-file=cabal.project.report -- --benchmarks "$bname" \
! cabal run report --project-file=cabal.project.report -- --targets "$bname" \
--fields "$CI_FIELDS" \
--no-measure --silent \
--diff-cutoff-percent $cutoff \

View File

@ -28,3 +28,5 @@ hie.yaml
stack.yaml
targets/default.nix
targets/cabal.project
test/report/default.nix
test/report/cabal.project

View File

@ -265,6 +265,7 @@ $RTS_OPTIONS \
then
# Escape "\" and double quotes in benchmark names
BENCH_NAME_ESC=$(echo "$BENCH_NAME_ORIG" | sed -e 's/\\/\\\\/g' | sed -e 's/"/\\"/g')
echo "$BENCH_NAME_ESC"
$BENCH_EXEC_PATH \
-j 1 \
$RTS_OPTIONS1 \

View File

@ -7,29 +7,7 @@ import Data.List (isInfixOf, isPrefixOf, isSuffixOf)
import Data.Map (Map)
import qualified Data.Map as Map
import Targets
comparisons :: Map String [String]
comparisons =
Map.fromList
[ ("base_stream_cmp", ["Data.Stream.StreamD", "Data.Stream.StreamK"])
, ("serial_wserial_cmp", ["Prelude.Serial", "Prelude.WSerial"])
, ("serial_async_cmp", ["Prelude.Serial", "Prelude.Async"])
, ( "concurrent_cmp"
, [ "Prelude.Async"
, "Prelude.WAsync"
, "Prelude.Ahead"
, "Prelude.Parallel"
])
, ( "array_cmp"
, [ "Data.Array.Foreign"
, "Data.Array.Prim"
, "Data.Array"
, "Data.Array.Prim.Pinned"
])
, ("pinned_array_cmp", ["Data.Array.Foreign", "Data.Array.Prim.Pinned"])
, ("base_parser_cmp", ["Data.Parser.ParserD", "Data.Parser.ParserK"])
]
import Targets (targets)
rtsOpts :: String -> String -> String
rtsOpts exeName benchName0 = unwords [general, exeSpecific, benchSpecific]
@ -151,4 +129,4 @@ speedOpts exeName benchName0 = exeSpecific <|> benchSpecific
| otherwise = Nothing
main :: IO ()
main = mainWith groupTargets individualTargets comparisons speedOpts rtsOpts
main = mainWith targets speedOpts rtsOpts

View File

@ -1,6 +1,7 @@
packages:
targets/streamly-targets.cabal
benchmark/report/report.cabal
test/report/streamly-test-report.cabal
streamly.cabal
core/streamly-core.cabal

View File

@ -88,6 +88,8 @@ extra-source-files:
docs/streamly-docs.cabal
targets/streamly-targets.cabal
targets/Targets.hs
test/report/Main.hs
test/report/streamly-test-report.cabal
-- This is duplicated
src/Streamly/Internal/Data/Stream/Instances.hs

View File

@ -1,55 +1,149 @@
module Targets
( groupTargets
, individualTargets
( targets
)
where
import Data.Map (Map)
targets :: [(String, [String])]
targets =
[ -- Base streams
("Data.Stream.StreamD",
[ "base_stream_grp"
, "base_stream_cmp"
, "noTest"
]
)
, ("Data.Stream.StreamK",
[ "base_stream_grp"
, "base_stream_cmp"
, "noTest"
]
)
, ("Data.Stream.StreamDK",
[ "base_stream_grp"
, "noTest"
]
)
import qualified Data.Map as Map
-- Streams
, ("Prelude.Serial", ["serial_wserial_cmp"])
, ("Prelude.WSerial", ["serial_wserial_cmp"])
, ("Prelude.Serial",
[ "prelude_serial_grp"
, "infinite_grp"
, "serial_wserial_cmp"
, "serial_async_cmp"
]
)
, ("Prelude.WSerial",
[ "prelude_serial_grp"
, "infinite_grp"
, "serial_wserial_cmp"
]
)
, ("Prelude.ZipSerial",
[ "prelude_serial_grp"
, "infinite_grp"
]
)
, ("Prelude.Async",
[ "prelude_concurrent_grp"
, "infinite_grp"
, "concurrent_cmp"
, "serial_async_cmp"
]
)
, ("Prelude.WAsync",
[ "prelude_concurrent_grp"
, "infinite_grp"
, "concurrent_cmp"
]
)
, ("Prelude.Ahead",
[ "prelude_concurrent_grp"
, "infinite_grp"
, "concurrent_cmp"
]
)
, ("Prelude.Parallel",
[ "prelude_concurrent_grp"
, "infinite_grp"
, "concurrent_cmp"
]
)
, ("Prelude.ZipAsync",
[ "prelude_concurrent_grp"
, "infinite_grp"
]
)
, ("Prelude.Concurrent", [ "prelude_other_grp" ])
, ("Prelude.Rate",
[ "prelude_other_grp"
, "infinite_grp"
, "testDevOnly"
]
)
, ("Prelude.Adaptive",
[ "prelude_other_grp"
, "noTest"
]
)
groupTargets :: Map String [String]
groupTargets =
Map.fromList
[ ( "base_stream_grp"
, [ "Data.Stream.StreamD"
, "Data.Stream.StreamK"
, "Data.Stream.StreamDK"
])
, ("prelude_serial_grp", preludeSerialGrp)
, ("prelude_concurrent_grp", preludeConcurrentGrp)
, ( "prelude_other_grp"
, ["Prelude.Rate", "Prelude.Concurrent", "Prelude.Adaptive"])
, ( "array_grp"
, [ "Data.Array"
, "Data.Array.Foreign"
, "Data.Array.Prim"
, "Data.SmallArray"
, "Data.Array.Prim.Pinned"
])
, ("base_parser_grp", ["Data.Parser.ParserD", "Data.Parser.ParserK"])
, ("parser_grp", ["Data.Fold", "Data.Parser"])
, ("list_grp ", [])
, ( "infinite_grp"
, preludeSerialGrp ++ preludeConcurrentGrp ++ ["Prelude.Rate"])
]
-- Arrays
, ("Data.Array",
[ "array_grp"
, "array_cmp"
]
)
, ("Data.Array.Foreign",
[ "array_grp"
, "array_cmp"
, "pinned_array_cmp"
]
)
, ("Data.Array.Prim",
[ "array_grp"
, "array_cmp"
]
)
, ("Data.Array.Prim.Pinned",
[ "array_grp"
, "array_cmp"
, "pinned_array_cmp"
]
)
, ("Data.SmallArray",
[ "array_grp" ]
)
where
-- Parsers
, ("Data.Parser.ParserD",
[ "base_parser_grp"
, "base_parser_cmp"
]
)
, ("Data.Parser.ParserK",
[ "base_parser_grp"
, "base_parser_cmp"
, "noTest"
]
)
, ("Data.Fold", [ "parser_grp" ])
, ("Data.Parser", [ "parser_grp" ])
preludeSerialGrp = ["Prelude.Serial", "Prelude.WSerial", "Prelude.ZipSerial"]
preludeConcurrentGrp =
[ "Prelude.Async"
, "Prelude.WAsync"
, "Prelude.Ahead"
, "Prelude.Parallel"
, "Prelude.ZipAsync"
]
, ("Data.Unfold", [])
, ("FileSystem.Handle", [])
, ("Unicode.Stream", [])
, ("Unicode.Utf8", ["noTest"])
, ("Unicode.Char", ["testDevOnly"])
individualTargets :: [String]
individualTargets =
[ "Data.Unfold"
, "Unicode.Stream"
, "Unicode.Char"
, "Unicode.Utf8"
, "FileSystem.Handle"
-- test only, no benchmarks
, ("Prelude", ["prelude_other_grp", "noBench"])
, ("Prelude.Fold", ["prelude_other_grp", "noBench"])
, ("FileSystem.Event", ["noBench"])
, ("Network.Socket", ["noBench"])
, ("Network.Inet.TCP", ["noBench"])
, ("version-bounds", ["noBench"])
, ("Data.List", ["list_grp", "noBench"])
, ("Data.List.Base", ["list_grp", "noBench"])
]

34
test/report/Main.hs Normal file
View File

@ -0,0 +1,34 @@
module Main where
import TestRunner (mainWith)
import BuildLib (Quickness(..))
import Control.Applicative ((<|>))
import Data.List (isInfixOf, isPrefixOf, isSuffixOf)
import Data.Map (Map)
import qualified Data.Map as Map
import Targets (targets)
rtsOpts :: Bool -> String -> String -> String
rtsOpts relaxMem exeName target =
if relaxMem
then "-K16M -M1024M"
else "-K8M -M64M " <> targetSpecific
where
targetSpecific =
case target of
-- XXX Data.Array.* heap requirement increased for GHC-8.10
"Data.Array.Foreign" -> "-M128M"
"Data.Array.Prim" -> "-M128M"
"Data.Array.Prim.Pinned" -> "-M128M"
"Prelude.Rate" -> "-M512M"
-- For -O0 case writeChunks test fails, maybe we should have a
-- separate flag for O0 case?
"FileSystem.Handle" -> "-K16M"
_ -> ""
main :: IO ()
main = mainWith targets rtsOpts

View File

@ -0,0 +1 @@
packages: ., ../../targets

157
test/report/default.nix Normal file
View File

@ -0,0 +1,157 @@
let
nixpkgsPath_21_11 =
"https://github.com/NixOS/nixpkgs/archive/refs/tags/21.11.tar.gz";
nixpkgsDefault = import (builtins.fetchTarball nixpkgsPath_21_11) { };
in
{
nixpkgs ? nixpkgsDefault
, compiler ? "default"
}:
let haskellPackages =
if compiler == "default"
then nixpkgs.haskellPackages
else nixpkgs.haskell.packages.${compiler};
mkPackage = super: pkg: path: opts: inShell:
let orig = super.callCabal2nixWithOptions pkg path opts {};
in if inShell
# Avoid copying the source directory to nix store by using
# src = null.
then orig.overrideAttrs (oldAttrs: { src = null; })
else orig;
mkPkgGit = super: gitSrc: rev: name:
let
src = builtins.fetchGit {
url = gitSrc;
rev = rev;
};
in super.callCabal2nix name src { };
mkPkgGitRef = super: gitSrc: rev: ref: name:
let
src = builtins.fetchGit {
url = gitSrc;
rev = rev;
ref = ref;
};
in super.callCabal2nix name src { };
mkHaskellPackages = inShell:
haskellPackages.override {
overrides = self: super:
with nixpkgs.haskell.lib;
{
report = mkPackage super "streamly-test-report" ./. "" inShell;
bench-report =
nixpkgs.haskell.lib.overrideCabal
(let src = fetchGit {
url = "git@github.com:composewell/bench-report.git";
rev = "c11f79b202d812efe4d1785e0537f1ad4d947bfe";
}; in super.callCabal2nix "bench-report" src {})
(old:
{ enableLibraryProfiling = false;
doHaddock = false;
});
# streamly-coreutils = let
# src = "git@github.com:composewell/streamly-coreutils.git";
# rev = "a12756efe24bbf303f2f6d66a95426c7657d297b";
# in mkPkgGit super src rev "streamly-coreutils";
streamly-coreutils =
nixpkgs.haskell.lib.overrideCabal
(let src = fetchGit {
url = "git@github.com:composewell/streamly-coreutils.git";
rev = "8fa4a3ebedb3f970f64b7d78d8ab340b0f771abe";
}; in super.callCabal2nix "streamly-coreutils" src {})
(old:
{ librarySystemDepends =
if builtins.currentSystem == "x86_64-darwin"
then [nixpkgs.darwin.apple_sdk.frameworks.Cocoa]
else [];
#enableLibraryProfiling = false;
doHaddock = false;
doCheck = false;
});
streamly-shell = let
src = "https://github.com/composewell/streamly-shell.git";
rev = "7d77ddc0c06aec21fbbfd1b920ec4f58da654a1b";
in mkPkgGit super src rev "streamly-shell";
streamly-process = let
src = "https://github.com/composewell/streamly-process.git";
rev = "a56ef61c1208c2d564a526eba315d903c0b4af2c";
in nixpkgs.haskell.lib.dontCheck
(mkPkgGit super src rev "streamly-process");
#streamly-process = nixpkgs.haskell.lib.dontCheck
# (super.callHackageDirect {
# pkg = "streamly-process";
# ver = "0.1.0";
# sha256 = "01nxisqfmn29fbirdsx71sfjp2rdqwrf469qyjcql2d11i1bxn94";
# } { });
# streamly = super.callHackageDirect {
# pkg = "streamly";
# ver = "0.8.0";
# sha256 = "0vy2lkljizlhpbpbybmg9jcmj2g4s1aaqd2dzy5c0y0n4rgwxask";
# } { };
streamly =
nixpkgs.haskell.lib.overrideCabal
#(super.callHackageDirect
# { pkg = "streamly";
# ver = "0.8.2";
# sha256 = "sha256-CjFq9SCdbgLZa7NqOE4OtC8OaFg4vK8VmIDjGU5rGko=";
# } {})
(let src = fetchGit {
url = "git@github.com:composewell/streamly.git";
rev = "a849812d9960d5b7868e770156ab774ee8f70157";
}; in super.callCabal2nix "streamly" src {})
(old:
{ librarySystemDepends =
if builtins.currentSystem == "x86_64-darwin"
then [nixpkgs.darwin.apple_sdk.frameworks.Cocoa]
else [];
#enableLibraryProfiling = false;
doHaddock = false;
});
streamly-core =
nixpkgs.haskell.lib.overrideCabal
(let src = fetchGit {
url = "git@github.com:composewell/streamly.git";
rev = "a849812d9960d5b7868e770156ab774ee8f70157";
}; in super.callCabal2nix "streamly-core" "${src}/core" {})
(old:
{ librarySystemDepends =
if builtins.currentSystem == "x86_64-darwin"
then [nixpkgs.darwin.apple_sdk.frameworks.Cocoa]
else [];
#enableLibraryProfiling = false;
doHaddock = false;
});
};
};
drv = mkHaskellPackages true;
shell = drv.shellFor {
packages = p:
[ p.report
];
# Use a better prompt
shellHook = ''
export CABAL_DIR="$(pwd)/.cabal.nix"
if test -n "$PS_SHELL"
then
export PS1="$PS_SHELL\[$bldred\](nix)\[$txtrst\] "
fi
'';
};
in if nixpkgs.lib.inNixShell
then shell
else (mkHaskellPackages false).streamly-test-report

View File

@ -0,0 +1,41 @@
cabal-version: 2.4
name: streamly-test-report
version: 0.1.0.0
-- A short (one-line) description of the package.
-- synopsis:
-- A longer description of the package.
-- description:
-- A URL where users can report bugs.
-- bug-reports:
-- The license under which the package is released.
-- license:
-- The package author(s).
-- author:
-- An email address to which users can send suggestions, bug reports, and patches.
-- maintainer:
-- A copyright notice.
-- copyright:
-- category:
-- extra-source-files: CHANGELOG.md
executable test-report
main-is: Main.hs
-- Modules included in this executable, other than Main.
-- other-modules:
-- LANGUAGE extensions used by modules in this package.
-- other-extensions:
build-depends: base
, bench-report
, containers
, streamly-targets
hs-source-dirs: .
default-language: Haskell2010