mirror of https://github.com/krallin/tini.git
Merge pull request #5 from krallin/tests-in-ci
Run some functional tests in ci/run_build.sh
This commit is contained in:
commit
98311caf52
|
@ -18,6 +18,10 @@ addons:
|
|||
- git
|
||||
- gdb
|
||||
- valgrind
|
||||
- python-dev
|
||||
- libcap-dev
|
||||
- python-pip
|
||||
- python-virtualenv
|
||||
|
||||
script: ./ci/run_build.sh
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
FROM ubuntu:precise
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install --no-install-recommends --yes build-essential git gdb valgrind cmake rpm python3 \
|
||||
&& apt-get install --no-install-recommends --yes build-essential git gdb valgrind cmake rpm python-dev libcap-dev python-pip python-virtualenv \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN pip install psutil
|
||||
|
|
|
@ -3,13 +3,23 @@
|
|||
set -o errexit
|
||||
set -o nounset
|
||||
|
||||
# Paths
|
||||
: ${SOURCE_DIR:="."}
|
||||
: ${DIST_DIR:="${SOURCE_DIR}/dist"}
|
||||
: ${BUILD_DIR:="/tmp/build"}
|
||||
|
||||
# Make those paths absolute, and export them for the Python tests to consume.
|
||||
export SOURCE_DIR="$(readlink -f "${SOURCE_DIR}")"
|
||||
export DIST_DIR="$(readlink -f "${DIST_DIR}")"
|
||||
export BUILD_DIR="$(readlink -f "${BUILD_DIR}")"
|
||||
|
||||
|
||||
# Ensure Python output is not buffered (to make tests output clearer)
|
||||
export PYTHONUNBUFFERED=1
|
||||
|
||||
# Set path to prioritize our utils
|
||||
export REAL_PATH="${PATH}"
|
||||
export PATH="$(readlink -f "${SOURCE_DIR}")/ci/util:${PATH}"
|
||||
export PATH="${SOURCE_DIR}/ci/util:${PATH}"
|
||||
|
||||
# Build
|
||||
cmake -B"${BUILD_DIR}" -H"${SOURCE_DIR}"
|
||||
|
@ -46,3 +56,29 @@ for tini in "${BUILD_DIR}/tini" "${BUILD_DIR}/tini-static"; do
|
|||
dpkg --contents "${DIST_DIR}/tini"*deb
|
||||
fi
|
||||
done
|
||||
|
||||
# Create virtual environment to run tests
|
||||
VENV="${BUILD_DIR}/venv"
|
||||
virtualenv "${VENV}"
|
||||
|
||||
# Don't use activate because it does not play nice with nounset
|
||||
export PATH="${VENV}/bin:${PATH}"
|
||||
|
||||
# Install test dependencies
|
||||
|
||||
# We need a patched version because Travis only gives us Ubuntu Precise
|
||||
# (whose Linux headers don't include PR_SET_CHILD_SUBREAPER), but actually
|
||||
# runs a newer Linux Kernel (because we're actually in Docker) that has the
|
||||
# PR_SET_CHILD_SUBREAPER prctl call.
|
||||
pushd /tmp
|
||||
pip install python-prctl==1.6.1 --download="."
|
||||
tar -xvf /tmp/python-prctl-1.6.1.tar.gz
|
||||
cd python-prctl-1.6.1
|
||||
patch -p1 < "${SOURCE_DIR}/test/0001-Add-PR_SET_CHILD_SUBREAPER.patch"
|
||||
python setup.py install
|
||||
popd
|
||||
|
||||
pip install psutil
|
||||
|
||||
# Run tests
|
||||
python "${SOURCE_DIR}/test/run_inner_tests.py"
|
||||
|
|
2
dtest.sh
2
dtest.sh
|
@ -6,4 +6,4 @@ IMG="tini"
|
|||
|
||||
|
||||
docker build -t "${IMG}" .
|
||||
python test/test.py "${IMG}"
|
||||
python test/run_outer_tests.py "${IMG}"
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
From b8c6ccd4575837e3901bbdee7b219ef951dc2065 Mon Sep 17 00:00:00 2001
|
||||
From: Thomas Orozco <thomas@orozco.fr>
|
||||
Date: Sun, 28 Jun 2015 15:25:37 +0200
|
||||
Subject: [PATCH] Add PR_SET_CHILD_SUBREAPER
|
||||
|
||||
---
|
||||
_prctlmodule.c | 12 ++++++++++++
|
||||
1 file changed, 12 insertions(+)
|
||||
|
||||
diff --git a/_prctlmodule.c b/_prctlmodule.c
|
||||
index 14121c3..19ad141 100644
|
||||
--- a/_prctlmodule.c
|
||||
+++ b/_prctlmodule.c
|
||||
@@ -15,6 +15,18 @@
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/signal.h>
|
||||
|
||||
+/* Our builds run in a Docker environment that has those, but they are
|
||||
+ * not in the kernel headers. Add them.
|
||||
+ */
|
||||
+
|
||||
+#ifndef PR_SET_CHILD_SUBREAPER
|
||||
+#define PR_SET_CHILD_SUBREAPER 36
|
||||
+#endif
|
||||
+
|
||||
+#ifndef PR_GET_CHILD_SUBREAPER
|
||||
+#define PR_GET_CHILD_SUBREAPER 37
|
||||
+#endif
|
||||
+
|
||||
/* New in 2.6.32, but named and implemented inconsistently. The linux
|
||||
* implementation has two ways of setting the policy to the default, and thus
|
||||
* needs an extra argument. We ignore the first argument and always call
|
||||
--
|
||||
2.4.3
|
||||
|
|
@ -1,25 +1,34 @@
|
|||
#!/usr/bin/env python3
|
||||
#!/usr/bin/env python
|
||||
from __future__ import print_function
|
||||
import os
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
import psutil
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
def main():
|
||||
p = subprocess.Popen([os.path.join(os.path.dirname(__file__), "stage_2.py")])
|
||||
p.wait()
|
||||
|
||||
# These are the only PIDs that should remain if the system is well-behaved:
|
||||
# - This process
|
||||
# - Init
|
||||
expected_pids = [1, os.getpid()]
|
||||
# In tests, we assume this process is the direct child of init
|
||||
this_process = psutil.Process(os.getpid())
|
||||
init_process = this_process.parent()
|
||||
|
||||
print("Reaping test: stage_1 is pid{0}, init is pid{1}".format(this_process.pid, init_process.pid))
|
||||
|
||||
# The only child PID that should persist is this one.
|
||||
expected_pids = [this_process.pid]
|
||||
|
||||
print("Expecting pids to remain: {0}".format(", ".join(str(pid) for pid in expected_pids)))
|
||||
|
||||
while 1:
|
||||
pids = [pid for pid in os.listdir('/proc') if pid.isdigit()]
|
||||
print("Has pids: {0}".format(", ".join(pids)))
|
||||
if set(int(pid) for pid in pids) == set(expected_pids):
|
||||
pids = [p.pid for p in init_process.children(recursive=True)]
|
||||
print("Has pids: {0}".format(", ".join(str(pid) for pid in pids)))
|
||||
if set(pids) == set(expected_pids):
|
||||
break
|
||||
time.sleep(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env python3
|
||||
#!/usr/bin/env python
|
||||
from __future__ import print_function
|
||||
import subprocess
|
||||
import os
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
#!/usr/bin/env python
|
||||
#coding:utf-8
|
||||
import os
|
||||
import sys
|
||||
import signal
|
||||
import subprocess
|
||||
|
||||
|
||||
def main():
|
||||
src = os.environ["SOURCE_DIR"]
|
||||
build = os.environ["BUILD_DIR"]
|
||||
|
||||
proxy = os.path.join(src, "test", "subreaper-proxy.py")
|
||||
tini = os.path.join(build, "tini")
|
||||
|
||||
# Run the reaping test
|
||||
print "Running reaping test"
|
||||
p = subprocess.Popen([proxy, tini, "--", os.path.join(src, "test", "reaping", "stage_1.py")])
|
||||
ret = p.wait()
|
||||
assert ret == 0, "Reaping test failed!"
|
||||
|
||||
# Run the signals test
|
||||
for signame in "SIGINT", "SIGTERM":
|
||||
print "running signal test for: {0}".format(signame)
|
||||
p = subprocess.Popen([proxy, tini, "--", os.path.join(src, "test", "signals", "test.py")])
|
||||
sig = getattr(signal, signame)
|
||||
p.send_signal(sig)
|
||||
ret = p.wait()
|
||||
assert ret == - sig, "Signals test failed!"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env python3
|
||||
#!/usr/bin/env python
|
||||
import time
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
#!/usr/bin/env python
|
||||
#coding:utf-8
|
||||
import os
|
||||
import sys
|
||||
|
||||
import prctl
|
||||
|
||||
|
||||
def main():
|
||||
args = sys.argv[1:]
|
||||
|
||||
print "subreaper-proxy: running '%s'" % (" ".join(args))
|
||||
|
||||
prctl.set_child_subreaper(1)
|
||||
os.execv(args[0], args)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -18,6 +18,10 @@ addons:
|
|||
- git
|
||||
- gdb
|
||||
- valgrind
|
||||
- python-dev
|
||||
- libcap-dev
|
||||
- python-pip
|
||||
- python-virtualenv
|
||||
|
||||
script: ./ci/run_build.sh
|
||||
|
||||
|
|
Loading…
Reference in New Issue