summaryrefslogtreecommitdiffhomepage
path: root/test/test_python_isolation.py
diff options
context:
space:
mode:
authorAndrei Zeliankou <zelenkov@nginx.com>2022-12-14 19:00:14 +0000
committerAndrei Zeliankou <zelenkov@nginx.com>2022-12-14 19:00:14 +0000
commit4b39cb1fc75b42e944e41a522dbdf3d539eff8db (patch)
tree84c1c3909675bd27e87a483c33d753da76ab5cb3 /test/test_python_isolation.py
parent24e3f171029da265ee8cc20fe1a8846a0b49cb43 (diff)
downloadunit-4b39cb1fc75b42e944e41a522dbdf3d539eff8db.tar.gz
unit-4b39cb1fc75b42e944e41a522dbdf3d539eff8db.tar.bz2
Tests: added tests for "path" option in isolation/cgroup.
Diffstat (limited to '')
-rw-r--r--test/test_python_isolation.py123
1 files changed, 123 insertions, 0 deletions
diff --git a/test/test_python_isolation.py b/test/test_python_isolation.py
index db398444..6d4ffaf3 100644
--- a/test/test_python_isolation.py
+++ b/test/test_python_isolation.py
@@ -1,3 +1,8 @@
+import os
+import re
+import subprocess
+from pathlib import Path
+
import pytest
from unit.applications.lang.python import TestApplicationPython
from unit.option import option
@@ -9,6 +14,23 @@ from unit.utils import waitforunmount
class TestPythonIsolation(TestApplicationPython):
prerequisites = {'modules': {'python': 'any'}, 'features': ['isolation']}
+ def get_cgroup(self, app_name):
+ output = subprocess.check_output(
+ ['ps', 'ax', '-o', 'pid', '-o', 'cmd']
+ ).decode()
+
+ pid = re.search(
+ r'(\d+)\s*unit: "' + app_name + '" application', output
+ ).group(1)
+
+ cgroup = '/proc/' + pid + '/cgroup'
+
+ if not os.path.isfile(cgroup):
+ pytest.skip('no cgroup at ' + cgroup)
+
+ with open(cgroup, 'r') as f:
+ return f.read().rstrip()
+
def test_python_isolation_rootfs(self, is_su, temp_dir):
isolation_features = option.available['features']['isolation'].keys()
@@ -102,3 +124,104 @@ class TestPythonIsolation(TestApplicationPython):
assert (
self.getjson(url='/?path=/proc/self')['body']['FileExists'] == True
), '/proc/self'
+
+ def test_python_isolation_cgroup(self, is_su, temp_dir):
+ if not is_su:
+ pytest.skip('requires root')
+
+ if not 'cgroup' in option.available['features']['isolation']:
+ pytest.skip('cgroup is not supported')
+
+ def set_cgroup_path(path):
+ isolation = {'cgroup': {'path': path}}
+ self.load('empty', processes=1, isolation=isolation)
+
+ set_cgroup_path('scope/python')
+
+ cgroup_rel = Path(self.get_cgroup('empty'))
+ assert cgroup_rel.parts[-2:] == ('scope', 'python'), 'cgroup rel'
+
+ set_cgroup_path('/scope2/python')
+
+ cgroup_abs = Path(self.get_cgroup('empty'))
+ assert cgroup_abs.parts[-2:] == ('scope2', 'python'), 'cgroup abs'
+
+ assert len(cgroup_rel.parts) >= len(cgroup_abs.parts)
+
+ def test_python_isolation_cgroup_two(self, is_su, temp_dir):
+ if not is_su:
+ pytest.skip('requires root')
+
+ if not 'cgroup' in option.available['features']['isolation']:
+ pytest.skip('cgroup is not supported')
+
+ def set_two_cgroup_path(path, path2):
+ script_path = option.test_dir + '/python/empty'
+
+ assert 'success' in self.conf(
+ {
+ "listeners": {
+ "*:7080": {"pass": "applications/one"},
+ "*:7081": {"pass": "applications/two"},
+ },
+ "applications": {
+ "one": {
+ "type": "python",
+ "processes": 1,
+ "path": script_path,
+ "working_directory": script_path,
+ "module": "wsgi",
+ "isolation": {
+ 'cgroup': {'path': path},
+ },
+ },
+ "two": {
+ "type": "python",
+ "processes": 1,
+ "path": script_path,
+ "working_directory": script_path,
+ "module": "wsgi",
+ "isolation": {
+ 'cgroup': {'path': path2},
+ },
+ },
+ },
+ }
+ )
+
+ set_two_cgroup_path('/scope/python', '/scope/python')
+ assert self.get_cgroup('one') == self.get_cgroup('two')
+
+ set_two_cgroup_path('/scope/python', '/scope2/python')
+ assert self.get_cgroup('one') != self.get_cgroup('two')
+
+ def test_python_isolation_cgroup_invalid(self, is_su):
+ if not is_su:
+ pytest.skip('requires root')
+
+ if not 'cgroup' in option.available['features']['isolation']:
+ pytest.skip('cgroup is not supported')
+
+ def check_invalid(path):
+ script_path = option.test_dir + '/python/empty'
+ assert 'error' in self.conf(
+ {
+ "listeners": {"*:7080": {"pass": "applications/empty"}},
+ "applications": {
+ "empty": {
+ "type": "python",
+ "processes": {"spare": 0},
+ "path": script_path,
+ "working_directory": script_path,
+ "module": "wsgi",
+ "isolation": {
+ 'cgroup': {'path': path},
+ },
+ }
+ },
+ }
+ )
+
+ check_invalid('')
+ check_invalid('../scope')
+ check_invalid('scope/../python')