mirror of
https://github.com/ansible/awx.git
synced 2026-02-26 07:26:03 -03:30
Merge pull request #1818 from chrismeyersfsu/fix-parallel_failures
isolate test cache
This commit is contained in:
0
awx/conf/tests/__init__.py
Normal file
0
awx/conf/tests/__init__.py
Normal file
6
awx/conf/tests/test_env.py
Normal file
6
awx/conf/tests/test_env.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
|
||||||
|
# Ensure that our autouse overwrites are working
|
||||||
|
def test_cache(settings):
|
||||||
|
assert settings.CACHES['default']['BACKEND'] == 'django.core.cache.backends.locmem.LocMemCache'
|
||||||
|
assert settings.CACHES['default']['LOCATION'].startswith('unique-')
|
||||||
@@ -106,3 +106,21 @@ def get_ssh_version(mocker):
|
|||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def job_template_with_survey_passwords_unit(job_template_with_survey_passwords_factory):
|
def job_template_with_survey_passwords_unit(job_template_with_survey_passwords_factory):
|
||||||
return job_template_with_survey_passwords_factory(persisted=False)
|
return job_template_with_survey_passwords_factory(persisted=False)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def mock_cache():
|
||||||
|
class MockCache(object):
|
||||||
|
cache = {}
|
||||||
|
|
||||||
|
def get(self, key, default=None):
|
||||||
|
return self.cache.get(key, default)
|
||||||
|
|
||||||
|
def set(self, key, value, timeout=60):
|
||||||
|
self.cache[key] = value
|
||||||
|
|
||||||
|
def delete(self, key):
|
||||||
|
del self.cache[key]
|
||||||
|
|
||||||
|
return MockCache()
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ from six.moves import xrange
|
|||||||
|
|
||||||
# Django
|
# Django
|
||||||
from django.core.urlresolvers import resolve
|
from django.core.urlresolvers import resolve
|
||||||
from django.core.cache import cache
|
|
||||||
from django.utils.six.moves.urllib.parse import urlparse
|
from django.utils.six.moves.urllib.parse import urlparse
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
@@ -57,14 +56,6 @@ def swagger_autogen(requests=__SWAGGER_REQUESTS__):
|
|||||||
return requests
|
return requests
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(autouse=True)
|
|
||||||
def clear_cache():
|
|
||||||
'''
|
|
||||||
Clear cache (local memory) for each test to prevent using cached settings.
|
|
||||||
'''
|
|
||||||
cache.clear()
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="session", autouse=True)
|
@pytest.fixture(scope="session", autouse=True)
|
||||||
def celery_memory_broker():
|
def celery_memory_broker():
|
||||||
'''
|
'''
|
||||||
|
|||||||
@@ -241,15 +241,16 @@ def test_shared_dependencies_launch(default_instance_group, job_template_factory
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_cleanup_interval():
|
def test_cleanup_interval(mock_cache):
|
||||||
assert cache.get('last_celery_task_cleanup') is None
|
with mock.patch.multiple('awx.main.scheduler.task_manager.cache', get=mock_cache.get, set=mock_cache.set):
|
||||||
|
assert mock_cache.get('last_celery_task_cleanup') is None
|
||||||
|
|
||||||
TaskManager().cleanup_inconsistent_celery_tasks()
|
TaskManager().cleanup_inconsistent_celery_tasks()
|
||||||
last_cleanup = cache.get('last_celery_task_cleanup')
|
last_cleanup = mock_cache.get('last_celery_task_cleanup')
|
||||||
assert isinstance(last_cleanup, datetime)
|
assert isinstance(last_cleanup, datetime)
|
||||||
|
|
||||||
TaskManager().cleanup_inconsistent_celery_tasks()
|
TaskManager().cleanup_inconsistent_celery_tasks()
|
||||||
assert cache.get('last_celery_task_cleanup') == last_cleanup
|
assert cache.get('last_celery_task_cleanup') == last_cleanup
|
||||||
|
|
||||||
|
|
||||||
class TestReaper():
|
class TestReaper():
|
||||||
@@ -326,7 +327,8 @@ class TestReaper():
|
|||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
@mock.patch.object(JobNotificationMixin, 'send_notification_templates')
|
@mock.patch.object(JobNotificationMixin, 'send_notification_templates')
|
||||||
@mock.patch.object(TaskManager, 'get_active_tasks', lambda self: ([], []))
|
@mock.patch.object(TaskManager, 'get_active_tasks', lambda self: ([], []))
|
||||||
def test_cleanup_inconsistent_task(self, notify, active_tasks, considered_jobs, reapable_jobs, running_tasks, waiting_tasks, mocker):
|
def test_cleanup_inconsistent_task(self, notify, active_tasks, considered_jobs, reapable_jobs, running_tasks, waiting_tasks, mocker, settings):
|
||||||
|
settings.AWX_INCONSISTENT_TASK_INTERVAL = 0
|
||||||
tm = TaskManager()
|
tm = TaskManager()
|
||||||
|
|
||||||
tm.get_running_tasks = mocker.Mock(return_value=(running_tasks, waiting_tasks))
|
tm.get_running_tasks = mocker.Mock(return_value=(running_tasks, waiting_tasks))
|
||||||
|
|||||||
6
awx/main/tests/test_env.py
Normal file
6
awx/main/tests/test_env.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
|
||||||
|
# Ensure that our autouse overwrites are working
|
||||||
|
def test_cache(settings):
|
||||||
|
assert settings.CACHES['default']['BACKEND'] == 'django.core.cache.backends.locmem.LocMemCache'
|
||||||
|
assert settings.CACHES['default']['LOCATION'].startswith('unique-')
|
||||||
@@ -7,10 +7,10 @@ import pytest
|
|||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
import json
|
import json
|
||||||
import yaml
|
import yaml
|
||||||
|
import mock
|
||||||
|
|
||||||
from backports.tempfile import TemporaryDirectory
|
from backports.tempfile import TemporaryDirectory
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.cache import cache
|
|
||||||
|
|
||||||
from rest_framework.exceptions import ParseError
|
from rest_framework.exceptions import ParseError
|
||||||
|
|
||||||
@@ -26,14 +26,6 @@ from awx.main.models import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(autouse=True)
|
|
||||||
def clear_cache():
|
|
||||||
'''
|
|
||||||
Clear cache (local memory) for each test to prevent using cached settings.
|
|
||||||
'''
|
|
||||||
cache.clear()
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('input_, output', [
|
@pytest.mark.parametrize('input_, output', [
|
||||||
({"foo": "bar"}, {"foo": "bar"}),
|
({"foo": "bar"}, {"foo": "bar"}),
|
||||||
('{"foo": "bar"}', {"foo": "bar"}),
|
('{"foo": "bar"}', {"foo": "bar"}),
|
||||||
@@ -114,46 +106,48 @@ def test_get_type_for_model(model, name):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def memoized_function(mocker):
|
def memoized_function(mocker, mock_cache):
|
||||||
@common.memoize(track_function=True)
|
with mock.patch('awx.main.utils.common.get_memoize_cache', return_value=mock_cache):
|
||||||
def myfunction(key, value):
|
@common.memoize(track_function=True)
|
||||||
if key not in myfunction.calls:
|
def myfunction(key, value):
|
||||||
myfunction.calls[key] = 0
|
if key not in myfunction.calls:
|
||||||
|
myfunction.calls[key] = 0
|
||||||
|
|
||||||
myfunction.calls[key] += 1
|
myfunction.calls[key] += 1
|
||||||
|
|
||||||
if myfunction.calls[key] == 1:
|
if myfunction.calls[key] == 1:
|
||||||
return value
|
return value
|
||||||
else:
|
else:
|
||||||
return '%s called %s times' % (value, myfunction.calls[key])
|
return '%s called %s times' % (value, myfunction.calls[key])
|
||||||
myfunction.calls = dict()
|
myfunction.calls = dict()
|
||||||
return myfunction
|
return myfunction
|
||||||
|
|
||||||
|
|
||||||
def test_memoize_track_function(memoized_function):
|
def test_memoize_track_function(memoized_function, mock_cache):
|
||||||
assert memoized_function('scott', 'scotterson') == 'scotterson'
|
assert memoized_function('scott', 'scotterson') == 'scotterson'
|
||||||
assert cache.get('myfunction') == {u'scott-scotterson': 'scotterson'}
|
assert mock_cache.get('myfunction') == {u'scott-scotterson': 'scotterson'}
|
||||||
assert memoized_function('scott', 'scotterson') == 'scotterson'
|
assert memoized_function('scott', 'scotterson') == 'scotterson'
|
||||||
|
|
||||||
assert memoized_function.calls['scott'] == 1
|
assert memoized_function.calls['scott'] == 1
|
||||||
|
|
||||||
assert memoized_function('john', 'smith') == 'smith'
|
assert memoized_function('john', 'smith') == 'smith'
|
||||||
assert cache.get('myfunction') == {u'scott-scotterson': 'scotterson', u'john-smith': 'smith'}
|
assert mock_cache.get('myfunction') == {u'scott-scotterson': 'scotterson', u'john-smith': 'smith'}
|
||||||
assert memoized_function('john', 'smith') == 'smith'
|
assert memoized_function('john', 'smith') == 'smith'
|
||||||
|
|
||||||
assert memoized_function.calls['john'] == 1
|
assert memoized_function.calls['john'] == 1
|
||||||
|
|
||||||
|
|
||||||
def test_memoize_delete(memoized_function):
|
def test_memoize_delete(memoized_function, mock_cache):
|
||||||
assert memoized_function('john', 'smith') == 'smith'
|
assert memoized_function('john', 'smith') == 'smith'
|
||||||
assert memoized_function('john', 'smith') == 'smith'
|
assert memoized_function('john', 'smith') == 'smith'
|
||||||
assert memoized_function.calls['john'] == 1
|
assert memoized_function.calls['john'] == 1
|
||||||
|
|
||||||
assert cache.get('myfunction') == {u'john-smith': 'smith'}
|
assert mock_cache.get('myfunction') == {u'john-smith': 'smith'}
|
||||||
|
|
||||||
common.memoize_delete('myfunction')
|
with mock.patch('awx.main.utils.common.memoize_delete', side_effect=mock_cache.delete):
|
||||||
|
common.memoize_delete('myfunction')
|
||||||
|
|
||||||
assert cache.get('myfunction') is None
|
assert mock_cache.get('myfunction') is None
|
||||||
|
|
||||||
assert memoized_function('john', 'smith') == 'smith called 2 times'
|
assert memoized_function('john', 'smith') == 'smith called 2 times'
|
||||||
assert memoized_function.calls['john'] == 2
|
assert memoized_function.calls['john'] == 2
|
||||||
|
|||||||
@@ -127,12 +127,16 @@ class IllegalArgumentError(ValueError):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def get_memoize_cache():
|
||||||
|
from django.core.cache import cache
|
||||||
|
return cache
|
||||||
|
|
||||||
|
|
||||||
def memoize(ttl=60, cache_key=None, track_function=False):
|
def memoize(ttl=60, cache_key=None, track_function=False):
|
||||||
'''
|
'''
|
||||||
Decorator to wrap a function and cache its result.
|
Decorator to wrap a function and cache its result.
|
||||||
'''
|
'''
|
||||||
from django.core.cache import cache
|
cache = get_memoize_cache()
|
||||||
|
|
||||||
|
|
||||||
def _memoizer(f, *args, **kwargs):
|
def _memoizer(f, *args, **kwargs):
|
||||||
if cache_key and track_function:
|
if cache_key and track_function:
|
||||||
@@ -160,8 +164,7 @@ def memoize(ttl=60, cache_key=None, track_function=False):
|
|||||||
|
|
||||||
|
|
||||||
def memoize_delete(function_name):
|
def memoize_delete(function_name):
|
||||||
from django.core.cache import cache
|
cache = get_memoize_cache()
|
||||||
|
|
||||||
return cache.delete(function_name)
|
return cache.delete(function_name)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -537,19 +537,12 @@ ASGI_AMQP = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Django Caching Configuration
|
# Django Caching Configuration
|
||||||
if is_testing():
|
CACHES = {
|
||||||
CACHES = {
|
'default': {
|
||||||
'default': {
|
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
|
||||||
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
|
'LOCATION': 'memcached:11211',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
else:
|
|
||||||
CACHES = {
|
|
||||||
'default': {
|
|
||||||
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
|
|
||||||
'LOCATION': 'memcached:11211',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
# Social Auth configuration.
|
# Social Auth configuration.
|
||||||
SOCIAL_AUTH_STRATEGY = 'social_django.strategy.DjangoStrategy'
|
SOCIAL_AUTH_STRATEGY = 'social_django.strategy.DjangoStrategy'
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import socket
|
|||||||
import copy
|
import copy
|
||||||
import sys
|
import sys
|
||||||
import traceback
|
import traceback
|
||||||
|
import random
|
||||||
|
|
||||||
# Centos-7 doesn't include the svg mime type
|
# Centos-7 doesn't include the svg mime type
|
||||||
# /usr/lib64/python/mimetypes.py
|
# /usr/lib64/python/mimetypes.py
|
||||||
@@ -20,6 +21,15 @@ from split_settings.tools import optional, include
|
|||||||
# Load default settings.
|
# Load default settings.
|
||||||
from defaults import * # NOQA
|
from defaults import * # NOQA
|
||||||
|
|
||||||
|
# don't use memcache when running tests
|
||||||
|
if "pytest" in sys.modules:
|
||||||
|
CACHES = {
|
||||||
|
'default': {
|
||||||
|
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
|
||||||
|
'LOCATION': 'unique-{}'.format(random.randint(0, sys.maxint)),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
# awx-manage shell_plus --notebook
|
# awx-manage shell_plus --notebook
|
||||||
NOTEBOOK_ARGUMENTS = [
|
NOTEBOOK_ARGUMENTS = [
|
||||||
'--NotebookApp.token=',
|
'--NotebookApp.token=',
|
||||||
|
|||||||
6
awx/sso/tests/test_env.py
Normal file
6
awx/sso/tests/test_env.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
|
||||||
|
# Ensure that our autouse overwrites are working
|
||||||
|
def test_cache(settings):
|
||||||
|
assert settings.CACHES['default']['BACKEND'] == 'django.core.cache.backends.locmem.LocMemCache'
|
||||||
|
assert settings.CACHES['default']['LOCATION'].startswith('unique-')
|
||||||
Reference in New Issue
Block a user