summary refs log tree commit diff
path: root/pkgs/test/make-binary-wrapper
diff options
context:
space:
mode:
authorTobias Bergkvist <tobias@bergkv.ist>2021-10-04 22:35:09 +0200
committerTobias Bergkvist <tobias@bergkv.ist>2021-10-04 22:35:09 +0200
commitb7d36b8d597df1a9d799fa9d6d8d55137a525570 (patch)
tree716510254e300367537f66567387c9694747c9b3 /pkgs/test/make-binary-wrapper
parentadef70ce7c964e0d1d9d961783036541323b06a7 (diff)
downloadnixpkgs-b7d36b8d597df1a9d799fa9d6d8d55137a525570.tar
nixpkgs-b7d36b8d597df1a9d799fa9d6d8d55137a525570.tar.gz
nixpkgs-b7d36b8d597df1a9d799fa9d6d8d55137a525570.tar.bz2
nixpkgs-b7d36b8d597df1a9d799fa9d6d8d55137a525570.tar.lz
nixpkgs-b7d36b8d597df1a9d799fa9d6d8d55137a525570.tar.xz
nixpkgs-b7d36b8d597df1a9d799fa9d6d8d55137a525570.tar.zst
nixpkgs-b7d36b8d597df1a9d799fa9d6d8d55137a525570.zip
Add golden tests for make-binary-wrapper.
To run tests after cloning on linux, use the following:
nix-build pkgs/top-level/release.nix -A tests.make-binary-wrapper.x86_64-linux
Diffstat (limited to 'pkgs/test/make-binary-wrapper')
-rw-r--r--pkgs/test/make-binary-wrapper/add-flags.c23
-rw-r--r--pkgs/test/make-binary-wrapper/argv0.c10
-rw-r--r--pkgs/test/make-binary-wrapper/basic.c9
-rw-r--r--pkgs/test/make-binary-wrapper/combination.c58
-rw-r--r--pkgs/test/make-binary-wrapper/default.nix69
-rw-r--r--pkgs/test/make-binary-wrapper/env.c17
-rw-r--r--pkgs/test/make-binary-wrapper/golden-test-utils.sh44
-rw-r--r--pkgs/test/make-binary-wrapper/prefix.c33
-rw-r--r--pkgs/test/make-binary-wrapper/suffix.c33
9 files changed, 296 insertions, 0 deletions
diff --git a/pkgs/test/make-binary-wrapper/add-flags.c b/pkgs/test/make-binary-wrapper/add-flags.c
new file mode 100644
index 00000000000..70d43e0bec0
--- /dev/null
+++ b/pkgs/test/make-binary-wrapper/add-flags.c
@@ -0,0 +1,23 @@
+// makeCWrapper /send/me/flags \
+    --add-flags "-x -y -z" \
+    --add-flags -abc
+
+#include <unistd.h>
+#include <stdlib.h>
+
+int main(int argc, char **argv) {
+    char **argv_tmp = malloc(sizeof(*argv_tmp) * (5 + argc));
+    argv_tmp[0] = argv[0];
+    argv_tmp[1] = "-x";
+    argv_tmp[2] = "-y";
+    argv_tmp[3] = "-z";
+    argv_tmp[4] = "-abc";
+    for (int i = 1; i < argc; ++i) {
+        argv_tmp[4 + i] = argv[i];
+    }
+    argv_tmp[4 + argc] = NULL;
+    argv = argv_tmp;
+
+    argv[0] = "/send/me/flags";
+    return execv("/send/me/flags", argv);
+}
\ No newline at end of file
diff --git a/pkgs/test/make-binary-wrapper/argv0.c b/pkgs/test/make-binary-wrapper/argv0.c
new file mode 100644
index 00000000000..8e3e1f2987b
--- /dev/null
+++ b/pkgs/test/make-binary-wrapper/argv0.c
@@ -0,0 +1,10 @@
+// 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);
+}
diff --git a/pkgs/test/make-binary-wrapper/basic.c b/pkgs/test/make-binary-wrapper/basic.c
new file mode 100644
index 00000000000..de366c51963
--- /dev/null
+++ b/pkgs/test/make-binary-wrapper/basic.c
@@ -0,0 +1,9 @@
+// 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);
+}
diff --git a/pkgs/test/make-binary-wrapper/combination.c b/pkgs/test/make-binary-wrapper/combination.c
new file mode 100644
index 00000000000..925fdf1ccfb
--- /dev/null
+++ b/pkgs/test/make-binary-wrapper/combination.c
@@ -0,0 +1,58 @@
+// 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
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+char *concat3(char *x, char *y, char *z) {
+    int xn = strlen(x);
+    int yn = strlen(y);
+    int zn = strlen(z);
+    char *res = malloc(sizeof(*res)*(xn + yn + zn + 1));
+    strncpy(res, x, xn);
+    strncpy(res + xn, y, yn);
+    strncpy(res + xn + yn, z, zn);
+    res[xn + yn + zn] = '\0';
+    return res;
+}
+
+void set_env_prefix(char *env, char *sep, char *val) {
+    char *existing = getenv(env);
+    if (existing) val = concat3(val, sep, existing);
+    setenv(env, val, 1);
+    if (existing) free(val);
+}
+
+void set_env_suffix(char *env, char *sep, char *val) {
+    char *existing = getenv(env);
+    if (existing) val = concat3(existing, sep, val);
+    setenv(env, val, 1);
+    if (existing) free(val);
+}
+
+int main(int argc, char **argv) {
+    setenv("MESSAGE", "HELLO", 0);
+    set_env_prefix("PATH", ":", "/usr/bin/");
+    set_env_suffix("PATH", ":", "/usr/local/bin/");
+    putenv("MESSAGE2=WORLD");
+
+    char **argv_tmp = malloc(sizeof(*argv_tmp) * (4 + argc));
+    argv_tmp[0] = argv[0];
+    argv_tmp[1] = "-x";
+    argv_tmp[2] = "-y";
+    argv_tmp[3] = "-z";
+    for (int i = 1; i < argc; ++i) {
+        argv_tmp[3 + i] = argv[i];
+    }
+    argv_tmp[3 + argc] = NULL;
+    argv = argv_tmp;
+
+    argv[0] = "my-wrapper";
+    return execv("/path/to/executable", argv);
+}
diff --git a/pkgs/test/make-binary-wrapper/default.nix b/pkgs/test/make-binary-wrapper/default.nix
new file mode 100644
index 00000000000..0b9f7e5abea
--- /dev/null
+++ b/pkgs/test/make-binary-wrapper/default.nix
@@ -0,0 +1,69 @@
+{ lib, stdenv, runCommand, makeBinaryWrapper }:
+
+let
+  makeGoldenTest = { name, filename }: stdenv.mkDerivation {
+    name = name;
+    dontUnpack = true;
+    buildInputs = [ 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 = {
+    add-flags = makeGoldenTest { name = "add-flags"; filename = ./add-flags.c; };
+    argv0 = makeGoldenTest { name = "argv0"; filename = ./argv0.c; };
+    basic = makeGoldenTest { name = "basic"; filename = ./basic.c; };
+    combination = makeGoldenTest { name = "combination"; filename = ./combination.c; };
+    env = makeGoldenTest { name = "env"; filename = ./env.c; };
+    prefix = makeGoldenTest { name = "prefix"; filename = ./prefix.c; };
+    suffix = makeGoldenTest { name = "suffix"; filename = ./suffix.c; };
+  };
+in runCommand "make-binary-wrapper-test" {
+  passthru = tests;
+  meta.platforms = lib.platforms.all;
+} ''
+  validate() {
+    local name=$1
+    local testout=$2
+    local assertion=$3
+
+    echo -n "... $name: " >&2
+
+    local rc=0
+    (out=$testout eval "$assertion") || rc=1
+
+    if [ "$rc" -eq 0 ]; then
+      echo "yes" >&2
+    else
+      echo "no" >&2
+    fi
+
+    return "$rc"
+  }
+
+  echo "checking whether makeCWrapper works properly... ">&2
+
+  fail=
+  ${lib.concatStringsSep "\n" (lib.mapAttrsToList (_: test: ''
+    validate "${test.name}" "${test}" ${lib.escapeShellArg test.assertion} || fail=1
+  '') tests)}
+
+  if [ "$fail" ]; then
+    echo "failed"
+    exit 1
+  else
+    echo "succeeded"
+    touch $out
+  fi
+''
diff --git a/pkgs/test/make-binary-wrapper/env.c b/pkgs/test/make-binary-wrapper/env.c
new file mode 100644
index 00000000000..89f1f496b34
--- /dev/null
+++ b/pkgs/test/make-binary-wrapper/env.c
@@ -0,0 +1,17 @@
+// makeCWrapper /hello/world \
+    --set PART1 HELLO \
+    --set-default PART2 WORLD \
+    --unset SOME_OTHER_VARIABLE \
+    --set PART3 $'"!!\n"'
+
+#include <unistd.h>
+#include <stdlib.h>
+
+int main(int argc, char **argv) {
+    putenv("PART1=HELLO");
+    setenv("PART2", "WORLD", 0);
+    unsetenv("SOME_OTHER_VARIABLE");
+    putenv("PART3=\"!!\n\"");
+    argv[0] = "/hello/world";
+    return execv("/hello/world", argv);
+}
\ No newline at end of file
diff --git a/pkgs/test/make-binary-wrapper/golden-test-utils.sh b/pkgs/test/make-binary-wrapper/golden-test-utils.sh
new file mode 100644
index 00000000000..a0408b5a908
--- /dev/null
+++ b/pkgs/test/make-binary-wrapper/golden-test-utils.sh
@@ -0,0 +1,44 @@
+#!/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"
+}
diff --git a/pkgs/test/make-binary-wrapper/prefix.c b/pkgs/test/make-binary-wrapper/prefix.c
new file mode 100644
index 00000000000..914fd851bb7
--- /dev/null
+++ b/pkgs/test/make-binary-wrapper/prefix.c
@@ -0,0 +1,33 @@
+// makeCWrapper /path/to/executable \
+    --prefix PATH : /usr/bin/ \
+    --prefix PATH : /usr/local/bin/
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+char *concat3(char *x, char *y, char *z) {
+    int xn = strlen(x);
+    int yn = strlen(y);
+    int zn = strlen(z);
+    char *res = malloc(sizeof(*res)*(xn + yn + zn + 1));
+    strncpy(res, x, xn);
+    strncpy(res + xn, y, yn);
+    strncpy(res + xn + yn, z, zn);
+    res[xn + yn + zn] = '\0';
+    return res;
+}
+
+void set_env_prefix(char *env, char *sep, char *val) {
+    char *existing = getenv(env);
+    if (existing) val = concat3(val, sep, existing);
+    setenv(env, val, 1);
+    if (existing) free(val);
+}
+
+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);
+}
\ No newline at end of file
diff --git a/pkgs/test/make-binary-wrapper/suffix.c b/pkgs/test/make-binary-wrapper/suffix.c
new file mode 100644
index 00000000000..865d76fe34e
--- /dev/null
+++ b/pkgs/test/make-binary-wrapper/suffix.c
@@ -0,0 +1,33 @@
+// makeCWrapper /path/to/executable \
+    --suffix PATH : /usr/bin/ \
+    --suffix PATH : /usr/local/bin/
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+char *concat3(char *x, char *y, char *z) {
+    int xn = strlen(x);
+    int yn = strlen(y);
+    int zn = strlen(z);
+    char *res = malloc(sizeof(*res)*(xn + yn + zn + 1));
+    strncpy(res, x, xn);
+    strncpy(res + xn, y, yn);
+    strncpy(res + xn + yn, z, zn);
+    res[xn + yn + zn] = '\0';
+    return res;
+}
+
+void set_env_suffix(char *env, char *sep, char *val) {
+    char *existing = getenv(env);
+    if (existing) val = concat3(existing, sep, val);
+    setenv(env, val, 1);
+    if (existing) free(val);
+}
+
+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);
+}
\ No newline at end of file