anvil-editor: init at 0.4
[NixPkgs.git] / pkgs / build-support / rust / build-rust-crate / test / default.nix
blob6069ef802dde28a130adc7d860a244e587e7cfee
1 { lib
2 , buildPackages
3 , buildRustCrate
4 , callPackage
5 , releaseTools
6 , runCommand
7 , runCommandCC
8 , stdenv
9 , symlinkJoin
10 , writeTextFile
11 , pkgsCross
14 let
15   mkCrate = buildRustCrate: args: let
16     p = {
17       crateName = "nixtestcrate";
18       version = "0.1.0";
19       authors = [ "Test <test@example.com>" ];
20     } // args;
21   in buildRustCrate p;
22   mkHostCrate = mkCrate buildRustCrate;
24   mkCargoToml =
25     { name, crateVersion ? "0.1.0", path ? "Cargo.toml" }:
26       mkFile path ''
27         [package]
28         name = ${builtins.toJSON name}
29         version = ${builtins.toJSON crateVersion}
30       '';
32   mkFile = destination: text: writeTextFile {
33     name = "src";
34     destination = "/${destination}";
35     inherit text;
36   };
38   mkBin = name: mkFile name ''
39     use std::env;
40     fn main() {
41       let name: String = env::args().nth(0).unwrap();
42       println!("executed {}", name);
43     }
44   '';
46   mkBinExtern = name: extern: mkFile name ''
47     extern crate ${extern};
48     fn main() {
49       assert_eq!(${extern}::test(), 23);
50     }
51   '';
53   mkTestFile = name: functionName: mkFile name ''
54     #[cfg(test)]
55     #[test]
56     fn ${functionName}() {
57       assert!(true);
58     }
59   '';
60   mkTestFileWithMain = name: functionName: mkFile name ''
61     #[cfg(test)]
62     #[test]
63     fn ${functionName}() {
64       assert!(true);
65     }
67     fn main() {}
68   '';
71   mkLib = name: mkFile name "pub fn test() -> i32 { return 23; }";
73   mkTest = crateArgs: let
74     crate = mkHostCrate (builtins.removeAttrs crateArgs ["expectedTestOutput"]);
75     hasTests = crateArgs.buildTests or false;
76     expectedTestOutputs = crateArgs.expectedTestOutputs or null;
77     binaries = map (v: lib.escapeShellArg v.name) (crateArgs.crateBin or []);
78     isLib = crateArgs ? libName || crateArgs ? libPath;
79     crateName = crateArgs.crateName or "nixtestcrate";
80     libName = crateArgs.libName or crateName;
82     libTestBinary = if !isLib then null else mkHostCrate {
83       crateName = "run-test-${crateName}";
84       dependencies = [ crate ];
85       src = mkBinExtern "src/main.rs" libName;
86     };
88     in
89       assert expectedTestOutputs != null -> hasTests;
90       assert hasTests -> expectedTestOutputs != null;
92       runCommand "run-buildRustCrate-${crateName}-test" {
93         nativeBuildInputs = [ crate ];
94       } (if !hasTests then ''
95           ${lib.concatMapStringsSep "\n" (binary:
96             # Can't actually run the binary when cross-compiling
97             (lib.optionalString (stdenv.hostPlatform != stdenv.buildPlatform) "type ") + binary
98           ) binaries}
99           ${lib.optionalString isLib ''
100               test -e ${crate}/lib/*.rlib || exit 1
101               ${lib.optionalString (stdenv.hostPlatform != stdenv.buildPlatform) "test -x "} \
102                 ${libTestBinary}/bin/run-test-${crateName}
103           ''}
104           touch $out
105         '' else if stdenv.hostPlatform == stdenv.buildPlatform then ''
106           for file in ${crate}/tests/*; do
107             $file 2>&1 >> $out
108           done
109           set -e
110           ${lib.concatMapStringsSep "\n" (o: "grep '${o}' $out || {  echo 'output \"${o}\" not found in:'; cat $out; exit 23; }") expectedTestOutputs}
111         '' else ''
112           for file in ${crate}/tests/*; do
113             test -x "$file"
114           done
115           touch "$out"
116         ''
117       );
119     /* Returns a derivation that asserts that the crate specified by `crateArgs`
120        has the specified files as output.
122        `name` is used as part of the derivation name that performs the checking.
124        `mkCrate` can be used to override the `mkCrate` call/implementation to use to
125        override the `buildRustCrate`, useful for cross compilation. Uses `mkHostCrate` by default.
127        `crateArgs` is passed to `mkCrate` to build the crate with `buildRustCrate`
129        `expectedFiles` contains a list of expected file paths in the output. E.g.
130        `[ "./bin/my_binary" ]`.
132        `output` specifies the name of the output to use. By default, the default
133        output is used but e.g. `output = "lib";` will cause the lib output
134        to be checked instead. You do not need to specify any directories.
135      */
136     assertOutputs = { name, mkCrate ? mkHostCrate, crateArgs, expectedFiles, output? null, }:
137       assert (builtins.isString name);
138       assert (builtins.isAttrs crateArgs);
139       assert (builtins.isList expectedFiles);
141       let
142         crate = mkCrate (builtins.removeAttrs crateArgs ["expectedTestOutput"]);
143         crateOutput = if output == null then crate else crate."${output}";
144         expectedFilesFile = writeTextFile {
145           name = "expected-files-${name}";
146           text =
147             let sorted = builtins.sort (a: b: a<b) expectedFiles;
148                 concatenated = builtins.concatStringsSep "\n" sorted;
149             in "${concatenated}\n";
150         };
151       in
152       runCommand "assert-outputs-${name}" {
153       } (''
154       local actualFiles=$(mktemp)
156       cd "${crateOutput}"
157       find . -type f \
158         | sort \
159       ''
160       # sed out the hash because it differs per platform
161       + ''
162         | sed 's/-${crate.metadata}//g' \
163         > "$actualFiles"
164       diff -q ${expectedFilesFile} "$actualFiles" > /dev/null || {
165         echo -e "\033[0;1;31mERROR: Difference in expected output files in ${crateOutput} \033[0m" >&2
166         echo === Got:
167         sed -e 's/^/  /' $actualFiles
168         echo === Expected:
169         sed -e 's/^/  /' ${expectedFilesFile}
170         echo === Diff:
171         diff -u ${expectedFilesFile} $actualFiles |\
172           tail -n +3 |\
173           sed -e 's/^/  /'
174         exit 1
175       }
176       touch $out
177       '')
178       ;
180   in rec {
182   tests = let
183     cases = rec {
184       libPath =  { libPath = "src/my_lib.rs"; src = mkLib "src/my_lib.rs"; };
185       srcLib =  { src = mkLib "src/lib.rs"; };
187       # This used to be supported by cargo but as of 1.40.0 I can't make it work like that with just cargo anymore.
188       # This might be a regression or deprecated thing they finally removed…
189       # customLibName =  { libName = "test_lib"; src = mkLib "src/test_lib.rs"; };
190       # rustLibTestsCustomLibName = {
191       #   libName = "test_lib";
192       #   src = mkTestFile "src/test_lib.rs" "foo";
193       #   buildTests = true;
194       #   expectedTestOutputs = [ "test foo ... ok" ];
195       # };
197       customLibNameAndLibPath =  { libName = "test_lib"; libPath = "src/best-lib.rs"; src = mkLib "src/best-lib.rs"; };
198       crateBinWithPath =  { crateBin = [{ name = "test_binary1"; path = "src/foobar.rs"; }]; src = mkBin "src/foobar.rs"; };
199       crateBinNoPath1 =  { crateBin = [{ name = "my-binary2"; }]; src = mkBin "src/my_binary2.rs"; };
200       crateBinNoPath2 =  {
201         crateBin = [{ name = "my-binary3"; } { name = "my-binary4"; }];
202         src = symlinkJoin {
203           name = "buildRustCrateMultipleBinariesCase";
204           paths = [ (mkBin "src/bin/my_binary3.rs") (mkBin "src/bin/my_binary4.rs") ];
205         };
206       };
207       crateBinNoPath3 =  { crateBin = [{ name = "my-binary5"; }]; src = mkBin "src/bin/main.rs"; };
208       crateBinNoPath4 =  { crateBin = [{ name = "my-binary6"; }]; src = mkBin "src/main.rs";};
209       crateBinRename1 = {
210         crateBin = [{ name = "my-binary-rename1"; }];
211         src = mkBinExtern "src/main.rs" "foo_renamed";
212         dependencies = [ (mkHostCrate { crateName = "foo"; src = mkLib "src/lib.rs"; }) ];
213         crateRenames = { "foo" = "foo_renamed"; };
214       };
215       crateBinRename2 = {
216         crateBin = [{ name = "my-binary-rename2"; }];
217         src = mkBinExtern "src/main.rs" "foo_renamed";
218         dependencies = [ (mkHostCrate { crateName = "foo"; libName = "foolib"; src = mkLib "src/lib.rs"; }) ];
219         crateRenames = { "foo" = "foo_renamed"; };
220       };
221       crateBinRenameMultiVersion = let
222         crateWithVersion = version: mkHostCrate {
223           crateName = "my_lib";
224           inherit version;
225           src = mkFile "src/lib.rs" ''
226             pub const version: &str = "${version}";
227           '';
228         };
229         depCrate01 = crateWithVersion "0.1.2";
230         depCrate02 = crateWithVersion "0.2.1";
231       in {
232         crateName = "my_bin";
233         src = symlinkJoin {
234           name = "my_bin_src";
235           paths = [
236             (mkFile  "src/main.rs" ''
237               #[test]
238               fn my_lib_01() { assert_eq!(lib01::version, "0.1.2"); }
240               #[test]
241               fn my_lib_02() { assert_eq!(lib02::version, "0.2.1"); }
243               fn main() { }
244             '')
245           ];
246         };
247         dependencies = [ depCrate01 depCrate02 ];
248         crateRenames = {
249           "my_lib" = [
250             {
251               version = "0.1.2";
252               rename = "lib01";
253             }
254             {
255               version = "0.2.1";
256               rename = "lib02";
257             }
258           ];
259         };
260         buildTests = true;
261         expectedTestOutputs = [
262           "test my_lib_01 ... ok"
263           "test my_lib_02 ... ok"
264         ];
265       };
266       rustLibTestsDefault = {
267         src = mkTestFile "src/lib.rs" "baz";
268         buildTests = true;
269         expectedTestOutputs = [ "test baz ... ok" ];
270       };
271       rustLibTestsCustomLibPath = {
272         libPath = "src/test_path.rs";
273         src = mkTestFile "src/test_path.rs" "bar";
274         buildTests = true;
275         expectedTestOutputs = [ "test bar ... ok" ];
276       };
277       rustLibTestsCustomLibPathWithTests = {
278         libPath = "src/test_path.rs";
279         src = symlinkJoin {
280           name = "rust-lib-tests-custom-lib-path-with-tests-dir";
281           paths = [
282             (mkTestFile "src/test_path.rs" "bar")
283             (mkTestFile "tests/something.rs" "something")
284           ];
285         };
286         buildTests = true;
287         expectedTestOutputs = [
288           "test bar ... ok"
289           "test something ... ok"
290         ];
291       };
292       rustBinTestsCombined = {
293         src = symlinkJoin {
294           name = "rust-bin-tests-combined";
295           paths = [
296             (mkTestFileWithMain "src/main.rs" "src_main")
297             (mkTestFile "tests/foo.rs" "tests_foo")
298             (mkTestFile "tests/bar.rs" "tests_bar")
299           ];
300         };
301         buildTests = true;
302         expectedTestOutputs = [
303           "test src_main ... ok"
304           "test tests_foo ... ok"
305           "test tests_bar ... ok"
306         ];
307       };
308       rustBinTestsSubdirCombined = {
309         src = symlinkJoin {
310           name = "rust-bin-tests-subdir-combined";
311           paths = [
312             (mkTestFileWithMain "src/main.rs" "src_main")
313             (mkTestFile "tests/foo/main.rs" "tests_foo")
314             (mkTestFile "tests/bar/main.rs" "tests_bar")
315           ];
316         };
317         buildTests = true;
318         expectedTestOutputs = [
319           "test src_main ... ok"
320           "test tests_foo ... ok"
321           "test tests_bar ... ok"
322         ];
323       };
324       linkAgainstRlibCrate = {
325         crateName = "foo";
326         src = mkFile  "src/main.rs" ''
327           extern crate somerlib;
328           fn main() {}
329         '';
330         dependencies = [
331           (mkHostCrate {
332             crateName = "somerlib";
333             type = [ "rlib" ];
334             src = mkLib "src/lib.rs";
335           })
336         ];
337       };
338       buildScriptDeps = let
339         depCrate = buildRustCrate: boolVal: mkCrate buildRustCrate {
340           crateName = "bar";
341           src = mkFile "src/lib.rs" ''
342             pub const baz: bool = ${boolVal};
343           '';
344         };
345       in {
346         crateName = "foo";
347         src = symlinkJoin {
348           name = "build-script-and-main";
349           paths = [
350             (mkFile  "src/main.rs" ''
351               extern crate bar;
352               #[cfg(test)]
353               #[test]
354               fn baz_false() { assert!(!bar::baz); }
355               fn main() { }
356             '')
357             (mkFile  "build.rs" ''
358               extern crate bar;
359               fn main() { assert!(bar::baz); }
360             '')
361           ];
362         };
363         buildDependencies = [ (depCrate buildPackages.buildRustCrate "true") ];
364         dependencies = [ (depCrate buildRustCrate "false") ];
365         buildTests = true;
366         expectedTestOutputs = [ "test baz_false ... ok" ];
367       };
368       buildScriptFeatureEnv = {
369         crateName = "build-script-feature-env";
370         features = [ "some-feature" "crate/another_feature" ];
371         src = symlinkJoin {
372           name = "build-script-feature-env";
373           paths = [
374             (mkFile  "src/main.rs" ''
375               #[cfg(test)]
376               #[test]
377               fn feature_not_visible() {
378                 assert!(std::env::var("CARGO_FEATURE_SOME_FEATURE").is_err());
379                 assert!(option_env!("CARGO_FEATURE_SOME_FEATURE").is_none());
380               }
381               fn main() {}
382             '')
383             (mkFile  "build.rs" ''
384               fn main() {
385                 assert!(std::env::var("CARGO_FEATURE_SOME_FEATURE").is_ok());
386                 assert!(option_env!("CARGO_FEATURE_SOME_FEATURE").is_none());
387               }
388             '')
389           ];
390         };
391         buildTests = true;
392         expectedTestOutputs = [ "test feature_not_visible ... ok" ];
393       };
394       # Regression test for https://github.com/NixOS/nixpkgs/pull/88054
395       # Build script output should be rewritten as valid env vars.
396       buildScriptIncludeDirDeps = let
397         depCrate = mkHostCrate {
398           crateName = "bar";
399           src = symlinkJoin {
400             name = "build-script-and-include-dir-bar";
401             paths = [
402               (mkFile  "src/lib.rs" ''
403                 fn main() { }
404               '')
405               (mkFile  "build.rs" ''
406                 use std::path::PathBuf;
407                 fn main() { println!("cargo:include-dir={}/src", std::env::current_dir().unwrap_or(PathBuf::from(".")).to_str().unwrap()); }
408               '')
409             ];
410           };
411         };
412       in {
413         crateName = "foo";
414         src = symlinkJoin {
415           name = "build-script-and-include-dir-foo";
416           paths = [
417             (mkFile  "src/main.rs" ''
418               fn main() { }
419             '')
420             (mkFile  "build.rs" ''
421               fn main() { assert!(std::env::var_os("DEP_BAR_INCLUDE_DIR").is_some()); }
422             '')
423           ];
424         };
425         buildDependencies = [ depCrate ];
426         dependencies = [ depCrate ];
427       };
428       # Support new invocation prefix for build scripts `cargo::`
429       # https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script
430       buildScriptInvocationPrefix = let
431         depCrate = buildRustCrate: mkCrate buildRustCrate {
432           crateName = "bar";
433           src = mkFile "build.rs" ''
434               fn main() {
435                 // Old invocation prefix
436                 // We likely won't see be mixing these syntaxes in the same build script in the wild.
437                 println!("cargo:key_old=value_old");
439                 // New invocation prefix
440                 println!("cargo::metadata=key=value");
441                 println!("cargo::metadata=key_complex=complex(value)");
442               }
443           '';
444         };
445       in {
446         crateName = "foo";
447         src = symlinkJoin {
448           name = "build-script-and-main-invocation-prefix";
449           paths = [
450             (mkFile  "src/main.rs" ''
451               const BUILDFOO: &'static str = env!("BUILDFOO");
453               #[test]
454               fn build_foo_check() { assert!(BUILDFOO == "yes(check)"); }
456               fn main() { }
457             '')
458             (mkFile  "build.rs" ''
459               use std::env;
460               fn main() {
461                 assert!(env::var_os("DEP_BAR_KEY_OLD").expect("metadata key 'key_old' not set in dependency") == "value_old");
462                 assert!(env::var_os("DEP_BAR_KEY").expect("metadata key 'key' not set in dependency") == "value");
463                 assert!(env::var_os("DEP_BAR_KEY_COMPLEX").expect("metadata key 'key_complex' not set in dependency") == "complex(value)");
465                 println!("cargo::rustc-env=BUILDFOO=yes(check)");
466               }
467             '')
468           ];
469         };
470         buildDependencies = [ (depCrate buildPackages.buildRustCrate) ];
471         dependencies = [ (depCrate buildRustCrate) ];
472         buildTests = true;
473         expectedTestOutputs = [ "test build_foo_check ... ok" ];
474       };
475       # Regression test for https://github.com/NixOS/nixpkgs/issues/74071
476       # Whenevever a build.rs file is generating files those should not be overlayed onto the actual source dir
477       buildRsOutDirOverlay = {
478         src = symlinkJoin {
479           name = "buildrs-out-dir-overlay";
480           paths = [
481             (mkLib "src/lib.rs")
482             (mkFile "build.rs" ''
483               use std::env;
484               use std::ffi::OsString;
485               use std::fs;
486               use std::path::Path;
487               fn main() {
488                 let out_dir = env::var_os("OUT_DIR").expect("OUT_DIR not set");
489                 let out_file = Path::new(&out_dir).join("lib.rs");
490                 fs::write(out_file, "invalid rust code!").expect("failed to write lib.rs");
491               }
492             '')
493           ];
494         };
495       };
496       # Regression test for https://github.com/NixOS/nixpkgs/pull/83379
497       # link flag order should be preserved
498       linkOrder = {
499         src = symlinkJoin {
500           name = "buildrs-out-dir-overlay";
501           paths = [
502             (mkFile "build.rs" ''
503               fn main() {
504                 // in the other order, linkage will fail
505                 println!("cargo:rustc-link-lib=b");
506                 println!("cargo:rustc-link-lib=a");
507               }
508             '')
509             (mkFile "src/main.rs" ''
510               extern "C" {
511                 fn hello_world();
512               }
513               fn main() {
514                 unsafe {
515                   hello_world();
516                 }
517               }
518             '')
519           ];
520         };
521         buildInputs = let
522           compile = name: text: let
523             src = writeTextFile {
524               name = "${name}-src.c";
525               inherit text;
526             };
527           in runCommandCC name {} ''
528             mkdir -p $out/lib
529             # Note: On darwin (which defaults to clang) we have to add
530             # `-undefined dynamic_lookup` as otherwise the compilation fails.
531             $CC -shared \
532               ${lib.optionalString stdenv.hostPlatform.isDarwin "-undefined dynamic_lookup"} \
533               -o $out/lib/${name}${stdenv.hostPlatform.extensions.library} ${src}
534           '';
535           b = compile "libb" ''
536             #include <stdio.h>
538             void hello();
540             void hello_world() {
541               hello();
542               printf(" world!\n");
543             }
544           '';
545           a = compile "liba" ''
546             #include <stdio.h>
548             void hello() {
549               printf("hello");
550             }
551           '';
552         in [ a b ];
553       };
554       rustCargoTomlInSubDir = {
555         # The "workspace_member" can be set to the sub directory with the crate to build.
556         # By default ".", meaning the top level directory is assumed.
557         # Using null will trigger a search.
558         workspace_member = null;
559         src = symlinkJoin rec {
560           name = "find-cargo-toml";
561           paths = [
562             (mkCargoToml { name = "ignoreMe"; })
563             (mkTestFileWithMain "src/main.rs" "ignore_main")
565             (mkCargoToml { name = "rustCargoTomlInSubDir"; path = "subdir/Cargo.toml"; })
566             (mkTestFileWithMain "subdir/src/main.rs" "src_main")
567             (mkTestFile "subdir/tests/foo/main.rs" "tests_foo")
568             (mkTestFile "subdir/tests/bar/main.rs" "tests_bar")
569           ];
570         };
571         buildTests = true;
572         expectedTestOutputs = [
573           "test src_main ... ok"
574           "test tests_foo ... ok"
575           "test tests_bar ... ok"
576         ];
577       };
579       rustCargoTomlInTopDir =
580         let
581           withoutCargoTomlSearch = builtins.removeAttrs rustCargoTomlInSubDir [ "workspace_member" ];
582         in
583           withoutCargoTomlSearch // {
584             expectedTestOutputs = [
585               "test ignore_main ... ok"
586             ];
587           };
588       procMacroInPrelude = {
589         procMacro = true;
590         edition = "2018";
591         src = symlinkJoin {
592           name = "proc-macro-in-prelude";
593           paths = [
594             (mkFile "src/lib.rs" ''
595               use proc_macro::TokenTree;
596             '')
597           ];
598         };
599       };
600     };
601     brotliCrates = (callPackage ./brotli-crates.nix {});
602     rcgenCrates = callPackage ./rcgen-crates.nix {
603       # Suppress deprecation warning
604       buildRustCrate = null;
605     };
606     tests = lib.mapAttrs (key: value: mkTest (value // lib.optionalAttrs (!value?crateName) { crateName = key; })) cases;
607   in tests // rec {
609     crateBinWithPathOutputs = assertOutputs {
610       name="crateBinWithPath";
611       crateArgs = {
612         crateBin = [{ name = "test_binary1"; path = "src/foobar.rs"; }];
613         src = mkBin "src/foobar.rs";
614       };
615       expectedFiles = [
616         "./bin/test_binary1"
617       ];
618     };
620     crateBinWithPathOutputsDebug = assertOutputs {
621       name="crateBinWithPath";
622       crateArgs = {
623         release = false;
624         crateBin = [{ name = "test_binary1"; path = "src/foobar.rs"; }];
625         src = mkBin "src/foobar.rs";
626       };
627       expectedFiles = [
628         "./bin/test_binary1"
629       ] ++ lib.optionals stdenv.hostPlatform.isDarwin [
630         # On Darwin, the debug symbols are in a separate directory.
631         "./bin/test_binary1.dSYM/Contents/Info.plist"
632         "./bin/test_binary1.dSYM/Contents/Resources/DWARF/test_binary1"
633       ];
634     };
636     crateBinNoPath1Outputs = assertOutputs {
637       name="crateBinNoPath1";
638       crateArgs = {
639         crateBin = [{ name = "my-binary2"; }];
640         src = mkBin "src/my_binary2.rs";
641       };
642       expectedFiles = [
643         "./bin/my-binary2"
644       ];
645     };
647     crateLibOutputs = assertOutputs {
648       name="crateLib";
649       output="lib";
650       crateArgs = {
651         libName = "test_lib";
652         type = [ "rlib" ];
653         libPath = "src/lib.rs";
654         src = mkLib "src/lib.rs";
655       };
656       expectedFiles = [
657         "./nix-support/propagated-build-inputs"
658         "./lib/libtest_lib.rlib"
659         "./lib/link"
660       ];
661     };
663     crateLibOutputsDebug = assertOutputs {
664       name="crateLib";
665       output="lib";
666       crateArgs = {
667         release = false;
668         libName = "test_lib";
669         type = [ "rlib" ];
670         libPath = "src/lib.rs";
671         src = mkLib "src/lib.rs";
672       };
673       expectedFiles = [
674         "./nix-support/propagated-build-inputs"
675         "./lib/libtest_lib.rlib"
676         "./lib/link"
677       ];
678     };
680     crateLibOutputsWasm32 = assertOutputs {
681       name = "wasm32-crate-lib";
682       output = "lib";
683       mkCrate = mkCrate pkgsCross.wasm32-unknown-none.buildRustCrate;
684       crateArgs = {
685         libName = "test_lib";
686         type = [ "cdylib" ];
687         libPath = "src/lib.rs";
688         src = mkLib "src/lib.rs";
689       };
690       expectedFiles = [
691         "./nix-support/propagated-build-inputs"
692         "./lib/test_lib.wasm"
693         "./lib/link"
694       ];
695     };
697     brotliTest = let
698       pkg = brotliCrates.brotli_2_5_0 {};
699     in runCommand "run-brotli-test-cmd" {
700       nativeBuildInputs = [ pkg ];
701     } (if stdenv.hostPlatform == stdenv.buildPlatform then ''
702       ${pkg}/bin/brotli -c ${pkg}/bin/brotli > /dev/null && touch $out
703     '' else ''
704       test -x '${pkg}/bin/brotli' && touch $out
705     '');
706     allocNoStdLibTest = let
707       pkg = brotliCrates.alloc_no_stdlib_1_3_0 {};
708     in runCommand "run-alloc-no-stdlib-test-cmd" {
709       nativeBuildInputs = [ pkg ];
710     } ''
711       test -e ${pkg}/bin/example && touch $out
712     '';
713     brotliDecompressorTest = let
714       pkg = brotliCrates.brotli_decompressor_1_3_1 {};
715     in runCommand "run-brotli-decompressor-test-cmd" {
716       nativeBuildInputs = [ pkg ];
717     } ''
718       test -e ${pkg}/bin/brotli-decompressor && touch $out
719     '';
721     rcgenTest = let
722       pkg = rcgenCrates.rootCrate.build;
723     in runCommand "run-rcgen-test-cmd" {
724       nativeBuildInputs = [ pkg ];
725     } (if stdenv.hostPlatform == stdenv.buildPlatform then ''
726       ${pkg}/bin/rcgen && touch $out
727     '' else ''
728       test -x '${pkg}/bin/rcgen' && touch $out
729     '');
730   };
731   test = releaseTools.aggregate {
732     name = "buildRustCrate-tests";
733     meta = {
734       description = "Test cases for buildRustCrate";
735       maintainers = [ ];
736     };
737     constituents = builtins.attrValues tests;
738   };