summary refs log tree commit diff
path: root/pkgs/build-support/rust/build-rust-crate/test/default.nix
diff options
context:
space:
mode:
authorAndreas Rammhold <andreas@rammhold.de>2019-12-17 21:15:53 +0100
committerAndreas Rammhold <andreas@rammhold.de>2020-01-07 11:57:34 +0100
commita3a51763f918d53278db8d16d87f7adbca77e105 (patch)
tree53e09c7323c9adc0130fe1d8ea34c5f611e36c7d /pkgs/build-support/rust/build-rust-crate/test/default.nix
parent2c4c7c929cfd5b526e52314f23bf0d94e998979a (diff)
downloadnixpkgs-a3a51763f918d53278db8d16d87f7adbca77e105.tar
nixpkgs-a3a51763f918d53278db8d16d87f7adbca77e105.tar.gz
nixpkgs-a3a51763f918d53278db8d16d87f7adbca77e105.tar.bz2
nixpkgs-a3a51763f918d53278db8d16d87f7adbca77e105.tar.lz
nixpkgs-a3a51763f918d53278db8d16d87f7adbca77e105.tar.xz
nixpkgs-a3a51763f918d53278db8d16d87f7adbca77e105.tar.zst
nixpkgs-a3a51763f918d53278db8d16d87f7adbca77e105.zip
buildRustCrate: add `buildTests` flag to tell rustc to build tests instead of binaries
This helps us instruct rustc to build tests instead of binaries. The
actual build will then ONLY produce test executables. This is a first
step towards having rust crate tests within nixpkgs.

We default back to only a single output in test cases since that is the
only reasonable thing to do here.

Producing libraries or binaries in addition to tests would theoretically
be feasible but usually generates different dependency trees. It is very
common to have some libraries in `[dev-depdendencies]` within Cargo.toml
just for your tests. To not start mixing things up going with a
dedicated derivation for the test build sounds like the best choice for
now.

To use this you must provide a proper test dependency chain to
`buildRustCrate` (as you would usually do with your non-test inputs).
And then set the `buildTests` attribute to `true`. The derivation will
then contain all tests that were built in `$out/tests`. All common test
patterns and directories should be supported and tested by this change.

Below is an example how you would run a single test from the derivation.
This commit contains some more examples in the `buildRustCrateTests`
attribute set that might be helpful.

```
let
  drv = buildRustCrate {
     …
     buildTests true;
  };
in runCommand "test-my-crate" {} ''
  touch $out
  exec ${drv}/tests/my-test
''
```
Diffstat (limited to 'pkgs/build-support/rust/build-rust-crate/test/default.nix')
-rw-r--r--pkgs/build-support/rust/build-rust-crate/test/default.nix119
1 files changed, 108 insertions, 11 deletions
diff --git a/pkgs/build-support/rust/build-rust-crate/test/default.nix b/pkgs/build-support/rust/build-rust-crate/test/default.nix
index 4a90cf442a4..f0f1ed4d1eb 100644
--- a/pkgs/build-support/rust/build-rust-crate/test/default.nix
+++ b/pkgs/build-support/rust/build-rust-crate/test/default.nix
@@ -29,10 +29,30 @@ let
     }
   '';
 
+  mkTestFile = name: functionName: mkFile name ''
+    #[cfg(test)]
+    #[test]
+    fn ${functionName}() {
+      assert!(true);
+    }
+  '';
+  mkTestFileWithMain = name: functionName: mkFile name ''
+    #[cfg(test)]
+    #[test]
+    fn ${functionName}() {
+      assert!(true);
+    }
+
+    fn main() {}
+  '';
+
+
   mkLib = name: mkFile name "pub fn test() -> i32 { return 23; }";
 
   mkTest = crateArgs: let
-    crate = mkCrate crateArgs;
+    crate = mkCrate (builtins.removeAttrs crateArgs ["expectedTestOutput"]);
+    hasTests = crateArgs.buildTests or false;
+    expectedTestOutputs = crateArgs.expectedTestOutputs or null;
     binaries = map (v: ''"${v.name}"'') (crateArgs.crateBin or []);
     isLib = crateArgs ? libName || crateArgs ? libPath;
     crateName = crateArgs.crateName or "nixtestcrate";
