summaryrefslogtreecommitdiffhomepage
path: root/test
diff options
context:
space:
mode:
authorMax Romanov <max.romanov@nginx.com>2021-07-29 19:50:39 +0300
committerMax Romanov <max.romanov@nginx.com>2021-07-29 19:50:39 +0300
commitfa9fb29be221e0393562831a9e3bcba416652f60 (patch)
treebc3e1a28d7915735507c64a62199a189bfb8231f /test
parentf3a1c1deb541784b2b0ed179514e4d5eba9fe626 (diff)
downloadunit-fa9fb29be221e0393562831a9e3bcba416652f60.tar.gz
unit-fa9fb29be221e0393562831a9e3bcba416652f60.tar.bz2
Application restart introduced.
When processing a restart request, the router sends a QUIT message to all existing processes of the application. Then, a new shared application port is created to ensure that new requests won't be handled by the old processes of the application.
Diffstat (limited to 'test')
-rw-r--r--test/python/restart/longstart.py10
-rw-r--r--test/python/restart/v1.py7
-rw-r--r--test/python/restart/v2.py7
-rw-r--r--test/test_python_procman.py79
-rw-r--r--test/unit/applications/lang/python.py1
5 files changed, 104 insertions, 0 deletions
diff --git a/test/python/restart/longstart.py b/test/python/restart/longstart.py
new file mode 100644
index 00000000..777398ac
--- /dev/null
+++ b/test/python/restart/longstart.py
@@ -0,0 +1,10 @@
+import os
+import time
+
+time.sleep(2)
+
+def application(environ, start_response):
+ body = str(os.getpid()).encode()
+
+ start_response('200', [('Content-Length', str(len(body)))])
+ return [body]
diff --git a/test/python/restart/v1.py b/test/python/restart/v1.py
new file mode 100644
index 00000000..2e45b269
--- /dev/null
+++ b/test/python/restart/v1.py
@@ -0,0 +1,7 @@
+import os
+
+def application(environ, start_response):
+ body = "v1".encode()
+
+ start_response('200', [('Content-Length', str(len(body)))])
+ return [body]
diff --git a/test/python/restart/v2.py b/test/python/restart/v2.py
new file mode 100644
index 00000000..59e3d30f
--- /dev/null
+++ b/test/python/restart/v2.py
@@ -0,0 +1,7 @@
+import os
+
+def application(environ, start_response):
+ body = "v2".encode()
+
+ start_response('200', [('Content-Length', str(len(body)))])
+ return [body]
diff --git a/test/test_python_procman.py b/test/test_python_procman.py
index b0d0f5af..a95c5680 100644
--- a/test/test_python_procman.py
+++ b/test/test_python_procman.py
@@ -1,4 +1,5 @@
import re
+import shutil
import subprocess
import time
@@ -201,3 +202,81 @@ class TestPythonProcman(TestApplicationPython):
assert 'success' in self.conf({"listeners": {}, "applications": {}})
assert len(self.pids_for_process()) == 0, 'stop all'
+
+ def test_python_restart(self, temp_dir):
+ shutil.copyfile(
+ option.test_dir + '/python/restart/v1.py', temp_dir + '/wsgi.py'
+ )
+
+ self.load(
+ temp_dir,
+ name=self.app_name,
+ processes=1,
+ environment={'PYTHONDONTWRITEBYTECODE': '1'},
+ )
+
+ b = self.get()['body']
+ assert b == "v1", 'process started'
+
+ shutil.copyfile(
+ option.test_dir + '/python/restart/v2.py', temp_dir + '/wsgi.py'
+ )
+
+ b = self.get()['body']
+ assert b == "v1", 'still old process'
+
+ assert 'success' in self.conf_get(
+ '/control/applications/' + self.app_name + '/restart'
+ ), 'restart processes'
+
+ b = self.get()['body']
+ assert b == "v2", 'new process started'
+
+ assert 'error' in self.conf_get(
+ '/control/applications/blah/restart'
+ ), 'application incorrect'
+
+ assert 'error' in self.conf_delete(
+ '/control/applications/' + self.app_name + '/restart'
+ ), 'method incorrect'
+
+ def test_python_restart_multi(self):
+ self.conf_proc('2')
+
+ pids = self.pids_for_process()
+ assert len(pids) == 2, 'restart 2 started'
+
+ assert 'success' in self.conf_get(
+ '/control/applications/' + self.app_name + '/restart'
+ ), 'restart processes'
+
+ new_pids = self.pids_for_process()
+ assert len(new_pids) == 2, 'restart still 2'
+
+ assert len(new_pids.intersection(pids)) == 0, 'restart all new'
+
+ def test_python_restart_longstart(self):
+ self.load(
+ 'restart',
+ name=self.app_name,
+ module="longstart",
+ processes={"spare": 1, "max": 2, "idle_timeout": 5},
+ )
+
+ assert len(self.pids_for_process()) == 1, 'longstarts == 1'
+
+ pid = self.get()['body']
+ pids = self.pids_for_process()
+ assert len(pids) == 2, 'longstarts == 2'
+
+ assert 'success' in self.conf_get(
+ '/control/applications/' + self.app_name + '/restart'
+ ), 'restart processes'
+
+ # wait for longstarted app
+ time.sleep(2)
+
+ new_pids = self.pids_for_process()
+ assert len(new_pids) == 1, 'restart 1'
+
+ assert len(new_pids.intersection(pids)) == 0, 'restart all new'
diff --git a/test/unit/applications/lang/python.py b/test/unit/applications/lang/python.py
index b399dffd..215aa332 100644
--- a/test/unit/applications/lang/python.py
+++ b/test/unit/applications/lang/python.py
@@ -44,6 +44,7 @@ class TestApplicationPython(TestApplicationProto):
for attr in (
'callable',
+ 'environment',
'home',
'limits',
'path',