Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactoring test/default.nix #434

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
226 changes: 187 additions & 39 deletions test/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -7,49 +7,197 @@
with pkgs;

let
withIfdInputs = builtins.mapAttrs (n: x:
if n == "ifdInputs"
then pkgs.recurseIntoAttrs (builtins.mapAttrs (_: pkgs.haskell-nix.withInputs) x)
else x);
# Set recurseForDerivations for both children and grand-children values in
# the input association list, but only if the key is "ifdInputs".
#
# withIfdInputs :: AttrSet -> AttrSet
#
# The values in the input attribute set must be attribute sets themselves.
#
# >>> withIfdInputs { ifdInputs = { plan-nix = { a = true; b = "hello"; }; }; cat = 2; }
# { ifdInputs = {
# plan-nix = {
# a = true;
# b = "hello";
# recurseForDerivations = true;
# };
# recurseForDerivations = true;
# };
# cat = 2;
# }
#
# >>> withIfdInputs { dog = "hello"; }
# { dog = "hello"; }
#
# >>> withIfdInputs { }
# { }
withIfdInputs =
builtins.mapAttrs
(name: val:
if name == "ifdInputs"
then
pkgs.recurseIntoAttrs
(builtins.mapAttrs (_: v: pkgs.haskell-nix.withInputs v) val)
else val
);

util = import ./util.nix { inherit (pkgs.haskell-nix) cabal-install; };
in pkgs.recurseIntoAttrs {
haskellNixRoots = haskell-nix.haskellNixRoots' ifdLevel;
} // pkgs.lib.optionalAttrs (ifdLevel > 1) (
builtins.mapAttrs (_: y: withIfdInputs y) ((if ifdLevel < 3
then builtins.mapAttrs (_: d: pkgs.recurseIntoAttrs (pkgs.lib.filterAttrs (n: _: n == "ifdInputs") d))
else x: x) {
cabal-simple = haskell-nix.callPackage ./cabal-simple { inherit util; };
Comment on lines -17 to -21
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aside from some simple formatting changes, this PR basically just pulls out each part of this code block into separate functions, and adds documentation describing what each does.

cabal-simple-prof = haskell-nix.callPackage ./cabal-simple-prof { inherit util; };
cabal-sublib = haskell-nix.callPackage ./cabal-sublib { inherit util; };
cabal-22 = haskell-nix.callPackage ./cabal-22 { inherit util; };
with-packages = haskell-nix.callPackage ./with-packages { inherit util; };
builder-haddock = haskell-nix.callPackage ./builder-haddock {};
stack-simple = haskell-nix.callPackage ./stack-simple {};
stack-local-resolver = haskell-nix.callPackage ./stack-local-resolver {};
snapshots = haskell-nix.callPackage ./snapshots {};
shell-for = haskell-nix.callPackage ./shell-for {};
shell-for-setup-deps = haskell-nix.callPackage ./shell-for-setup-deps {};
setup-deps = import ./setup-deps { inherit pkgs; };
callStackToNix = haskell-nix.callPackage ./call-stack-to-nix {};
callCabalProjectToNix = haskell-nix.callPackage ./call-cabal-project-to-nix {};
cabal-source-repo = haskell-nix.callPackage ./cabal-source-repo {};
buildable = haskell-nix.callPackage ./buildable {};
project-flags-cabal = haskell-nix.callPackage ./project-flags/cabal.nix {};
project-flags-stack = haskell-nix.callPackage ./project-flags/stack.nix {};
fully-static = haskell-nix.callPackage ./fully-static { inherit (pkgs) buildPackages; };
ghc-options-cabal = haskell-nix.callPackage ./ghc-options/cabal.nix {};
ghc-options-stack = haskell-nix.callPackage ./ghc-options/stack.nix {};
exe-only = haskell-nix.callPackage ./exe-only { inherit util; };
stack-source-repo = haskell-nix.callPackage ./stack-source-repo {};

# Map the values in an association list over the withIfdInputs function.
#
# addIfdInputsToVal :: AttrSet -> AttrSet
#
# The values in the input association list must be attribute sets themselves.
addIfdInputsToVal = builtins.mapAttrs (_: val: withIfdInputs val);

# Keep only the attribute with the key "ifdInputs".
#
# filterAttrsIfdInputs :: AttrSet -> AttrSet
#
# >>> filterAttrsIfdInputs { ifdInputs = 1; foobar = 2 }
# { ifdInputs = 1 }
#
# >>> filterAttrsIfdInputs { foobar = "hello" }
# { }
filterAttrsIfdInputs = pkgs.lib.filterAttrs (n: _: n == "ifdInputs");

# Remove all keys and values in a attribute set where the key
# doesn't equal "ifdInputs". Set the "recurseForDerivations"
# key in the resulting value.
#
# filterNonIfdInputsSetRecurse :: AttrSet -> AttrSet
#
# >>> filterNonIfdInputsSetRecurse { ifdInputs = 1; foobar = 2 }
# { ifdInputs = 1; recurseForDerivations = true }
#
# >>> filterNonIfdInputsSetRecurse { foobar = "hello" }
# { recurseForDerivations = true; }
filterNonIfdInputsSetRecurse = attrs:
pkgs.recurseIntoAttrs (filterAttrsIfdInputs attrs);

# Filter all out all the keys/values for child values of this attribute set
# where the key is not equal to "ifdInputs".
#
# filterNonIfdInputsValues :: AttrSet -> AttrSet
#
# The values in the input AttrSet must be attribute sets themselves.
#
# >>> filterNonIfdInputsValues { foo = { ifdInputs = 1; cat = 2; }; bar = { dog = "hello"; }; }
# { foo = {
# ifdInputs = 1;
# recurseForDerivations = true;
# };
# bar = {
# recurseForDerivations = true;
# };
# }
#
# >>> filterNonIfdInputsValues { }
# { }
filterNonIfdInputsValues = attrs:
builtins.mapAttrs (_: d: filterNonIfdInputsSetRecurse d) attrs;

# Call filterNonIfdInputsValues on the input attribute set, but only
# if ifdLevel is less than 3. Otherwise, just return the attribute set.
#
# filterNonIfdInputsValuesLTLevel3 :: AttrSet -> AttrSet
#
# >>> filterNonIfdInputsValuesLTLevel3 2 { cabal-doctests = { ifdInputs = {...}; run = ""; }; cabal-simple = { run = ""; }; }
# { cabal-doctests = {
# ifdInputs = {...};
# recurseForDerivations = true;
# };
# cabal-simple = {
# recurseForDerivations = true;
# };
# }
#
# >>> filterNonIfdInputsValuesLTLevel3 1000 { cabal-doctests = { ifdInputs = {...}; run = "..."; }; cabal-simple = { run = "..."; }; }
# { cabal-doctests = {
# ifdInputs = {...};
# run = "...";
# recurseForDerivations = true;
# };
# cabal-simple = {
# run = "...";
# recurseForDerivations = true;
# };
# }
#
# >>> filterNonIfdInputsValuesLTLevel3 0 { }
# { }
filterNonIfdInputsValuesLTLevel3 = ifdLevel: attrs:
if ifdLevel < 3
then filterNonIfdInputsValues attrs
else attrs;

# Run unit tests with: nix-instantiate --eval --strict -A unit.tests
# An empty list means success.
unit = let
tests = haskell-nix.callPackage ./unit.nix {};
in runCommand "unit-tests" { passthru = { inherit tests; }; }
(lib.concatMapStringsSep "\n" (t: "echo ${t.name} failed") tests +
(if builtins.length tests == 0 then "\ntouch $out" else "\nexit 1"));
}))
unitTests =
let
tests = haskell-nix.callPackage ./unit.nix {};
testsFailedEcho = lib.concatMapStringsSep "\n" (t: "echo ${t.name} failed") tests;
testsFinalLine = if builtins.length tests == 0 then "\ntouch $out" else "\nexit 1";
testsScript = testsFailedEcho + testsFinalLine;
in
runCommand "unit-tests" { passthru = { inherit tests; }; } testsScript;

