django-cachalot/cachalot/tests/settings.py
Andrew-Chen-Wang 602cdcee1d
Version 2.2.0 (#146)
This PR upgrades cachalot to version 2.2.0 allowing for anyone to install cachalot at any Django package above 1.11. All tests currently function now.

* Added mysql as a service to fix Travis CI

* Removed tox dependency

* Removed upper limit on Django and support 2.2-3.0 CI Test
* Cachalot will only say "officially supports" while removing upper limit to not hinder anyone's progress.
* Added Python 3.8 and Django 2.2 and 3.0 to CI tests

- Max is 200 and we'll get there quickly if we add another Python version. Utilizes #127
- Keep dependencies for six and django.utils.six

* Correctly run Travis test by updating tox.ini
* Originally using tox syntax but changed testenv to travis so that travis env and travis dependencies and stuff are used

* Tox tests should start running command

* testenv without dependencies broke travis. New spot in Tox
* testenv without dependencies broke travis
* I can't figure out where testenv is supposed to be
* Good thing there's squash

* Added missing six in test
* Also added six package to Tox for Django 3.0 coverage.
* The missing six package caused several problems in several tests due to using an incorrect DB

* Resolves #138
* Need to add the panels here in order to satisfy tests

* Adds CachalotPanel to Python 2 backwards compatibility
* Forgot super class took those like save()

* Added databases to certain test cases
* APITestCase, DebugToolbarTestCase, SignalsTestCase required a database set
* Fixes errors like these: https://travis-ci.org/noripyt/django-cachalot/jobs/648691385#L4892

* Dropped OFFICIAL support for Python 3.4 + MySQL
* MySQL and its client on 3.4 is f--king up a lot of the testing and I can't bear with it. We can revisit it later, but, honestly, who uses Python 3.4... and if an organization is, then they will either have no problem with Postgres and SQLite or know that MySQL doesn't work.

* Drop Py3.4 from running. Fixed databases
* Now goes with setting's databases rather than hardcoded since some tests don't have other databases.

* Fix ReadTestCase

Django 2.2+ changed self.queryset at line 1000 with self.query=queryset.query

* Django Dependency Removed from utils.py

* Last commit used Django version. This one used try except

* Fixed assertNumQuery; added allow_failures for 3.4
* Primary: More information in test_utils.py with method is_django_21_below_and_is_sqlite
* The problem with the entire build lie in the self.is_sqlite for the tests. SQLite will make 2 queries when creating or destroying or updating instead of 1.
* In summary, if SQLite is the DB and Django

* Changed build matrix to allow failures for 3.4 instead of taking it out completely so that we can get it to work soon.

* Remove -> From function return
* I love backwards compatibility

* SQLite2 in multi_db.py returned incorrect bool

* Django 2.1 and SQLite checker doesn't work for some tests
* Some tests DO HAVE the BEGIN query that is returned... Not sure why. If the next test show completely different WriteTestCase problems, then we need to find alternative.
* Removed check from atomic

* Adjust Django and is_sqlite errors
* CI testing the Tox errors: https://travis-ci.org/noripyt/django-cachalot?utm_medium=notification&utm_source=github_status

* Adjust Django and is_sqlite errors (590 CI)
* CI testing the Tox errors: https://travis-ci.org/noripyt/django-cachalot?utm_medium=notification&utm_source=github_status
* Adjustment 2

* Make include matrix and Adjust Django and is_sqlite errors (594 CI)
* CI testing the Tox errors: https://travis-ci.org/noripyt/django-cachalot?utm_medium=notification&utm_source=github_status
* Adjustment 3

* Adjust Django and is_sqlite errors (596 CI)
* CI testing the Tox errors: https://travis-ci.org/noripyt/django-cachalot?utm_medium=notification&utm_source=github_status
* Adjustment 4
* Added my intro to ReadTheDocs

* Adjust Django and is_sqlite errors (598 CI)
* CI testing the Tox errors: https://travis-ci.org/noripyt/django-cachalot?utm_medium=notification&utm_source=github_status
* Adjustment 5

* Drop Python 3.4 from tests since PyLibMC not cooperating at that level.

* Bump package version up 1 minor for Django 2.2 and 3.0
2020-02-12 00:52:12 -05:00

285 lines
11 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# coding: utf-8
from __future__ import unicode_literals
from time import sleep
from unittest import skipIf
from django.conf import settings
from django.contrib.auth.models import User
from django.core.cache import DEFAULT_CACHE_ALIAS
from django.core.checks import run_checks, Tags, Warning, Error
from django.db import connection
from django.test import TransactionTestCase
from django.test.utils import override_settings
from ..api import invalidate
from ..settings import SUPPORTED_ONLY, SUPPORTED_DATABASE_ENGINES
from .models import Test, TestParent, TestChild
from .test_utils import TestUtilsMixin
class SettingsTestCase(TestUtilsMixin, TransactionTestCase):
@override_settings(CACHALOT_ENABLED=False)
def test_decorator(self):
self.assert_query_cached(Test.objects.all(), after=1)
def test_django_override(self):
with self.settings(CACHALOT_ENABLED=False):
qs = Test.objects.all()
self.assert_query_cached(qs, after=1)
with self.settings(CACHALOT_ENABLED=True):
self.assert_query_cached(qs)
def test_enabled(self):
qs = Test.objects.all()
with self.settings(CACHALOT_ENABLED=True):
self.assert_query_cached(qs)
with self.settings(CACHALOT_ENABLED=False):
self.assert_query_cached(qs, after=1)
with self.assertNumQueries(0):
list(Test.objects.all())
with self.settings(CACHALOT_ENABLED=False):
with self.assertNumQueries(2 if self.is_dj_21_below_and_is_sqlite() else 1):
t = Test.objects.create(name='test')
with self.assertNumQueries(1):
data = list(Test.objects.all())
self.assertListEqual(data, [t])
@skipIf(len(settings.CACHES) == 1, 'We cant change the cache used '
'since theres only one configured.')
def test_cache(self):
other_cache_alias = next(alias for alias in settings.CACHES
if alias != DEFAULT_CACHE_ALIAS)
invalidate(Test, cache_alias=other_cache_alias)
qs = Test.objects.all()
with self.settings(CACHALOT_CACHE=DEFAULT_CACHE_ALIAS):
self.assert_query_cached(qs)
with self.settings(CACHALOT_CACHE=other_cache_alias):
self.assert_query_cached(qs)
Test.objects.create(name='test')
# Only `CACHALOT_CACHE` is invalidated, so changing the database should
# not invalidate all caches.
with self.settings(CACHALOT_CACHE=other_cache_alias):
self.assert_query_cached(qs, before=0)
def test_databases(self):
qs = Test.objects.all()
with self.settings(CACHALOT_DATABASES=SUPPORTED_ONLY):
self.assert_query_cached(qs)
invalidate(Test)
engine = connection.settings_dict['ENGINE']
SUPPORTED_DATABASE_ENGINES.remove(engine)
with self.settings(CACHALOT_DATABASES=SUPPORTED_ONLY):
self.assert_query_cached(qs, after=1)
SUPPORTED_DATABASE_ENGINES.add(engine)
with self.settings(CACHALOT_DATABASES=SUPPORTED_ONLY):
self.assert_query_cached(qs)
with self.settings(CACHALOT_DATABASES=[]):
self.assert_query_cached(qs, after=1)
def test_cache_timeout(self):
qs = Test.objects.all()
with self.assertNumQueries(1):
list(qs.all())
sleep(1)
with self.assertNumQueries(0):
list(qs.all())
invalidate(Test)
with self.settings(CACHALOT_TIMEOUT=0):
with self.assertNumQueries(1):
list(qs.all())
sleep(0.05)
with self.assertNumQueries(1):
list(qs.all())
# We have to test with a full second and not a shorter time because
# memcached only takes the integer part of the timeout into account.
with self.settings(CACHALOT_TIMEOUT=1):
self.assert_query_cached(qs)
sleep(1)
with self.assertNumQueries(1):
list(Test.objects.all())
def test_cache_random(self):
qs = Test.objects.order_by('?')
self.assert_query_cached(qs, after=1, compare_results=False)
with self.settings(CACHALOT_CACHE_RANDOM=True):
self.assert_query_cached(qs)
def test_invalidate_raw(self):
with self.assertNumQueries(1):
list(Test.objects.all())
with self.settings(CACHALOT_INVALIDATE_RAW=False):
with self.assertNumQueries(1):
with connection.cursor() as cursor:
cursor.execute("UPDATE %s SET name = 'new name';"
% Test._meta.db_table)
with self.assertNumQueries(0):
list(Test.objects.all())
def test_only_cachable_tables(self):
with self.settings(CACHALOT_ONLY_CACHABLE_TABLES=('cachalot_test',)):
self.assert_query_cached(Test.objects.all())
self.assert_query_cached(TestParent.objects.all(), after=1)
self.assert_query_cached(Test.objects.select_related('owner'),
after=1)
self.assert_query_cached(TestParent.objects.all())
with self.settings(CACHALOT_ONLY_CACHABLE_TABLES=(
'cachalot_test', 'cachalot_testchild', 'auth_user')):
self.assert_query_cached(Test.objects.select_related('owner'))
# TestChild uses multi-table inheritance, and since its parent,
# 'cachalot_testparent', is not cachable, a basic
# TestChild query cant be cached
self.assert_query_cached(TestChild.objects.all(), after=1)
# However, if we only fetch data from the 'cachalot_testchild'
# table, its cachable.
self.assert_query_cached(TestChild.objects.values('public'))
def test_uncachable_tables(self):
qs = Test.objects.all()
with self.settings(CACHALOT_UNCACHABLE_TABLES=('cachalot_test',)):
self.assert_query_cached(qs, after=1)
self.assert_query_cached(qs)
with self.settings(CACHALOT_UNCACHABLE_TABLES=('cachalot_test',)):
self.assert_query_cached(qs, after=1)
def test_only_cachable_and_uncachable_table(self):
with self.settings(
CACHALOT_ONLY_CACHABLE_TABLES=('cachalot_test',
'cachalot_testparent'),
CACHALOT_UNCACHABLE_TABLES=('cachalot_test',)):
self.assert_query_cached(Test.objects.all(), after=1)
self.assert_query_cached(TestParent.objects.all())
self.assert_query_cached(User.objects.all(), after=1)
def test_cache_compatibility(self):
compatible_cache = {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
}
incompatible_cache = {
'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
'LOCATION': 'cache_table'
}
with self.settings(CACHES={'default': compatible_cache,
'secondary': incompatible_cache}):
errors = run_checks(tags=[Tags.compatibility])
self.assertListEqual(errors, [])
warning001 = Warning(
'Cache backend %r is not supported by django-cachalot.'
% 'django.core.cache.backends.db.DatabaseCache',
hint='Switch to a supported cache backend '
'like Redis or Memcached.',
id='cachalot.W001')
with self.settings(CACHES={'default': incompatible_cache}):
errors = run_checks(tags=[Tags.compatibility])
self.assertListEqual(errors, [warning001])
with self.settings(CACHES={'default': compatible_cache,
'secondary': incompatible_cache},
CACHALOT_CACHE='secondary'):
errors = run_checks(tags=[Tags.compatibility])
self.assertListEqual(errors, [warning001])
def test_database_compatibility(self):
compatible_database = {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'non_existent_db.sqlite3',
}
incompatible_database = {
'ENGINE': 'django.db.backends.oracle',
'NAME': 'non_existent_db',
}
warning002 = Warning(
'None of the configured databases are supported '
'by django-cachalot.',
hint='Use a supported database, or remove django-cachalot, or '
'put at least one database alias in `CACHALOT_DATABASES` '
'to force django-cachalot to use it.',
id='cachalot.W002'
)
warning003 = Warning(
'Database engine %r is not supported by django-cachalot.'
% 'django.db.backends.oracle',
hint='Switch to a supported database engine.',
id='cachalot.W003'
)
warning004 = Warning(
'Django-cachalot is useless because no database '
'is configured in `CACHALOT_DATABASES`.',
hint='Reconfigure django-cachalot or remove it.',
id='cachalot.W004'
)
error001 = Error(
'Database alias %r from `CACHALOT_DATABASES` '
'is not defined in `DATABASES`.' % 'secondary',
hint='Change `CACHALOT_DATABASES` to be compliant with'
'`CACHALOT_DATABASES`',
id='cachalot.E001',
)
error002 = Error(
"`CACHALOT_DATABASES` must be either %r or a list, tuple, "
"frozenset or set of database aliases." % SUPPORTED_ONLY,
hint='Remove `CACHALOT_DATABASES` or change it.',
id='cachalot.E002',
)
with self.settings(DATABASES={'default': incompatible_database}):
errors = run_checks(tags=[Tags.compatibility])
self.assertListEqual(errors, [warning002])
with self.settings(DATABASES={'default': compatible_database,
'secondary': incompatible_database}):
errors = run_checks(tags=[Tags.compatibility])
self.assertListEqual(errors, [])
with self.settings(DATABASES={'default': incompatible_database,
'secondary': compatible_database}):
errors = run_checks(tags=[Tags.compatibility])
self.assertListEqual(errors, [])
with self.settings(DATABASES={'default': incompatible_database},
CACHALOT_DATABASES=['default']):
errors = run_checks(tags=[Tags.compatibility])
self.assertListEqual(errors, [warning003])
with self.settings(DATABASES={'default': incompatible_database},
CACHALOT_DATABASES=[]):
errors = run_checks(tags=[Tags.compatibility])
self.assertListEqual(errors, [warning004])
with self.settings(DATABASES={'default': incompatible_database},
CACHALOT_DATABASES=['secondary']):
errors = run_checks(tags=[Tags.compatibility])
self.assertListEqual(errors, [error001])
with self.settings(DATABASES={'default': compatible_database},
CACHALOT_DATABASES=['default', 'secondary']):
errors = run_checks(tags=[Tags.compatibility])
self.assertListEqual(errors, [error001])
with self.settings(CACHALOT_DATABASES='invalid value'):
errors = run_checks(tags=[Tags.compatibility])
self.assertListEqual(errors, [error002])