@@ -44,16 +64,28 @@ let
       src = mkBinExtern "src/main.rs" libName;
     };
 
-    in runCommand "run-buildRustCrate-${crateName}-test" {
-      nativeBuildInputs = [ crate ];
-    } ''
-      ${lib.concatStringsSep "\n" binaries}
-      ${lib.optionalString isLib ''
-          test -e ${crate}/lib/*.rlib || exit 1
-          ${libTestBinary}/bin/run-test-${crateName}
-      ''}
-      touch $out
-  '';
+    in
+      assert expectedTestOutputs != null -> hasTests;
+      assert hasTests -> expectedTestOutputs != null;
+
+      runCommand "run-buildRustCrate-${crateName}-test" {
+        nativeBuildInputs = [ crate ];
+      } (if !hasTests then ''
+          ${lib.concatStringsSep "\n" binaries}
+          ${lib.optionalString isLib ''
+              test -e ${crate}/lib/*.rlib || exit 1
+              ${libTestBinary}/bin/run-test-${crateName}
+          ''}
+          touch $out
+        '' else ''
+          for file in ${crate}/tests/*; do
+            $file 2>&1 >> $out
+          done
+          set -e
+          ${lib.concatMapStringsSep "\n" (o: "grep '${o}' $out || {  echo 'output \"${o}\" not found in:'; cat $out; exit 23; }") expectedTestOutputs}
+        ''
+      );
+
   in rec {
 
   tests = let
@@ -85,6 +117,71 @@ let
         dependencies = [ (mkCrate { crateName = "foo"; libName = "foolib"; src = mkLib "src/lib.rs"; }) ];
         crateRenames = { "foo" = "foo_renamed"; };
       };
+      rustLibTestsDefault = {
+        src = mkTestFile "src/lib.rs" "baz";
+        buildTests = true;
+        expectedTestOutputs = [ "test baz ... ok" ];
+      };
+      rustLibTestsCustomLibName = {
+        libName = "test_lib";
+        src = mkTestFile "src/test_lib.rs" "foo";
+        buildTests = true;
+        expectedTestOutputs = [ "test foo ... ok" ];
+      };
+      rustLibTestsCustomLibPath = {
+        libPath = "src/test_path.rs";
+        src = mkTestFile "src/test_path.rs" "bar";
+        buildTests = true;
+        expectedTestOutputs = [ "test bar ... ok" ];
+      };
+      rustLibTestsCustomLibPathWithTests = {
+        libPath = "src/test_path.rs";
+        src = symlinkJoin {
+          name = "rust-lib-tests-custom-lib-path-with-tests-dir";
+          paths = [
+            (mkTestFile "src/test_path.rs" "bar")
+            (mkTestFile "tests/something.rs" "something")
+          ];
+        };
+        buildTests = true;
+        expectedTestOutputs = [
+          "test bar ... ok"
+          "test something ... ok"
+        ];
+      };
+      rustBinTestsCombined = {
+        src = symlinkJoin {
+          name = "rust-bin-tests-combined";
+          paths = [
+            (mkTestFileWithMain "src/main.rs" "src_main")
+            (mkTestFile "tests/foo.rs" "tests_foo")
+            (mkTestFile "tests/bar.rs" "tests_bar")
+          ];
+        };
+        buildTests = true;
+        expectedTestOutputs = [
+          "test src_main ... ok"
+          "test tests_foo ... ok"
+          "test tests_bar ... ok"
+        ];
+      };
+      rustBinTestsSubdirCombined = {
+        src = symlinkJoin {
+          name = "rust-bin-tests-subdir-combined";
+          paths = [
+            (mkTestFileWithMain "src/main.rs" "src_main")
+            (mkTestFile "tests/foo/main.rs" "tests_foo")
+            (mkTestFile "tests/bar/main.rs" "tests_bar")
+          ];
+        };
+        buildTests = true;
+        expectedTestOutputs = [
+          "test src_main ... ok"
+          "test tests_foo ... ok"
+          "test tests_bar ... ok"
+        ];
+      };
+
     };
     brotliCrates = (callPackage ./brotli-crates.nix {});
   in lib.mapAttrs (key: value: mkTest (value // lib.optionalAttrs (!value?crateName) { crateName = key; })) cases // {