Skip to content

Commit

Permalink
Merge pull request #59 from diox/remove-django-nose
Browse files Browse the repository at this point in the history
Remove django-nose completely
  • Loading branch information
diox authored May 16, 2024
2 parents 8bda536 + e8830e6 commit db09cce
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 64 deletions.
136 changes: 75 additions & 61 deletions multidb/tests.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,35 @@
import warnings
from threading import Lock, Thread

from django.http import HttpRequest, HttpResponse
from django.test import TestCase
from django.test.utils import override_settings


try:
from unittest import mock
except ImportError:
import mock
from nose.tools import eq_

# For deprecation tests
import multidb
import multidb.pinning

from multidb import (DEFAULT_DB_ALIAS, ReplicaRouter, PinningReplicaRouter,
get_replica)
from multidb.middleware import (pinning_cookie, pinning_cookie_httponly,
pinning_cookie_samesite, pinning_cookie_secure,
pinning_seconds, PinningRouterMiddleware)
from multidb.pinning import (this_thread_is_pinned, pin_this_thread,
unpin_this_thread, use_primary_db, db_write)
from multidb import DEFAULT_DB_ALIAS, PinningReplicaRouter, ReplicaRouter, get_replica
from multidb.middleware import (
PinningRouterMiddleware,
pinning_cookie,
pinning_cookie_httponly,
pinning_cookie_samesite,
pinning_cookie_secure,
pinning_seconds,
)
from multidb.pinning import (
db_write,
pin_this_thread,
this_thread_is_pinned,
unpin_this_thread,
use_primary_db,
)


class UnpinningTestCase(TestCase):
Expand All @@ -31,13 +40,12 @@ def tearDown(self):


class ReplicaRouterTests(TestCase):

def test_db_for_read(self):
eq_(ReplicaRouter().db_for_read(None), get_replica())
self.assertEqual(ReplicaRouter().db_for_read(None), get_replica())
# TODO: Test the round-robin functionality.

def test_db_for_write(self):
eq_(ReplicaRouter().db_for_write(None), DEFAULT_DB_ALIAS)
self.assertEqual(ReplicaRouter().db_for_write(None), DEFAULT_DB_ALIAS)

def test_allow_syncdb(self):
router = ReplicaRouter()
Expand All @@ -46,32 +54,32 @@ def test_allow_syncdb(self):

def test_allow_migrate(self):
router = ReplicaRouter()
assert router.allow_migrate(DEFAULT_DB_ALIAS, 'dummy')
assert not router.allow_migrate(get_replica(), 'dummy')
assert router.allow_migrate(DEFAULT_DB_ALIAS, "dummy")
assert not router.allow_migrate(get_replica(), "dummy")


class SettingsTests(TestCase):
"""Tests for default settings."""

def test_defaults(self):
"""Check that the cookie name has the right default."""
eq_(pinning_cookie(), 'multidb_pin_writes')
eq_(pinning_seconds(), 15)
eq_(pinning_cookie_secure(), False)
eq_(pinning_cookie_httponly(), False)
eq_(pinning_cookie_samesite(), 'Lax')
self.assertEqual(pinning_cookie(), "multidb_pin_writes")
self.assertEqual(pinning_seconds(), 15)
self.assertEqual(pinning_cookie_secure(), False)
self.assertEqual(pinning_cookie_httponly(), False)
self.assertEqual(pinning_cookie_samesite(), "Lax")

@override_settings(MULTIDB_PINNING_COOKIE="override_pin_writes")
@override_settings(MULTIDB_PINNING_SECONDS=60)
@override_settings(MULTIDB_PINNING_COOKIE_SECURE=True)
@override_settings(MULTIDB_PINNING_COOKIE_HTTPONLY=True)
@override_settings(MULTIDB_PINNING_COOKIE_SAMESITE="Strict")
def test_overrides(self):
eq_(pinning_cookie(), "override_pin_writes")
eq_(pinning_seconds(), 60)
eq_(pinning_cookie_secure(), True)
eq_(pinning_cookie_httponly(), True)
eq_(pinning_cookie_samesite(), "Strict")
self.assertEqual(pinning_cookie(), "override_pin_writes")
self.assertEqual(pinning_seconds(), 60)
self.assertEqual(pinning_cookie_secure(), True)
self.assertEqual(pinning_cookie_httponly(), True)
self.assertEqual(pinning_cookie_samesite(), "Strict")


class PinningTests(UnpinningTestCase):
Expand All @@ -80,40 +88,40 @@ class PinningTests(UnpinningTestCase):

def test_pinning_encapsulation(self):
"""Check the pinning getters and setters."""
assert not this_thread_is_pinned(), \
"Thread started out pinned or this_thread_is_pinned() is broken."
assert (
not this_thread_is_pinned()
), "Thread started out pinned or this_thread_is_pinned() is broken."

pin_this_thread()
assert this_thread_is_pinned(), \
"pin_this_thread() didn't pin the thread."
assert this_thread_is_pinned(), "pin_this_thread() didn't pin the thread."

unpin_this_thread()
assert not this_thread_is_pinned(), \
"Thread remained pinned after unpin_this_thread()."
assert (
not this_thread_is_pinned()
), "Thread remained pinned after unpin_this_thread()."

def test_pinned_reads(self):
"""Test PinningReplicaRouter.db_for_read() when pinned and when
not."""
router = PinningReplicaRouter()

eq_(router.db_for_read(None), get_replica())
self.assertEqual(router.db_for_read(None), get_replica())

pin_this_thread()
eq_(router.db_for_read(None), DEFAULT_DB_ALIAS)
self.assertEqual(router.db_for_read(None), DEFAULT_DB_ALIAS)