# All tests.
allTests = {
cabal-simple = haskell-nix.callPackage ./cabal-simple { inherit util; };
cabal-simple-prof = haskell-nix.callPackage ./cabal-simple-prof { inherit util; };
cabal-sublib = haskell-nix.callPackage ./cabal-sublib { inherit util; };
cabal-22 = haskell-nix.callPackage ./cabal-22 { inherit util; };
with-packages = haskell-nix.callPackage ./with-packages { inherit util; };
builder-haddock = haskell-nix.callPackage ./builder-haddock {};
stack-simple = haskell-nix.callPackage ./stack-simple {};
stack-local-resolver = haskell-nix.callPackage ./stack-local-resolver {};
snapshots = haskell-nix.callPackage ./snapshots {};
shell-for = haskell-nix.callPackage ./shell-for {};
shell-for-setup-deps = haskell-nix.callPackage ./shell-for-setup-deps {};
setup-deps = import ./setup-deps { inherit pkgs; };
callStackToNix = haskell-nix.callPackage ./call-stack-to-nix {};
callCabalProjectToNix = haskell-nix.callPackage ./call-cabal-project-to-nix {};
cabal-source-repo = haskell-nix.callPackage ./cabal-source-repo {};
buildable = haskell-nix.callPackage ./buildable {};
project-flags-cabal = haskell-nix.callPackage ./project-flags/cabal.nix {};
project-flags-stack = haskell-nix.callPackage ./project-flags/stack.nix {};
fully-static = haskell-nix.callPackage ./fully-static { inherit (pkgs) buildPackages; };
ghc-options-cabal = haskell-nix.callPackage ./ghc-options/cabal.nix {};
ghc-options-stack = haskell-nix.callPackage ./ghc-options/stack.nix {};
exe-only = haskell-nix.callPackage ./exe-only { inherit util; };
stack-source-repo = haskell-nix.callPackage ./stack-source-repo {};

unit = unitTests;
};

# This is the same as allTests, but filter out all the key/vaules from the
# tests other than the "ifdInputs" key if the input ifdLevel is less than 3.
allTestsRemoveIfdLTLevel3 = ifdLevel:
filterNonIfdInputsValuesLTLevel3 ifdLevel allTests;

# This is the same as allTestsRemoveIfdLTLevel3, but make sure
# recurseForDerivations is set on all child values under the
# ifdInputs key.
allTestsWithIfdInputs = ifdLevel:
addIfdInputsToVal (allTestsRemoveIfdLTLevel3 ifdLevel);

# This is the same as allTestsWithIfdInputs, but returns an empty attribute set
# if the input ifdLevel is 0 or 1.
#
# Here is the result based on the input ifdLevel:
#
# - input ifdLevel is 0 or 1: {}
# - input ifdLevel is 2: filter out everything from the children of allTests
# except for the ifdInputs attribute
# - input ifdLevel is 3 or greater: return allTests
optionalIfdTests = ifdLevel:
pkgs.lib.optionalAttrs (ifdLevel > 1) (allTestsWithIfdInputs ifdLevel);
in

pkgs.recurseIntoAttrs {
haskellNixRoots = haskell-nix.haskellNixRoots' ifdLevel;
} // optionalIfdTests ifdLevel

## more possible test cases
# 1. fully static linking
Expand Down