181 lines
6.5 KiB
Python
181 lines
6.5 KiB
Python
import http
|
|
import os
|
|
import socket
|
|
import time
|
|
|
|
import pytest
|
|
from django.core.exceptions import ObjectDoesNotExist
|
|
from django.urls import reverse
|
|
from pytest_django.live_server_helper import LiveServer
|
|
|
|
from perms.models import Perm
|
|
from users.models import UserInfo
|
|
|
|
DEFAULT_USER = 'admin'
|
|
DEFAULT_PASSWORD = 'nimda'
|
|
|
|
TEST_LANGS = sorted(('ru', 'en'))
|
|
TEST_TIMEZONES = sorted(('UTC', 'Europe/Moscow', 'Europe/Paris', 'America/New_York'))
|
|
|
|
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
CUR_DIR = os.path.abspath(os.getcwd())
|
|
TIMEOUT = 10 # time before timeout exception appears
|
|
POLL_TIMEOUT = 0.3 # time execute next poll cycle, for example when waiting element
|
|
|
|
from django.conf import settings
|
|
|
|
LOGS_F = os.path.join(getattr(settings, 'LOG_PATH', ''), getattr(settings, 'USER_LOG_FILENAME', ''))
|
|
|
|
|
|
@pytest.fixture(scope='session')
|
|
def test_server() -> LiveServer:
|
|
""" Custom fixture for creating live test server """
|
|
addr = socket.gethostbyname(socket.gethostname())
|
|
server = LiveServer(addr)
|
|
try:
|
|
yield server
|
|
finally:
|
|
server.stop()
|
|
|
|
|
|
def find_message_in_log_file(file, message):
|
|
""" Function for finding certain string in log file
|
|
:param file: Log file descriptor
|
|
:param message: message, that needs to be found
|
|
:return:
|
|
Assert True if message is found
|
|
Assert False if message not found
|
|
"""
|
|
with open(file, encoding='utf-8') as f:
|
|
if message in f.read():
|
|
return True, message
|
|
else:
|
|
return False, message
|
|
|
|
|
|
@pytest.fixture
|
|
def get_url(test_server):
|
|
""" Get url from liveserver
|
|
|
|
:param url: Url's name
|
|
:param kwargs: Dictionary with arguments for reverse function
|
|
:return: string with url
|
|
"""
|
|
|
|
def _get_url(url, kwargs=None):
|
|
return test_server.url + reverse(url, kwargs=kwargs)
|
|
|
|
return _get_url
|
|
|
|
|
|
@pytest.fixture
|
|
def add_user_with_permissions(django_user_model):
|
|
""" Add user with selected permissions
|
|
|
|
:param username: User name
|
|
:param password: User password
|
|
:param permissions: List with Perm's permissions, that will be add to created user
|
|
:param is_superuser: If True - user will be superuser
|
|
:return: created user with updated permissions cache
|
|
"""
|
|
|
|
def _login_user(username, password, permissions=[], is_superuser=False):
|
|
user = django_user_model.objects.create_user(username=username, password=password)
|
|
if is_superuser:
|
|
user.is_superuser = True
|
|
user.save()
|
|
|
|
UserInfo(user=user).save()
|
|
|
|
for cur in permissions:
|
|
user.user_permissions.add(Perm.get_rights(cur))
|
|
|
|
return django_user_model.objects.get(pk=user.pk)
|
|
|
|
return _login_user
|
|
|
|
|
|
def wait_db_element(query_method, message='', timeout=TIMEOUT, poll=POLL_TIMEOUT):
|
|
end_time = time.time() + timeout
|
|
screen, stacktrace = None, None
|
|
while True:
|
|
try:
|
|
e = query_method()
|
|
if e:
|
|
return e
|
|
except ObjectDoesNotExist as exc:
|
|
message = message or str(exc)
|
|
screen = getattr(exc, 'screen', None)
|
|
stacktrace = getattr(exc, 'stacktrace', None)
|
|
time.sleep(poll)
|
|
if time.time() > end_time:
|
|
break
|
|
# TODO: Maybe add here screen and stacktrace from above
|
|
raise RuntimeError(message)
|
|
|
|
|
|
class PermApiBaseTest:
|
|
""" Test class for checking API permissions
|
|
@param get_url: URL to check
|
|
@param test_server: testing server instance
|
|
@param api_list: Fixture with API for testing in following format:
|
|
[Permission_to_check, URL of api, arguments for API (optional)]
|
|
e.x. with arguments
|
|
[[Perm.can_export_events], 'api_change_event_export', dict(state='disable')]
|
|
e.x. without arguments
|
|
[[Perm.can_export_events], 'api_change_event_export']
|
|
"""
|
|
|
|
def test_api_without_perms(self, get_url, test_server, api_list, add_user_with_permissions, client):
|
|
username = 'user_with_no_perms'
|
|
password = 'nimda'
|
|
user = add_user_with_permissions(username=username, password=password)
|
|
client.force_login(user)
|
|
if len(api_list) == 2:
|
|
response = client.get(get_url(api_list[1]))
|
|
elif len(api_list) == 3:
|
|
response = client.get(get_url(api_list[1], api_list[2]))
|
|
else:
|
|
assert False, f'Incorrect format of api_list instance: {api_list}'
|
|
assert response.status_code == http.HTTPStatus.FORBIDDEN
|
|
|
|
def test_api_with_perms(self, get_url, test_server, add_user_with_permissions, api_list, client):
|
|
# username 'admin_1' used instead of DEFAULT_USER because in some cases login_user failing due to the
|
|
# existence of user with that username
|
|
# Fixed by @lvlukianenko in recent commits
|
|
username = 'user_with_perms'
|
|
password = 'nimda'
|
|
user = add_user_with_permissions(username=username, password=password, permissions=api_list[0])
|
|
client.force_login(user)
|
|
if len(api_list) == 2:
|
|
response = client.get(get_url(api_list[1]))
|
|
elif len(api_list) == 3:
|
|
response = client.get(get_url(api_list[1], api_list[2]))
|
|
else:
|
|
assert False, f'Incorrect format of api_list instance: {api_list}'
|
|
assert response.status_code == http.HTTPStatus.OK
|
|
|
|
# TODO: Move to integration tests
|
|
# class TestDeleteElasticsearchIndexes:
|
|
# index_name = 'test-index'
|
|
#
|
|
# @pytest.fixture(autouse=True)
|
|
# def setup_tests(self):
|
|
# self.es = Elasticsearch([{'host': ELK_HOST, 'port': ELK_PORT}], http_auth=(ELK_LOGIN, ELK_PASS))
|
|
# for i in range(3):
|
|
# self.es.indices.create(index=f'{self.index_name}-{i}', ignore=400)
|
|
# yield
|
|
# self.es.indices.delete(index=f'{self.index_name}-*', ignore=[400, 404])
|
|
#
|
|
# def test_delete_all_index_by_template(self):
|
|
# index_template = f'{self.index_name}-*'
|
|
# index_count = len(self.es.indices.get_alias(index=index_template).keys())
|
|
# assert index_count == 3
|
|
# delete_elasticsearch_indexes_by_template(index_template)
|
|
# assert len(self.es.indices.get_alias(index=index_template)) == 0
|
|
#
|
|
# @pytest.mark.parametrize('exclude_indexes,expected', TEST_EXCLUDE_INDEXES)
|
|
# def test_delete_index_by_template_witch_exclude_index(self, exclude_indexes: set, expected: int):
|
|
# index_template = f'{self.index_name}-*'
|
|
# delete_elasticsearch_indexes_by_template(index_template, es=self.es, exclude_indexes=exclude_indexes)
|
|
# assert len(self.es.indices.get_alias(index=index_template, ignore=[400, 404])) == expected
|