mirror of
https://github.com/YunoHost/yunohost.git
synced 2024-09-03 20:06:10 +02:00
Merge pull request #974 from YunoHost/test_apps_cleanup_and_automation
Test apps cleanup and automation
This commit is contained in:
commit
ea7594ac78
4 changed files with 99 additions and 45 deletions
|
@ -26,14 +26,6 @@ postinstall:
|
||||||
- pip install -U pip
|
- pip install -U pip
|
||||||
- hash -d pip
|
- hash -d pip
|
||||||
- pip --cache-dir=.pip install pytest pytest-sugar pytest-mock requests-mock mock
|
- pip --cache-dir=.pip install pytest pytest-sugar pytest-mock requests-mock mock
|
||||||
- pushd src/yunohost/tests
|
|
||||||
- >
|
|
||||||
if [ ! -d "./apps" ]; then
|
|
||||||
git clone https://github.com/YunoHost/test_apps ./apps
|
|
||||||
fi
|
|
||||||
- cd apps
|
|
||||||
- git pull > /dev/null 2>&1
|
|
||||||
- popd
|
|
||||||
- export PYTEST_ADDOPTS="--color=yes"
|
- export PYTEST_ADDOPTS="--color=yes"
|
||||||
cache:
|
cache:
|
||||||
paths:
|
paths:
|
||||||
|
@ -129,4 +121,4 @@ lint:
|
||||||
#format-check:
|
#format-check:
|
||||||
# extends: .lint-stage
|
# extends: .lint-stage
|
||||||
# script:
|
# script:
|
||||||
# - black --check --diff
|
# - black --check --diff
|
||||||
|
|
|
@ -2,3 +2,11 @@
|
||||||
addopts = -s -v
|
addopts = -s -v
|
||||||
norecursedirs = dist doc build .tox .eggs
|
norecursedirs = dist doc build .tox .eggs
|
||||||
testpaths = tests/
|
testpaths = tests/
|
||||||
|
markers =
|
||||||
|
with_system_archive_from_2p4
|
||||||
|
with_backup_recommended_app_installed
|
||||||
|
clean_opt_dir
|
||||||
|
with_wordpress_archive_from_2p4
|
||||||
|
with_legacy_app_installed
|
||||||
|
with_backup_recommended_app_installed_with_ynh_restore
|
||||||
|
with_permission_app_installed
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import os
|
||||||
import pytest
|
import pytest
|
||||||
import sys
|
import sys
|
||||||
import moulinette
|
import moulinette
|
||||||
|
@ -9,6 +10,15 @@ from contextlib import contextmanager
|
||||||
sys.path.append("..")
|
sys.path.append("..")
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="session", autouse=True)
|
||||||
|
def clone_test_app(request):
|
||||||
|
cwd = os.path.split(os.path.realpath(__file__))[0]
|
||||||
|
|
||||||
|
if not os.path.exists(cwd + "/apps"):
|
||||||
|
os.system("git clone https://github.com/YunoHost/test_apps %s/apps" % cwd)
|
||||||
|
else:
|
||||||
|
os.system("cd %s/apps && git pull > /dev/null 2>&1" % cwd)
|
||||||
|
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def message(mocker, key, **kwargs):
|
def message(mocker, key, **kwargs):
|
||||||
|
|
|
@ -6,13 +6,22 @@ import requests
|
||||||
|
|
||||||
from conftest import message, raiseYunohostError
|
from conftest import message, raiseYunohostError
|
||||||
|
|
||||||
from moulinette import m18n
|
|
||||||
from moulinette.utils.filesystem import mkdir
|
from moulinette.utils.filesystem import mkdir
|
||||||
|
|
||||||
from yunohost.app import app_install, app_remove, app_ssowatconf, _is_installed, app_upgrade, app_map
|
from yunohost.app import (
|
||||||
|
app_install,
|
||||||
|
app_remove,
|
||||||
|
app_ssowatconf,
|
||||||
|
_is_installed,
|
||||||
|
app_upgrade,
|
||||||
|
app_map,
|
||||||
|
)
|
||||||
from yunohost.domain import _get_maindomain, domain_add, domain_remove, domain_list
|
from yunohost.domain import _get_maindomain, domain_add, domain_remove, domain_list
|
||||||
from yunohost.utils.error import YunohostError
|
from yunohost.utils.error import YunohostError
|
||||||
from yunohost.tests.test_permission import check_LDAP_db_integrity, check_permission_for_apps
|
from yunohost.tests.test_permission import (
|
||||||
|
check_LDAP_db_integrity,
|
||||||
|
check_permission_for_apps,
|
||||||
|
)
|
||||||
from yunohost.permission import user_permission_list, permission_delete
|
from yunohost.permission import user_permission_list, permission_delete
|
||||||
|
|
||||||
|
|
||||||
|
@ -20,10 +29,12 @@ def setup_function(function):
|
||||||
|
|
||||||
clean()
|
clean()
|
||||||
|
|
||||||
|
|
||||||
def teardown_function(function):
|
def teardown_function(function):
|
||||||
|
|
||||||
clean()
|
clean()
|
||||||
|
|
||||||
|
|
||||||
def clean():
|
def clean():
|
||||||
|
|
||||||
# Make sure we have a ssowat
|
# Make sure we have a ssowat
|
||||||
|
@ -44,10 +55,18 @@ def clean():
|
||||||
for folderpath in glob.glob("/var/www/*%s*" % test_app):
|
for folderpath in glob.glob("/var/www/*%s*" % test_app):
|
||||||
shutil.rmtree(folderpath, ignore_errors=True)
|
shutil.rmtree(folderpath, ignore_errors=True)
|
||||||
|
|
||||||
os.system("bash -c \"mysql -u root --password=$(cat /etc/yunohost/mysql) 2>/dev/null <<< 'DROP DATABASE %s' \"" % test_app)
|
os.system(
|
||||||
os.system("bash -c \"mysql -u root --password=$(cat /etc/yunohost/mysql) 2>/dev/null <<< 'DROP USER %s@localhost'\"" % test_app)
|
"bash -c \"mysql -u root --password=$(cat /etc/yunohost/mysql) 2>/dev/null <<< 'DROP DATABASE %s' \""
|
||||||
|
% test_app
|
||||||
|
)
|
||||||
|
os.system(
|
||||||
|
"bash -c \"mysql -u root --password=$(cat /etc/yunohost/mysql) 2>/dev/null <<< 'DROP USER %s@localhost'\""
|
||||||
|
% test_app
|
||||||
|
)
|
||||||
|
|
||||||
os.system("systemctl reset-failed nginx") # Reset failed quota for service to avoid running into start-limit rate ?
|
os.system(
|
||||||
|
"systemctl reset-failed nginx"
|
||||||
|
) # Reset failed quota for service to avoid running into start-limit rate ?
|
||||||
os.system("systemctl start nginx")
|
os.system("systemctl start nginx")
|
||||||
|
|
||||||
# Clean permissions
|
# Clean permissions
|
||||||
|
@ -55,6 +74,7 @@ def clean():
|
||||||
if any(test_app in permission_name for test_app in test_apps):
|
if any(test_app in permission_name for test_app in test_apps):
|
||||||
permission_delete(permission_name, force=True)
|
permission_delete(permission_name, force=True)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(autouse=True)
|
@pytest.fixture(autouse=True)
|
||||||
def check_LDAP_db_integrity_call():
|
def check_LDAP_db_integrity_call():
|
||||||
check_LDAP_db_integrity()
|
check_LDAP_db_integrity()
|
||||||
|
@ -68,6 +88,7 @@ def check_permission_for_apps_call():
|
||||||
yield
|
yield
|
||||||
check_permission_for_apps()
|
check_permission_for_apps()
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def secondary_domain(request):
|
def secondary_domain(request):
|
||||||
|
|
||||||
|
@ -76,6 +97,7 @@ def secondary_domain(request):
|
||||||
|
|
||||||
def remove_example_domain():
|
def remove_example_domain():
|
||||||
domain_remove("example.test")
|
domain_remove("example.test")
|
||||||
|
|
||||||
request.addfinalizer(remove_example_domain)
|
request.addfinalizer(remove_example_domain)
|
||||||
|
|
||||||
return "example.test"
|
return "example.test"
|
||||||
|
@ -85,6 +107,7 @@ def secondary_domain(request):
|
||||||
# Helpers #
|
# Helpers #
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
def app_expected_files(domain, app):
|
def app_expected_files(domain, app):
|
||||||
|
|
||||||
yield "/etc/nginx/conf.d/%s.d/%s.conf" % (domain, app)
|
yield "/etc/nginx/conf.d/%s.d/%s.conf" % (domain, app)
|
||||||
|
@ -98,42 +121,55 @@ def app_expected_files(domain, app):
|
||||||
|
|
||||||
def app_is_installed(domain, app):
|
def app_is_installed(domain, app):
|
||||||
|
|
||||||
return _is_installed(app) and all(os.path.exists(f) for f in app_expected_files(domain, app))
|
return _is_installed(app) and all(
|
||||||
|
os.path.exists(f) for f in app_expected_files(domain, app)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def app_is_not_installed(domain, app):
|
def app_is_not_installed(domain, app):
|
||||||
|
|
||||||
return not _is_installed(app) and not all(os.path.exists(f) for f in app_expected_files(domain, app))
|
return not _is_installed(app) and not all(
|
||||||
|
os.path.exists(f) for f in app_expected_files(domain, app)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def app_is_exposed_on_http(domain, path, message_in_page):
|
def app_is_exposed_on_http(domain, path, message_in_page):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
r = requests.get("http://127.0.0.1" + path + "/", headers={"Host": domain}, timeout=10, verify=False)
|
r = requests.get(
|
||||||
|
"http://127.0.0.1" + path + "/",
|
||||||
|
headers={"Host": domain},
|
||||||
|
timeout=10,
|
||||||
|
verify=False,
|
||||||
|
)
|
||||||
return r.status_code == 200 and message_in_page in r.text
|
return r.status_code == 200 and message_in_page in r.text
|
||||||
except Exception as e:
|
except Exception:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def install_legacy_app(domain, path, public=True):
|
def install_legacy_app(domain, path, public=True):
|
||||||
|
|
||||||
app_install("./tests/apps/legacy_app_ynh",
|
app_install(
|
||||||
args="domain=%s&path=%s&is_public=%s" % (domain, path, 1 if public else 0),
|
"./tests/apps/legacy_app_ynh",
|
||||||
force=True)
|
args="domain=%s&path=%s&is_public=%s" % (domain, path, 1 if public else 0),
|
||||||
|
force=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def install_full_domain_app(domain):
|
def install_full_domain_app(domain):
|
||||||
|
|
||||||
app_install("./tests/apps/full_domain_app_ynh",
|
app_install(
|
||||||
args="domain=%s" % domain,
|
"./tests/apps/full_domain_app_ynh", args="domain=%s" % domain, force=True
|
||||||
force=True)
|
)
|
||||||
|
|
||||||
|
|
||||||
def install_break_yo_system(domain, breakwhat):
|
def install_break_yo_system(domain, breakwhat):
|
||||||
|
|
||||||
app_install("./tests/apps/break_yo_system_ynh",
|
app_install(
|
||||||
args="domain=%s&breakwhat=%s" % (domain, breakwhat),
|
"./tests/apps/break_yo_system_ynh",
|
||||||
force=True)
|
args="domain=%s&breakwhat=%s" % (domain, breakwhat),
|
||||||
|
force=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_legacy_app_install_main_domain():
|
def test_legacy_app_install_main_domain():
|
||||||
|
@ -144,9 +180,9 @@ def test_legacy_app_install_main_domain():
|
||||||
|
|
||||||
app_map_ = app_map(raw=True)
|
app_map_ = app_map(raw=True)
|
||||||
assert main_domain in app_map_
|
assert main_domain in app_map_
|
||||||
assert '/legacy' in app_map_[main_domain]
|
assert "/legacy" in app_map_[main_domain]
|
||||||
assert 'id' in app_map_[main_domain]['/legacy']
|
assert "id" in app_map_[main_domain]["/legacy"]
|
||||||
assert app_map_[main_domain]['/legacy']['id'] == 'legacy_app'
|
assert app_map_[main_domain]["/legacy"]["id"] == "legacy_app"
|
||||||
|
|
||||||
assert app_is_installed(main_domain, "legacy_app")
|
assert app_is_installed(main_domain, "legacy_app")
|
||||||
assert app_is_exposed_on_http(main_domain, "/legacy", "This is a dummy app")
|
assert app_is_exposed_on_http(main_domain, "/legacy", "This is a dummy app")
|
||||||
|
@ -174,9 +210,9 @@ def test_legacy_app_install_secondary_domain_on_root(secondary_domain):
|
||||||
|
|
||||||
app_map_ = app_map(raw=True)
|
app_map_ = app_map(raw=True)
|
||||||
assert secondary_domain in app_map_
|
assert secondary_domain in app_map_
|
||||||
assert '/' in app_map_[secondary_domain]
|
assert "/" in app_map_[secondary_domain]
|
||||||
assert 'id' in app_map_[secondary_domain]['/']
|
assert "id" in app_map_[secondary_domain]["/"]
|
||||||
assert app_map_[secondary_domain]['/']['id'] == 'legacy_app'
|
assert app_map_[secondary_domain]["/"]["id"] == "legacy_app"
|
||||||
|
|
||||||
assert app_is_installed(secondary_domain, "legacy_app")
|
assert app_is_installed(secondary_domain, "legacy_app")
|
||||||
assert app_is_exposed_on_http(secondary_domain, "/", "This is a dummy app")
|
assert app_is_exposed_on_http(secondary_domain, "/", "This is a dummy app")
|
||||||
|
@ -191,7 +227,9 @@ def test_legacy_app_install_private(secondary_domain):
|
||||||
install_legacy_app(secondary_domain, "/legacy", public=False)
|
install_legacy_app(secondary_domain, "/legacy", public=False)
|
||||||
|
|
||||||
assert app_is_installed(secondary_domain, "legacy_app")
|
assert app_is_installed(secondary_domain, "legacy_app")
|
||||||
assert not app_is_exposed_on_http(secondary_domain, "/legacy", "This is a dummy app")
|
assert not app_is_exposed_on_http(
|
||||||
|
secondary_domain, "/legacy", "This is a dummy app"
|
||||||
|
)
|
||||||
|
|
||||||
app_remove("legacy_app")
|
app_remove("legacy_app")
|
||||||
|
|
||||||
|
@ -246,7 +284,9 @@ def test_legacy_app_install_with_nginx_down(mocker, secondary_domain):
|
||||||
|
|
||||||
os.system("systemctl stop nginx")
|
os.system("systemctl stop nginx")
|
||||||
|
|
||||||
with raiseYunohostError(mocker, "app_action_cannot_be_ran_because_required_services_down"):
|
with raiseYunohostError(
|
||||||
|
mocker, "app_action_cannot_be_ran_because_required_services_down"
|
||||||
|
):
|
||||||
install_legacy_app(secondary_domain, "/legacy")
|
install_legacy_app(secondary_domain, "/legacy")
|
||||||
|
|
||||||
|
|
||||||
|
@ -257,7 +297,7 @@ def test_legacy_app_failed_install(mocker, secondary_domain):
|
||||||
mkdir("/var/www/legacy_app/", 0o750)
|
mkdir("/var/www/legacy_app/", 0o750)
|
||||||
|
|
||||||
with pytest.raises(YunohostError):
|
with pytest.raises(YunohostError):
|
||||||
with message(mocker, 'app_install_script_failed'):
|
with message(mocker, "app_install_script_failed"):
|
||||||
install_legacy_app(secondary_domain, "/legacy")
|
install_legacy_app(secondary_domain, "/legacy")
|
||||||
|
|
||||||
assert app_is_not_installed(secondary_domain, "legacy_app")
|
assert app_is_not_installed(secondary_domain, "legacy_app")
|
||||||
|
@ -302,7 +342,7 @@ def test_systemfuckedup_during_app_install(mocker, secondary_domain):
|
||||||
|
|
||||||
with pytest.raises(YunohostError):
|
with pytest.raises(YunohostError):
|
||||||
with message(mocker, "app_install_failed"):
|
with message(mocker, "app_install_failed"):
|
||||||
with message(mocker, 'app_action_broke_system'):
|
with message(mocker, "app_action_broke_system"):
|
||||||
install_break_yo_system(secondary_domain, breakwhat="install")
|
install_break_yo_system(secondary_domain, breakwhat="install")
|
||||||
|
|
||||||
assert app_is_not_installed(secondary_domain, "break_yo_system")
|
assert app_is_not_installed(secondary_domain, "break_yo_system")
|
||||||
|
@ -313,8 +353,8 @@ def test_systemfuckedup_during_app_remove(mocker, secondary_domain):
|
||||||
install_break_yo_system(secondary_domain, breakwhat="remove")
|
install_break_yo_system(secondary_domain, breakwhat="remove")
|
||||||
|
|
||||||
with pytest.raises(YunohostError):
|
with pytest.raises(YunohostError):
|
||||||
with message(mocker, 'app_action_broke_system'):
|
with message(mocker, "app_action_broke_system"):
|
||||||
with message(mocker, 'app_removed'):
|
with message(mocker, "app_removed"):
|
||||||
app_remove("break_yo_system")
|
app_remove("break_yo_system")
|
||||||
|
|
||||||
assert app_is_not_installed(secondary_domain, "break_yo_system")
|
assert app_is_not_installed(secondary_domain, "break_yo_system")
|
||||||
|
@ -324,7 +364,7 @@ def test_systemfuckedup_during_app_install_and_remove(mocker, secondary_domain):
|
||||||
|
|
||||||
with pytest.raises(YunohostError):
|
with pytest.raises(YunohostError):
|
||||||
with message(mocker, "app_install_failed"):
|
with message(mocker, "app_install_failed"):
|
||||||
with message(mocker, 'app_action_broke_system'):
|
with message(mocker, "app_action_broke_system"):
|
||||||
install_break_yo_system(secondary_domain, breakwhat="everything")
|
install_break_yo_system(secondary_domain, breakwhat="everything")
|
||||||
|
|
||||||
assert app_is_not_installed(secondary_domain, "break_yo_system")
|
assert app_is_not_installed(secondary_domain, "break_yo_system")
|
||||||
|
@ -335,7 +375,7 @@ def test_systemfuckedup_during_app_upgrade(mocker, secondary_domain):
|
||||||
install_break_yo_system(secondary_domain, breakwhat="upgrade")
|
install_break_yo_system(secondary_domain, breakwhat="upgrade")
|
||||||
|
|
||||||
with pytest.raises(YunohostError):
|
with pytest.raises(YunohostError):
|
||||||
with message(mocker, 'app_action_broke_system'):
|
with message(mocker, "app_action_broke_system"):
|
||||||
app_upgrade("break_yo_system", file="./tests/apps/break_yo_system_ynh")
|
app_upgrade("break_yo_system", file="./tests/apps/break_yo_system_ynh")
|
||||||
|
|
||||||
|
|
||||||
|
@ -346,6 +386,10 @@ def test_failed_multiple_app_upgrade(mocker, secondary_domain):
|
||||||
|
|
||||||
with pytest.raises(YunohostError):
|
with pytest.raises(YunohostError):
|
||||||
with message(mocker, "app_not_upgraded"):
|
with message(mocker, "app_not_upgraded"):
|
||||||
app_upgrade(["break_yo_system", "legacy_app"],
|
app_upgrade(
|
||||||
file={"break_yo_system": "./tests/apps/break_yo_system_ynh",
|
["break_yo_system", "legacy_app"],
|
||||||
"legacy": "./tests/apps/legacy_app_ynh"})
|
file={
|
||||||
|
"break_yo_system": "./tests/apps/break_yo_system_ynh",
|
||||||
|
"legacy": "./tests/apps/legacy_app_ynh",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
Loading…
Add table
Reference in a new issue