Add golden effects test
This commit is contained in:
parent
f3b16a6b5d
commit
2bc7345064
@ -1,7 +1,3 @@
|
||||
// makeCWrapper /send/me/flags \
|
||||
--add-flags "-x -y -z" \
|
||||
--add-flags -abc
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
@ -22,4 +18,4 @@ int main(int argc, char **argv) {
|
||||
|
||||
argv[0] = "/send/me/flags";
|
||||
return execv("/send/me/flags", argv);
|
||||
}
|
||||
}
|
||||
|
2
pkgs/test/make-binary-wrapper/add-flags.cmdline
Normal file
2
pkgs/test/make-binary-wrapper/add-flags.cmdline
Normal file
@ -0,0 +1,2 @@
|
||||
--add-flags "-x -y -z" \
|
||||
--add-flags -abc
|
6
pkgs/test/make-binary-wrapper/add-flags.env
Normal file
6
pkgs/test/make-binary-wrapper/add-flags.env
Normal file
@ -0,0 +1,6 @@
|
||||
CWD=SUBST_CWD
|
||||
SUBST_ARGV0
|
||||
-x
|
||||
-y
|
||||
-z
|
||||
-abc
|
@ -1,10 +1,7 @@
|
||||
// makeCWrapper /path/to/some/executable \
|
||||
--argv0 alternative-name
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
argv[0] = "alternative-name";
|
||||
return execv("/path/to/some/executable", argv);
|
||||
return execv("/send/me/flags", argv);
|
||||
}
|
||||
|
1
pkgs/test/make-binary-wrapper/argv0.cmdline
Normal file
1
pkgs/test/make-binary-wrapper/argv0.cmdline
Normal file
@ -0,0 +1 @@
|
||||
--argv0 alternative-name
|
2
pkgs/test/make-binary-wrapper/argv0.env
Normal file
2
pkgs/test/make-binary-wrapper/argv0.env
Normal file
@ -0,0 +1,2 @@
|
||||
CWD=SUBST_CWD
|
||||
alternative-name
|
@ -1,9 +1,7 @@
|
||||
// makeCWrapper /path/to/executable
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
argv[0] = "/path/to/executable";
|
||||
return execv("/path/to/executable", argv);
|
||||
argv[0] = "/send/me/flags";
|
||||
return execv("/send/me/flags", argv);
|
||||
}
|
||||
|
0
pkgs/test/make-binary-wrapper/basic.cmdline
Normal file
0
pkgs/test/make-binary-wrapper/basic.cmdline
Normal file
2
pkgs/test/make-binary-wrapper/basic.env
Normal file
2
pkgs/test/make-binary-wrapper/basic.env
Normal file
@ -0,0 +1,2 @@
|
||||
CWD=SUBST_CWD
|
||||
SUBST_ARGV0
|
@ -1,6 +1,3 @@
|
||||
// makeCWrapper /path/to/executable \
|
||||
--chdir /usr/local/bin
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
@ -8,7 +5,7 @@
|
||||
#define assert_success(e) do { if ((e) < 0) { perror(#e); abort(); } } while (0)
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
assert_success(chdir("/usr/local/bin"));
|
||||
argv[0] = "/path/to/executable";
|
||||
return execv("/path/to/executable", argv);
|
||||
}
|
||||
assert_success(chdir("/tmp/foo"));
|
||||
argv[0] = "/send/me/flags";
|
||||
return execv("/send/me/flags", argv);
|
||||
}
|
||||
|
1
pkgs/test/make-binary-wrapper/chdir.cmdline
Normal file
1
pkgs/test/make-binary-wrapper/chdir.cmdline
Normal file
@ -0,0 +1 @@
|
||||
--chdir /tmp/foo
|
2
pkgs/test/make-binary-wrapper/chdir.env
Normal file
2
pkgs/test/make-binary-wrapper/chdir.env
Normal file
@ -0,0 +1,2 @@
|
||||
CWD=/tmp/foo
|
||||
SUBST_ARGV0
|
@ -1,11 +1,3 @@
|
||||
// makeCWrapper /path/to/executable \
|
||||
--argv0 my-wrapper \
|
||||
--set-default MESSAGE HELLO \
|
||||
--prefix PATH : /usr/bin/ \
|
||||
--suffix PATH : /usr/local/bin/ \
|
||||
--add-flags "-x -y -z" \
|
||||
--set MESSAGE2 WORLD
|
||||
|
||||
#define _GNU_SOURCE /* See feature_test_macros(7) */
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
@ -57,5 +49,5 @@ int main(int argc, char **argv) {
|
||||
argv = argv_tmp;
|
||||
|
||||
argv[0] = "my-wrapper";
|
||||
return execv("/path/to/executable", argv);
|
||||
return execv("/send/me/flags", argv);
|
||||
}
|
||||
|
6
pkgs/test/make-binary-wrapper/combination.cmdline
Normal file
6
pkgs/test/make-binary-wrapper/combination.cmdline
Normal file
@ -0,0 +1,6 @@
|
||||
--argv0 my-wrapper \
|
||||
--set-default MESSAGE HELLO \
|
||||
--prefix PATH : /usr/bin/ \
|
||||
--suffix PATH : /usr/local/bin/ \
|
||||
--add-flags "-x -y -z" \
|
||||
--set MESSAGE2 WORLD
|
8
pkgs/test/make-binary-wrapper/combination.env
Normal file
8
pkgs/test/make-binary-wrapper/combination.env
Normal file
@ -0,0 +1,8 @@
|
||||
MESSAGE=HELLO
|
||||
PATH=/usr/bin/:/usr/local/bin/
|
||||
MESSAGE2=WORLD
|
||||
CWD=SUBST_CWD
|
||||
my-wrapper
|
||||
-x
|
||||
-y
|
||||
-z
|
@ -1,73 +1,54 @@
|
||||
{ lib, stdenv, runCommand, makeBinaryWrapper }:
|
||||
{ lib, coreutils, python3, gcc, writeText, writeScript, runCommand, makeBinaryWrapper }:
|
||||
|
||||
let
|
||||
makeGoldenTest = { name, filename }: stdenv.mkDerivation {
|
||||
name = name;
|
||||
dontUnpack = true;
|
||||
strictDeps = true;
|
||||
nativeBuildInputs = [ makeBinaryWrapper ];
|
||||
phases = [ "installPhase" ];
|
||||
installPhase = ''
|
||||
source ${./golden-test-utils.sh}
|
||||
mkdir -p $out/bin
|
||||
command=$(getInputCommand "${filename}")
|
||||
eval "$command" > "$out/bin/result"
|
||||
'';
|
||||
passthru = {
|
||||
assertion = ''
|
||||
source ${./golden-test-utils.sh}
|
||||
contents=$(getOutputText "${filename}")
|
||||
echo "$contents" | diff $out/bin/result -
|
||||
'';
|
||||
};
|
||||
};
|
||||
tests = {
|
||||
basic = makeGoldenTest { name = "basic"; filename = ./basic.c; };
|
||||
argv0 = makeGoldenTest { name = "argv0"; filename = ./argv0.c; };
|
||||
inherit_argv0 = makeGoldenTest { name = "inherit-argv0"; filename = ./inherit-argv0.c; };
|
||||
env = makeGoldenTest { name = "env"; filename = ./env.c; };
|
||||
invalid_env = makeGoldenTest { name = "invalid-env"; filename = ./invalid-env.c; };
|
||||
prefix = makeGoldenTest { name = "prefix"; filename = ./prefix.c; };
|
||||
suffix = makeGoldenTest { name = "suffix"; filename = ./suffix.c; };
|
||||
add_flags = makeGoldenTest { name = "add-flags"; filename = ./add-flags.c; };
|
||||
chdir = makeGoldenTest { name = "chdir"; filename = ./chdir.c; };
|
||||
combination = makeGoldenTest { name = "combination"; filename = ./combination.c; };
|
||||
};
|
||||
in runCommand "make-binary-wrapper-test" {
|
||||
passthru = tests;
|
||||
meta.platforms = lib.platforms.all;
|
||||
} ''
|
||||
validate() {
|
||||
local name=$1
|
||||
local testout=$2
|
||||
local assertion=$3
|
||||
env = { nativeBuildInputs = [ makeBinaryWrapper gcc ]; };
|
||||
envCheck = runCommand "envcheck" env ''
|
||||
cc -o $out ${./envcheck.c}
|
||||
'';
|
||||
makeGoldenTest = testname: runCommand "test-wrapper_${testname}" env ''
|
||||
mkdir -p /tmp/foo
|
||||
|
||||
echo -n "... $name: " >&2
|
||||
params=$(<"${./.}/${testname}.cmdline")
|
||||
eval "makeCWrapper /send/me/flags $params" > wrapper.c
|
||||
|
||||
local rc=0
|
||||
(out=$testout eval "$assertion") || rc=1
|
||||
diff wrapper.c "${./.}/${testname}.c"
|
||||
|
||||
if [ "$rc" -eq 0 ]; then
|
||||
echo "yes" >&2
|
||||
if [ -f "${./.}/${testname}.env" ]; then
|
||||
eval "makeBinaryWrapper ${envCheck} wrapped $params"
|
||||
env -i ./wrapped > env.txt
|
||||
sed "s#SUBST_ARGV0#${envCheck}#;s#SUBST_CWD#$PWD#" \
|
||||
"${./.}/${testname}.env" > golden-env.txt
|
||||
if ! diff env.txt golden-env.txt; then
|
||||
echo "env/argv should be:"
|
||||
cat golden-env.txt
|
||||
echo "env/argv output is:"
|
||||
cat env.txt
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "no" >&2
|
||||
# without a golden env, we expect the wrapper compilation to fail
|
||||
! eval "makeBinaryWrapper ${envCheck} wrapped $params" &> error.txt
|
||||
fi
|
||||
|
||||
return "$rc"
|
||||
}
|
||||
|
||||
echo "checking whether makeCWrapper works properly... ">&2
|
||||
|
||||
fail=
|
||||
cp wrapper.c $out
|
||||
'';
|
||||
tests = let
|
||||
names = [
|
||||
"add-flags"
|
||||
"argv0"
|
||||
"basic"
|
||||
"chdir"
|
||||
"combination"
|
||||
"env"
|
||||
"inherit-argv0"
|
||||
"invalid-env"
|
||||
"prefix"
|
||||
"suffix"
|
||||
];
|
||||
f = name: lib.nameValuePair name (makeGoldenTest name);
|
||||
in builtins.listToAttrs (builtins.map f names);
|
||||
in writeText "make-binary-wrapper-test" ''
|
||||
${lib.concatStringsSep "\n" (lib.mapAttrsToList (_: test: ''
|
||||
validate "${test.name}" "${test}" ${lib.escapeShellArg test.assertion} || fail=1
|
||||
"${test.name}" "${test}"
|
||||
'') tests)}
|
||||
|
||||
if [ "$fail" ]; then
|
||||
echo "failed"
|
||||
exit 1
|
||||
else
|
||||
echo "succeeded"
|
||||
touch $out
|
||||
fi
|
||||
''
|
||||
'' // tests
|
||||
|
@ -1,9 +1,3 @@
|
||||
// makeCWrapper /hello/world \
|
||||
--set PART1 HELLO \
|
||||
--set-default PART2 WORLD \
|
||||
--unset SOME_OTHER_VARIABLE \
|
||||
--set PART3 $'"!!\n"'
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
@ -15,6 +9,6 @@ int main(int argc, char **argv) {
|
||||
assert_success(setenv("PART2", "WORLD", 0));
|
||||
assert_success(unsetenv("SOME_OTHER_VARIABLE"));
|
||||
putenv("PART3=\"!!\n\"");
|
||||
argv[0] = "/hello/world";
|
||||
return execv("/hello/world", argv);
|
||||
}
|
||||
argv[0] = "/send/me/flags";
|
||||
return execv("/send/me/flags", argv);
|
||||
}
|
||||
|
4
pkgs/test/make-binary-wrapper/env.cmdline
Normal file
4
pkgs/test/make-binary-wrapper/env.cmdline
Normal file
@ -0,0 +1,4 @@
|
||||
--set PART1 HELLO \
|
||||
--set-default PART2 WORLD \
|
||||
--unset SOME_OTHER_VARIABLE \
|
||||
--set PART3 $'"!!\n"'
|
6
pkgs/test/make-binary-wrapper/env.env
Normal file
6
pkgs/test/make-binary-wrapper/env.env
Normal file
@ -0,0 +1,6 @@
|
||||
PART1=HELLO
|
||||
PART2=WORLD
|
||||
PART3="!!
|
||||
"
|
||||
CWD=SUBST_CWD
|
||||
SUBST_ARGV0
|
22
pkgs/test/make-binary-wrapper/envcheck.c
Normal file
22
pkgs/test/make-binary-wrapper/envcheck.c
Normal file
@ -0,0 +1,22 @@
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main(int argc, char **argv, char **envp) {
|
||||
for (char **env = envp; *env != 0; ++env) {
|
||||
puts(*env);
|
||||
}
|
||||
|
||||
char cwd[PATH_MAX];
|
||||
if (getcwd(cwd, sizeof(cwd))) {
|
||||
printf("CWD=%s\n", cwd);
|
||||
} else {
|
||||
perror("getcwd() error");
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (int i=0; i < argc; ++i) {
|
||||
puts(argv[i]);
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# Split a generated C-file into the command used to generate it,
|
||||
# and the outputted code itself.
|
||||
|
||||
# This is useful because it allows input and output to be inside the same file
|
||||
|
||||
# How it works:
|
||||
# - The first line needs to start with '//' (and becomes the command).
|
||||
# - Whitespace/padding between the comment and the generated code is ignored
|
||||
# - To write a command using multiple lines, end each line with backslash (\)
|
||||
|
||||
# Count the number of lines before the output text starts
|
||||
# commandLineCount FILE
|
||||
commandLineCount() {
|
||||
local n state
|
||||
n=0
|
||||
state="init"
|
||||
while IFS="" read -r p || [ -n "$p" ]; do
|
||||
case $state in
|
||||
init)
|
||||
if [[ $p =~ ^//.*\\$ ]]; then state="comment"
|
||||
elif [[ $p =~ ^//.* ]]; then state="padding"
|
||||
else break
|
||||
fi
|
||||
;;
|
||||
comment) [[ ! $p =~ ^.*\\$ ]] && state="padding";;
|
||||
padding) [ -n "${p// }" ] && break;;
|
||||
esac
|
||||
n=$((n+1))
|
||||
done < "$1"
|
||||
printf '%s' "$n"
|
||||
}
|
||||
|
||||
# getInputCommand FILE
|
||||
getInputCommand() {
|
||||
n=$(commandLineCount "$1")
|
||||
head -n "$n" "$1" | awk '{ if (NR == 1) print substr($0, 3); else print $0 }'
|
||||
}
|
||||
|
||||
# getOutputText FILE
|
||||
getOutputText() {
|
||||
n=$(commandLineCount "$1")
|
||||
sed "1,${n}d" "$1"
|
||||
}
|
@ -1,9 +1,6 @@
|
||||
// makeCWrapper /path/to/executable \
|
||||
--inherit-argv0
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
return execv("/path/to/executable", argv);
|
||||
}
|
||||
return execv("/send/me/flags", argv);
|
||||
}
|
||||
|
1
pkgs/test/make-binary-wrapper/inherit-argv0.cmdline
Normal file
1
pkgs/test/make-binary-wrapper/inherit-argv0.cmdline
Normal file
@ -0,0 +1 @@
|
||||
--inherit-argv0
|
2
pkgs/test/make-binary-wrapper/inherit-argv0.env
Normal file
2
pkgs/test/make-binary-wrapper/inherit-argv0.env
Normal file
@ -0,0 +1,2 @@
|
||||
CWD=SUBST_CWD
|
||||
./wrapped
|
@ -1,7 +1,3 @@
|
||||
// makeCWrapper /bad/env/example \
|
||||
--set "=" "TEST1" \
|
||||
--set-default "" "TEST2"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
@ -13,6 +9,6 @@ int main(int argc, char **argv) {
|
||||
#error Illegal environment variable name `=` (cannot contain `=`)
|
||||
assert_success(setenv("", "TEST2", 0));
|
||||
#error Environment variable name can't be empty.
|
||||
argv[0] = "/bad/env/example";
|
||||
return execv("/bad/env/example", argv);
|
||||
}
|
||||
argv[0] = "/send/me/flags";
|
||||
return execv("/send/me/flags", argv);
|
||||
}
|
||||
|
2
pkgs/test/make-binary-wrapper/invalid-env.cmdline
Normal file
2
pkgs/test/make-binary-wrapper/invalid-env.cmdline
Normal file
@ -0,0 +1,2 @@
|
||||
--set "=" "TEST1" \
|
||||
--set-default "" "TEST2"
|
@ -1,7 +1,3 @@
|
||||
// makeCWrapper /path/to/executable \
|
||||
--prefix PATH : /usr/bin/ \
|
||||
--prefix PATH : /usr/local/bin/
|
||||
|
||||
#define _GNU_SOURCE /* See feature_test_macros(7) */
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
@ -25,6 +21,6 @@ void set_env_prefix(char *env, char *sep, char *prefix) {
|
||||
int main(int argc, char **argv) {
|
||||
set_env_prefix("PATH", ":", "/usr/bin/");
|
||||
set_env_prefix("PATH", ":", "/usr/local/bin/");
|
||||
argv[0] = "/path/to/executable";
|
||||
return execv("/path/to/executable", argv);
|
||||
argv[0] = "/send/me/flags";
|
||||
return execv("/send/me/flags", argv);
|
||||
}
|
||||
|
2
pkgs/test/make-binary-wrapper/prefix.cmdline
Normal file
2
pkgs/test/make-binary-wrapper/prefix.cmdline
Normal file
@ -0,0 +1,2 @@
|
||||
--prefix PATH : /usr/bin/ \
|
||||
--prefix PATH : /usr/local/bin/
|
3
pkgs/test/make-binary-wrapper/prefix.env
Normal file
3
pkgs/test/make-binary-wrapper/prefix.env
Normal file
@ -0,0 +1,3 @@
|
||||
PATH=/usr/local/bin/:/usr/bin/
|
||||
CWD=SUBST_CWD
|
||||
SUBST_ARGV0
|
@ -1,7 +1,3 @@
|
||||
// makeCWrapper /path/to/executable \
|
||||
--suffix PATH : /usr/bin/ \
|
||||
--suffix PATH : /usr/local/bin/
|
||||
|
||||
#define _GNU_SOURCE /* See feature_test_macros(7) */
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
@ -25,6 +21,6 @@ void set_env_suffix(char *env, char *sep, char *suffix) {
|
||||
int main(int argc, char **argv) {
|
||||
set_env_suffix("PATH", ":", "/usr/bin/");
|
||||
set_env_suffix("PATH", ":", "/usr/local/bin/");
|
||||
argv[0] = "/path/to/executable";
|
||||
return execv("/path/to/executable", argv);
|
||||
argv[0] = "/send/me/flags";
|
||||
return execv("/send/me/flags", argv);
|
||||
}
|
||||
|
2
pkgs/test/make-binary-wrapper/suffix.cmdline
Normal file
2
pkgs/test/make-binary-wrapper/suffix.cmdline
Normal file
@ -0,0 +1,2 @@
|
||||
--suffix PATH : /usr/bin/ \
|
||||
--suffix PATH : /usr/local/bin/
|
3
pkgs/test/make-binary-wrapper/suffix.env
Normal file
3
pkgs/test/make-binary-wrapper/suffix.env
Normal file
@ -0,0 +1,3 @@
|
||||
PATH=/usr/bin/:/usr/local/bin/
|
||||
CWD=SUBST_CWD
|
||||
SUBST_ARGV0
|
Loading…
Reference in New Issue
Block a user