From 2b414e1c1553c1ff678d172f99da227670b8f68e Mon Sep 17 00:00:00 2001 From: Judson Date: Mon, 1 May 2017 09:07:42 -0700 Subject: Test harnesses --- .../development/ruby-modules/bundler-env/basic.nix | 42 ++++++++------- .../ruby-modules/bundler-env/default.nix | 47 ++++++++++------ .../ruby-modules/bundler-env/functions.nix | 5 +- .../ruby-modules/bundler-env/tap-support.nix | 20 +++++++ pkgs/development/ruby-modules/bundler-env/test.nix | 49 +++++++++++++++++ .../ruby-modules/bundler-env/testing.nix | 62 ++++++++++++++++++++++ 6 files changed, 189 insertions(+), 36 deletions(-) create mode 100644 pkgs/development/ruby-modules/bundler-env/tap-support.nix create mode 100644 pkgs/development/ruby-modules/bundler-env/test.nix create mode 100644 pkgs/development/ruby-modules/bundler-env/testing.nix (limited to 'pkgs/development/ruby-modules/bundler-env') diff --git a/pkgs/development/ruby-modules/bundler-env/basic.nix b/pkgs/development/ruby-modules/bundler-env/basic.nix index 705c8dabd63..7f96a8ce0e7 100644 --- a/pkgs/development/ruby-modules/bundler-env/basic.nix +++ b/pkgs/development/ruby-modules/bundler-env/basic.nix @@ -5,11 +5,11 @@ }@defs: { - drvName -, pname + pname , gemfile , lockfile , gemset +, gemdir , ruby ? defs.ruby , gemConfig ? defaultGemConfig , postBuild ? null @@ -20,14 +20,13 @@ , ... }@args: -with (import ./functions.nix); +with (import ./functions.nix { inherit lib ruby gemConfig groups; }); let - mainGem = gems."${pname}" or (throw "bundlerEnv: gem ${pname} not found"); importedGemset = import gemset; - filteredGemset = lib.filterAttrs (name: attrs: platformMatches attrs && groupMatches attrs) importedGemset; + filteredGemset = filterGemset importedGemset; configuredGemset = lib.flip lib.mapAttrs filteredGemset (name: attrs: applyGemConfigs (attrs // { inherit ruby; gemName = name; }) @@ -47,14 +46,18 @@ let '' else "" ); - maybeCopyAll = main: if main == null then "" else copyIfBundledByPath main; + maybeCopyAll = pname: if pname == null then "" else + let + mainGem = gems."${pname}" or (throw "bundlerEnv: gem ${pname} not found"); + in + copyIfBundledByPath mainGem; # We have to normalize the Gemfile.lock, otherwise bundler tries to be # helpful by doing so at run time, causing executables to immediately bail # out. Yes, I'm serious. confFiles = runCommand "gemfile-and-lockfile" {} '' mkdir -p $out - ${maybeCopyAll mainGem} + ${maybeCopyAll pname} cp ${gemfile} $out/Gemfile || ls -l $out/Gemfile cp ${lockfile} $out/Gemfile.lock || ls -l $out/Gemfile.lock ''; @@ -71,13 +74,10 @@ let envPaths = lib.attrValues gems ++ lib.optional (!hasBundler) bundler; - # binPaths = if mainGem != null then [ mainGem ] else envPaths; - -in - buildEnv { + basicEnv = buildEnv { inherit ignoreCollisions; - name = drvName; + name = pname; paths = envPaths; pathsToLink = [ "/lib" ]; @@ -90,20 +90,20 @@ in meta = { platforms = ruby.meta.platforms; } // meta; passthru = rec { - inherit ruby bundler gems; + inherit ruby bundler gems; # drvName; wrappedRuby = stdenv.mkDerivation { - name = "wrapped-ruby-${drvName}"; + name = "wrapped-ruby-${pname}"; nativeBuildInputs = [ makeWrapper ]; buildCommand = '' mkdir -p $out/bin for i in ${ruby}/bin/*; do makeWrapper "$i" $out/bin/$(basename "$i") \ --set BUNDLE_GEMFILE ${confFiles}/Gemfile \ - --set BUNDLE_PATH ${bundlerEnv}/${ruby.gemPath} \ + --set BUNDLE_PATH ${basicEnv}/${ruby.gemPath} \ --set BUNDLE_FROZEN 1 \ - --set GEM_HOME ${bundlerEnv}/${ruby.gemPath} \ - --set GEM_PATH ${bundlerEnv}/${ruby.gemPath} + --set GEM_HOME ${basicEnv}/${ruby.gemPath} \ + --set GEM_PATH ${basicEnv}/${ruby.gemPath} done ''; }; @@ -117,8 +117,8 @@ in require 'bundler/setup' ''; in stdenv.mkDerivation { - name = "${drvName}-interactive-environment"; - nativeBuildInputs = [ wrappedRuby bundlerEnv ]; + name = "${pname}-interactive-environment"; + nativeBuildInputs = [ wrappedRuby basicEnv ]; shellHook = '' export OLD_IRBRC="$IRBRC" export IRBRC=${irbrc} @@ -131,4 +131,6 @@ in ''; }; }; - } + }; +in + basicEnv diff --git a/pkgs/development/ruby-modules/bundler-env/default.nix b/pkgs/development/ruby-modules/bundler-env/default.nix index 5218d7f0c4d..d1fa4785c06 100644 --- a/pkgs/development/ruby-modules/bundler-env/default.nix +++ b/pkgs/development/ruby-modules/bundler-env/default.nix @@ -24,15 +24,13 @@ }@args: let + inherit (import ./functions.nix (defs // args)) genStubsScript; + drvName = if name != null then name - else if pname != null then "${toString pname}-${mainGem.version}" + else if pname != null then "${toString pname}-${basicEnv.gems."${pname}".version}" else throw "bundlerEnv: either pname or name must be set"; - mainGem = - if pname == null then null - else gems."${pname}" or (throw "bundlerEnv: gem ${pname} not found"); - gemfile' = if gemfile == null then gemdir + "/Gemfile" else gemfile; @@ -45,12 +43,13 @@ let if gemset == null then gemdir + "/gemset.nix" else gemset; - envPaths = lib.attrValues gems ++ lib.optional (!hasBundler) bundler; - - binPaths = if mainGem != null then [ mainGem ] else envPaths; - - basicEnv = import ./basic args // { inherit drvName pname gemfile lockfile gemset; }; + basicEnv = (callPackage ./basic.nix {}) (args // { inherit pname gemdir; + gemfile = gemfile'; + lockfile = lockfile'; + gemset = gemset'; + }); + inherit (basicEnv) envPaths; # Idea here is a mkDerivation that gen-bin-stubs new stubs "as specified" - # either specific executables or the bin/ for certain gem(s), but # incorporates the basicEnv as a requirement so that its $out is in our path. @@ -63,8 +62,26 @@ let # The basicEnv should be put into passthru so that e.g. nix-shell can use it. in - (linkFarm drvName entries) // { - passthru = { - inherit basicEnv; - }; - } + if builtins.trace "pname: ${toString pname}" pname == null then + basicEnv // { inherit name; } + else + (buildEnv { + inherit ignoreCollisions; + + name = builtins.trace "name: ${toString drvName}" drvName; + + paths = envPaths; + pathsToLink = [ "/lib" ]; + + postBuild = genStubsScript defs // args // { + inherit bundler; + confFiles = basicEnv.confFiles; + binPaths = [ basicEnv.mainGem ]; + } + lib.optionalString (postBuild != null) postBuild; + + meta = { platforms = ruby.meta.platforms; } // meta; + passthru = basicEnv.passthru // { + inherit basicEnv; + inherit (basicEnv) env; + }; + }) diff --git a/pkgs/development/ruby-modules/bundler-env/functions.nix b/pkgs/development/ruby-modules/bundler-env/functions.nix index a2d17be4701..75dd276f663 100644 --- a/pkgs/development/ruby-modules/bundler-env/functions.nix +++ b/pkgs/development/ruby-modules/bundler-env/functions.nix @@ -1,4 +1,7 @@ +{ lib, ruby, groups, gemConfig, ... }: rec { + filterGemset = gemset: lib.filterAttrs (name: attrs: platformMatches attrs && groupMatches attrs) gemset; + platformMatches = attrs: ( !(attrs ? "platforms") || builtins.any (platform: @@ -17,7 +20,7 @@ rec { then attrs // gemConfig."${attrs.gemName}" attrs else attrs); - genStubsScript = { lib, ruby, confFile, bundler, groups, binPaths }@args: '' + genStubsScript = { lib, ruby, confFiles, bundler, groups, binPaths }: '' ${ruby}/bin/ruby ${./gen-bin-stubs.rb} \ "${ruby}/bin/ruby" \ "${confFiles}/Gemfile" \ diff --git a/pkgs/development/ruby-modules/bundler-env/tap-support.nix b/pkgs/development/ruby-modules/bundler-env/tap-support.nix new file mode 100644 index 00000000000..ba576683d37 --- /dev/null +++ b/pkgs/development/ruby-modules/bundler-env/tap-support.nix @@ -0,0 +1,20 @@ +with builtins; +let + withIndexes = list: genList (idx: (elemAt list idx) // {index = idx;}) (length list); + + testLine = report: "${okStr report} ${toString report.index} ${report.description}" + testDirective report + testYaml report; + + testDirective = report: ""; + + testYaml = report: ""; + + okStr = { result, ...}: if result == "pass" then "ok" else "not ok"; +in + { + output = reports: '' + TAP version 13 + 1..${toString (length reports)}'' + (foldl' (l: r: l + "\n" + r) "" (map testLine (withIndexes reports))) + '' + + # Finished at ${toString currentTime} + ''; + } diff --git a/pkgs/development/ruby-modules/bundler-env/test.nix b/pkgs/development/ruby-modules/bundler-env/test.nix new file mode 100644 index 00000000000..3f77eb1fb43 --- /dev/null +++ b/pkgs/development/ruby-modules/bundler-env/test.nix @@ -0,0 +1,49 @@ +{ writeText, lib, ruby, defaultGemConfig, callPackage }: +let + test = import ./testing.nix; + tap = import ./tap-support.nix; + + bundlerEnv = callPackage ./default.nix {}; + + testConfigs = { + groups = ["default"]; + gemConfig = defaultGemConfig; + confFiles = "./testConfs"; + }; + functions = (import ./functions.nix ({ inherit lib ruby; } // testConfigs)); + + should = { + equal = expected: actual: + if actual == expected then + (test.passed "= ${toString expected}") else + (test.failed "'${toString actual}'(${builtins.typeOf actual}) != '${toString expected}'(${builtins.typeOf expected})"); + + beASet = actual: + if builtins.isAttrs actual then + (test.passed "is a set") else + (test.failed "is not a set, was ${builtins.typeOf actual}: ${toString actual}"); + }; + + justName = bundlerEnv { + name = "test"; + gemset = ./test/gemset.nix; + }; + + pnamed = bundlerEnv { + pname = "test"; + gemset = ./test/gemset.nix; + }; + + results = builtins.concatLists [ + (test.run "Filter empty gemset" {} (set: functions.filterGemset set == {})) + (test.run "bundlerEnv { name }" justName { + name = should.equal "test"; + }) + (test.run "bundlerEnv { pname }" pnamed + { + name = should.equal "test-0.1.2"; + env = should.beASet; + }) + ]; +in + writeText "test-results.tap" (tap.output results) diff --git a/pkgs/development/ruby-modules/bundler-env/testing.nix b/pkgs/development/ruby-modules/bundler-env/testing.nix new file mode 100644 index 00000000000..43d10fca044 --- /dev/null +++ b/pkgs/development/ruby-modules/bundler-env/testing.nix @@ -0,0 +1,62 @@ +with builtins; +let + /* + underTest = { + x = { + a = 1; + b = "2"; + }; + }; + + tests = [ + (root: false) + { + x = [ + (set: true) + { + a = (a: a > 1); + b = (b: b == "3"); + } + ]; + } + ]; + + results = run "Examples" underTest tests; + */ + + passed = desc: { + result = "pass"; + description = desc; + }; + + failed = desc: { + result = "failed"; + description = desc; + }; + + prefixName = name: res: { + inherit (res) result; + description = "${name}: ${res.description}"; + }; + + run = name: under: tests: if isList tests then + (concatLists (map (run name under) tests)) + else if isAttrs tests then + (concatLists (map ( + subName: run (name + "." + subName) (if hasAttr subName under then getAttr subName under else "") (getAttr subName tests) + ) (attrNames tests))) + else if isFunction tests then + let + res = tests under; + in + if isBool res then + [ + (prefixName name (if tests under then passed "passed" else failed "failed")) + ] + else + [ (prefixName name res) ] + else [ + failed (name ": not a function, list or set") + ]; +in + { inherit run passed failed; } -- cgit 1.4.1