def test_db_write_decorator(self):

def read_view(req):
eq_(router.db_for_read(None), get_replica())
self.assertEqual(router.db_for_read(None), get_replica())
return HttpResponse()

@db_write
def write_view(req):
eq_(router.db_for_read(None), DEFAULT_DB_ALIAS)
self.assertEqual(router.db_for_read(None), DEFAULT_DB_ALIAS)
return HttpResponse()

router = PinningReplicaRouter()
eq_(router.db_for_read(None), get_replica())
self.assertEqual(router.db_for_read(None), get_replica())
write_view(HttpRequest())
read_view(HttpRequest())

Expand All @@ -134,43 +142,46 @@ def setUp(self):

def test_pin_on_cookie(self):
"""Thread should pin when the cookie is set."""
self.request.COOKIES[pinning_cookie()] = 'y'
self.request.COOKIES[pinning_cookie()] = "y"
self.middleware.process_request(self.request)
assert this_thread_is_pinned()

def test_unpin_on_no_cookie(self):
"""Thread should unpin when cookie is absent and method is GET."""
pin_this_thread()
self.request.method = 'GET'
self.request.method = "GET"
self.middleware.process_request(self.request)
assert not this_thread_is_pinned()

def test_pin_on_post(self):
"""Thread should pin when method is POST."""
self.request.method = 'POST'
self.request.method = "POST"
self.middleware.process_request(self.request)
assert this_thread_is_pinned()

def test_process_response(self):
"""Make sure the cookie gets set on POSTs but not GETs."""

self.request.method = 'GET'
response = self.middleware.process_response(
self.request, HttpResponse())
self.request.method = "GET"
response = self.middleware.process_response(self.request, HttpResponse())
assert pinning_cookie() not in response.cookies

self.request.method = 'POST'
response = self.middleware.process_response(
self.request, HttpResponse())
self.request.method = "POST"
response = self.middleware.process_response(self.request, HttpResponse())
assert pinning_cookie() in response.cookies
eq_(response.cookies[pinning_cookie()]['max-age'],
pinning_seconds())
eq_(response.cookies[pinning_cookie()]['samesite'],
pinning_cookie_samesite())
eq_(response.cookies[pinning_cookie()]['httponly'],
pinning_cookie_httponly() or '')
eq_(response.cookies[pinning_cookie()]['secure'],
pinning_cookie_secure() or '')
self.assertEqual(
response.cookies[pinning_cookie()]["max-age"], pinning_seconds()
)
self.assertEqual(
response.cookies[pinning_cookie()]["samesite"], pinning_cookie_samesite()
)
self.assertEqual(
response.cookies[pinning_cookie()]["httponly"],
pinning_cookie_httponly() or "",
)
self.assertEqual(
response.cookies[pinning_cookie()]["secure"], pinning_cookie_secure() or ""
)

def test_attribute(self):
"""The cookie should get set if the _db_write attribute is True."""
Expand All @@ -182,16 +193,18 @@ def test_attribute(self):
def test_db_write_decorator(self):
"""The @db_write decorator should make any view set the cookie."""
req = self.request
req.method = 'GET'
req.method = "GET"

def view(req):
return HttpResponse()

response = self.middleware.process_response(req, view(req))
assert pinning_cookie() not in response.cookies

@db_write
def write_view(req):
return HttpResponse()

response = self.middleware.process_response(req, write_view(req))
assert pinning_cookie() in response.cookies

Expand All @@ -201,6 +214,7 @@ def test_decorator(self):
@use_primary_db
def check():
assert this_thread_is_pinned()

unpin_this_thread()
assert not this_thread_is_pinned()
check()
Expand All @@ -210,6 +224,7 @@ def test_decorator_resets(self):
@use_primary_db
def check():
assert this_thread_is_pinned()

pin_this_thread()
assert this_thread_is_pinned()
check()
Expand Down Expand Up @@ -289,34 +304,33 @@ def thread2_worker():
class DeprecationTestCase(TestCase):
def test_masterslaverouter(self):
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
warnings.simplefilter("always")
router = multidb.MasterSlaveRouter()
assert isinstance(router, ReplicaRouter)
assert len(w) == 1
assert issubclass(w[-1].category, DeprecationWarning)

def test_pinningmasterslaverouter(self):
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
warnings.simplefilter("always")
router = multidb.PinningMasterSlaveRouter()
assert isinstance(router, PinningReplicaRouter)
assert len(w) == 1
assert issubclass(w[-1].category, DeprecationWarning)

@mock.patch.object(multidb, 'get_replica')
@mock.patch.object(multidb, "get_replica")
def test_get_slave(self, mock_get_replica):
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
warnings.simplefilter("always")
multidb.get_slave()
assert mock_get_replica.called
assert len(w) == 1
assert issubclass(w[-1].category, DeprecationWarning)

def test_use_master(self):
assert isinstance(multidb.pinning.use_master,
use_primary_db.__class__)
assert isinstance(multidb.pinning.use_master, use_primary_db.__class__)
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
warnings.simplefilter("always")
with multidb.pinning.use_master:
pass
assert len(w) == 1
Expand Down
1 change: 0 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
django-nose==1.4.7
flake8==6.0.0
3 changes: 3 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[flake8]
max-line-length = 88
extend-ignore = E203
2 changes: 0 additions & 2 deletions test_settings.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# A Django settings module to support the tests

SECRET_KEY = 'dummy'
# TEST_RUNNER = 'django_nose.runner.NoseTestSuiteRunner'

MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware'
Expand Down

0 comments on commit db09cce

Please sign in to comment.