Ticket #8138: 8138alternate-tzcommit.diff

File 8138alternate-tzcommit.diff, 20.8 KB (added by Karen Tracey, 15 years ago)
  • django/test/client.py

     
    1919from django.utils.encoding import smart_str
    2020from django.utils.http import urlencode
    2121from django.utils.itercompat import is_iterable
     22from django.db import transaction, close_connection
    2223
    2324BOUNDARY = 'BoUnDaRyStRiNg'
    2425MULTIPART_CONTENT = 'multipart/form-data; boundary=%s' % BOUNDARY
     
    6970                response = middleware_method(request, response)
    7071            response = self.apply_response_fixes(request, response)
    7172        finally:
     73            signals.request_finished.disconnect(close_connection)           
    7274            signals.request_finished.send(sender=self.__class__)
     75            signals.request_finished.connect(close_connection)
    7376
    7477        return response
    7578
  • django/test/testcases.py

     
    77from django.core import mail
    88from django.core.management import call_command
    99from django.core.urlresolvers import clear_url_caches
    10 from django.db import transaction
     10from django.db import transaction, connection
    1111from django.http import QueryDict
    1212from django.test import _doctest as doctest
    1313from django.test.client import Client
     
    2626        value = [value]
    2727    return value
    2828
     29real_commit = transaction.commit
     30real_rollback = transaction.rollback
     31real_enter_transaction_management = transaction.enter_transaction_management
     32real_leave_transaction_management = transaction.leave_transaction_management
     33real_savepoint_commit = transaction.savepoint_commit
     34real_savepoint_rollback = transaction.savepoint_rollback
    2935
     36def nop(x=None):
     37    return
     38
     39def disable_transaction_methods():
     40    transaction.commit = nop
     41    transaction.rollback = nop
     42    transaction.savepoint_commit = nop
     43    transaction.savepoint_rollback = nop
     44    transaction.enter_transaction_management = nop
     45    transaction.leave_transaction_management = nop       
     46
     47def restore_transaction_methods():
     48    transaction.commit = real_commit
     49    transaction.rollback = real_rollback
     50    transaction.savepoint_commit = real_savepoint_commit
     51    transaction.savepoint_rollback = real_savepoint_rollback
     52    transaction.enter_transaction_management = real_enter_transaction_management
     53    transaction.leave_transaction_management = real_leave_transaction_management
     54
    3055class OutputChecker(doctest.OutputChecker):
    3156    def check_output(self, want, got, optionflags):
    3257        "The entry method for doctest output checking. Defers to a sequence of child checkers"
     
    168193        # Rollback, in case of database errors. Otherwise they'd have
    169194        # side effects on other tests.
    170195        transaction.rollback_unless_managed()
     196       
     197    def run(self, test, compileflags=None, out=None, clear_globs=True):
     198        """
     199        Wraps the parent run() and encloses it in a transaction.
     200        """
     201        transaction.enter_transaction_management()
     202        transaction.managed(True)
     203        result = doctest.DocTestRunner.run(self, test, compileflags, out, clear_globs)
     204        transaction.rollback()
     205        transaction.leave_transaction_management()
     206        return result
    171207
    172 class TestCase(unittest.TestCase):
     208class TransactionTestCase(unittest.TestCase):
    173209    def _pre_setup(self):
    174210        """Performs any pre-test setup. This includes:
    175211
     
    180216              ROOT_URLCONF with it.
    181217            * Clearing the mail test outbox.
    182218        """
     219        self._fixture_setup()
     220        self._urlconf_setup()
     221        mail.outbox = []
     222
     223    def _fixture_setup(self):
    183224        call_command('flush', verbosity=0, interactive=False)
    184225        if hasattr(self, 'fixtures'):
    185226            # We have to use this slightly awkward syntax due to the fact
    186227            # that we're using *args and **kwargs together.
    187228            call_command('loaddata', *self.fixtures, **{'verbosity': 0})
     229
     230    def _urlconf_setup(self):
    188231        if hasattr(self, 'urls'):
    189232            self._old_root_urlconf = settings.ROOT_URLCONF
    190233            settings.ROOT_URLCONF = self.urls
    191234            clear_url_caches()
    192         mail.outbox = []
    193235
    194236    def __call__(self, result=None):
    195237        """
     
    206248            import sys
    207249            result.addError(self, sys.exc_info())
    208250            return
    209         super(TestCase, self).__call__(result)
     251        super(TransactionTestCase, self).__call__(result)       
    210252        try:
    211253            self._post_teardown()
    212254        except (KeyboardInterrupt, SystemExit):
     
    221263
    222264            * Putting back the original ROOT_URLCONF if it was changed.
    223265        """
     266        self._fixture_teardown()
     267        self._urlconf_teardown()
     268
     269    def _fixture_teardown(self):
     270        pass
     271
     272    def _urlconf_teardown(self):       
    224273        if hasattr(self, '_old_root_urlconf'):
    225274            settings.ROOT_URLCONF = self._old_root_urlconf
    226275            clear_url_caches()
     
    354403        self.failIf(template_name in template_names,
    355404            (u"Template '%s' was used unexpectedly in rendering the"
    356405             u" response") % template_name)
     406
     407class TestCase(TransactionTestCase):
     408    """
     409    Does basically the same as TransactionTestCase, but surrounds every test
     410    with a transaction, monkey-patches the real transaction management routines to
     411    do nothing, and rollsback the test transaction at the end of the test. You have
     412    to use TransactionTestCase, if you need transaction management inside a test.
     413    """
     414
     415    def _fixture_setup(self):
     416        if not settings.DATABASE_SUPPORTS_TRANSACTIONS:
     417            return super(TestCase, self)._fixture_setup()
     418       
     419        transaction.enter_transaction_management()
     420        transaction.managed(True)
     421        disable_transaction_methods()
     422
     423        from django.contrib.sites.models import Site
     424        Site.objects.clear_cache()
     425
     426        if hasattr(self, 'fixtures'):
     427            call_command('loaddata', *self.fixtures, **{
     428                                                        'verbosity': 0,
     429                                                        'commit': False
     430                                                        })
     431
     432    def _fixture_teardown(self):
     433        if not settings.DATABASE_SUPPORTS_TRANSACTIONS:
     434            return super(TestCase, self)._fixture_teardown()
     435               
     436        restore_transaction_methods()
     437        transaction.rollback()
     438        transaction.leave_transaction_management()
     439 No newline at end of file
  • django/test/__init__.py

     
    33"""
    44
    55from django.test.client import Client
    6 from django.test.testcases import TestCase
     6from django.test.testcases import TestCase, TransactionTestCase
  • django/db/backends/postgresql/base.py

     
    116116        cursor = self.connection.cursor()
    117117        if set_tz:
    118118            cursor.execute("SET TIME ZONE %s", [settings.TIME_ZONE])
     119            self.connection.commit()
    119120            if not hasattr(self, '_version'):
    120121                self.__class__._version = get_version(cursor)
    121122            if self._version < (8, 0):
  • django/db/backends/postgresql_psycopg2/base.py

     
    8888        cursor.tzinfo_factory = None
    8989        if set_tz:
    9090            cursor.execute("SET TIME ZONE %s", [settings.TIME_ZONE])
     91            self.connection.commit()
    9192            if not hasattr(self, '_version'):
    9293                self.__class__._version = get_version(cursor)
    9394            if self._version < (8, 0):
  • django/db/backends/creation.py

     
    311311
    312312        self.connection.close()
    313313        settings.DATABASE_NAME = test_database_name
    314 
     314        settings.DATABASE_SUPPORTS_TRANSACTIONS = self._rollback_works()
     315       
    315316        call_command('syncdb', verbosity=verbosity, interactive=False)
    316317
    317318        if settings.CACHE_BACKEND.startswith('db://'):
     
    362363                sys.exit(1)
    363364
    364365        return test_database_name
    365 
     366   
     367    def _rollback_works(self):
     368        cursor = self.connection.cursor()
     369        cursor.execute('CREATE TABLE ROLLBACK_TEST (X INT)')
     370        self.connection._commit()
     371        cursor.execute('INSERT INTO ROLLBACK_TEST (X) VALUES (8)')
     372        self.connection._rollback()
     373        cursor.execute('SELECT COUNT(X) FROM ROLLBACK_TEST')
     374        count, = cursor.fetchone()
     375        cursor.execute('DROP TABLE ROLLBACK_TEST')
     376        self.connection._commit()
     377        return count == 0
     378       
    366379    def destroy_test_db(self, old_database_name, verbosity=1):
    367380        """
    368381        Destroy a test database, prompting the user for confirmation if the
  • tests/regressiontests/generic_inline_admin/tests.py

     
    2121        # relies on content type IDs, which will vary depending on what
    2222        # other tests have been run), thus we do it here.
    2323        e = Episode.objects.create(name='This Week in Django')
     24        self.episode_pk = e.pk
    2425        m = Media(content_object=e, url='http://example.com/podcast.mp3')
    2526        m.save()
     27        self.media_pk = m.pk
    2628   
    2729    def tearDown(self):
    2830        self.client.logout()
     
    3941        """
    4042        A smoke test to ensure GET on the change_view works.
    4143        """
    42         response = self.client.get('/generic_inline_admin/admin/generic_inline_admin/episode/1/')
     44        response = self.client.get('/generic_inline_admin/admin/generic_inline_admin/episode/%d/' % self.episode_pk)
    4345        self.failUnlessEqual(response.status_code, 200)
    4446   
    4547    def testBasicAddPost(self):
     
    6466            # inline data
    6567            "generic_inline_admin-media-content_type-object_id-TOTAL_FORMS": u"2",
    6668            "generic_inline_admin-media-content_type-object_id-INITIAL_FORMS": u"1",
    67             "generic_inline_admin-media-content_type-object_id-0-id": u"1",
     69            "generic_inline_admin-media-content_type-object_id-0-id": u"%d" % self.media_pk,
    6870            "generic_inline_admin-media-content_type-object_id-0-url": u"http://example.com/podcast.mp3",
    6971            "generic_inline_admin-media-content_type-object_id-1-id": u"",
    7072            "generic_inline_admin-media-content_type-object_id-1-url": u"",
    7173        }
    72         response = self.client.post('/generic_inline_admin/admin/generic_inline_admin/episode/1/', post_data)
     74        url = '/generic_inline_admin/admin/generic_inline_admin/episode/%d/' % self.episode_pk
     75        response = self.client.post(url, post_data)
    7376        self.failUnlessEqual(response.status_code, 302) # redirect somewhere
  • tests/regressiontests/comment_tests/tests/moderation_view_tests.py

     
    88
    99    def testFlagGet(self):
    1010        """GET the flag view: render a confirmation page."""
    11         self.createSomeComments()
     11        comments = self.createSomeComments()
     12        pk = comments[0].pk
    1213        self.client.login(username="normaluser", password="normaluser")
    13         response = self.client.get("/flag/1/")
     14        response = self.client.get("/flag/%d/" % pk)
    1415        self.assertTemplateUsed(response, "comments/flag.html")
    1516
    1617    def testFlagPost(self):
    1718        """POST the flag view: actually flag the view (nice for XHR)"""
    18         self.createSomeComments()
     19        comments = self.createSomeComments()
     20        pk = comments[0].pk
    1921        self.client.login(username="normaluser", password="normaluser")
    20         response = self.client.post("/flag/1/")
    21         self.assertEqual(response["Location"], "http://testserver/flagged/?c=1")
    22         c = Comment.objects.get(pk=1)
     22        response = self.client.post("/flag/%d/" % pk)
     23        self.assertEqual(response["Location"], "http://testserver/flagged/?c=%d" % pk)
     24        c = Comment.objects.get(pk=pk)
    2325        self.assertEqual(c.flags.filter(flag=CommentFlag.SUGGEST_REMOVAL).count(), 1)
    2426        return c
    2527
    2628    def testFlagPostTwice(self):
    2729        """Users don't get to flag comments more than once."""
    2830        c = self.testFlagPost()
    29         self.client.post("/flag/1/")
    30         self.client.post("/flag/1/")
     31        self.client.post("/flag/%d/" % c.pk)
     32        self.client.post("/flag/%d/" % c.pk)
    3133        self.assertEqual(c.flags.filter(flag=CommentFlag.SUGGEST_REMOVAL).count(), 1)
    3234
    3335    def testFlagAnon(self):
    3436        """GET/POST the flag view while not logged in: redirect to log in."""
    35         self.createSomeComments()
    36         response = self.client.get("/flag/1/")
    37         self.assertEqual(response["Location"], "http://testserver/accounts/login/?next=/flag/1/")
    38         response = self.client.post("/flag/1/")
    39         self.assertEqual(response["Location"], "http://testserver/accounts/login/?next=/flag/1/")
     37        comments = self.createSomeComments()
     38        pk = comments[0].pk       
     39        response = self.client.get("/flag/%d/" % pk)
     40        self.assertEqual(response["Location"], "http://testserver/accounts/login/?next=/flag/%d/" % pk)
     41        response = self.client.post("/flag/%d/" % pk)
     42        self.assertEqual(response["Location"], "http://testserver/accounts/login/?next=/flag/%d/" % pk)
    4043
    4144    def testFlaggedView(self):
    42         self.createSomeComments()
    43         response = self.client.get("/flagged/", data={"c":1})
     45        comments = self.createSomeComments()
     46        pk = comments[0].pk       
     47        response = self.client.get("/flagged/", data={"c":pk})
    4448        self.assertTemplateUsed(response, "comments/flagged.html")
    4549
    4650    def testFlagSignals(self):
     
    7074
    7175    def testDeletePermissions(self):
    7276        """The delete view should only be accessible to 'moderators'"""
    73         self.createSomeComments()
     77        comments = self.createSomeComments()
     78        pk = comments[0].pk       
    7479        self.client.login(username="normaluser", password="normaluser")
    75         response = self.client.get("/delete/1/")
    76         self.assertEqual(response["Location"], "http://testserver/accounts/login/?next=/delete/1/")
     80        response = self.client.get("/delete/%d/" % pk)
     81        self.assertEqual(response["Location"], "http://testserver/accounts/login/?next=/delete/%d/" % pk)
    7782
    7883        makeModerator("normaluser")
    79         response = self.client.get("/delete/1/")
     84        response = self.client.get("/delete/%d/" % pk)
    8085        self.assertEqual(response.status_code, 200)
    8186
    8287    def testDeletePost(self):
    8388        """POSTing the delete view should mark the comment as removed"""
    84         self.createSomeComments()
     89        comments = self.createSomeComments()
     90        pk = comments[0].pk
    8591        makeModerator("normaluser")
    8692        self.client.login(username="normaluser", password="normaluser")
    87         response = self.client.post("/delete/1/")
    88         self.assertEqual(response["Location"], "http://testserver/deleted/?c=1")
    89         c = Comment.objects.get(pk=1)
     93        response = self.client.post("/delete/%d/" % pk)
     94        self.assertEqual(response["Location"], "http://testserver/deleted/?c=%d" % pk)
     95        c = Comment.objects.get(pk=pk)
    9096        self.failUnless(c.is_removed)
    9197        self.assertEqual(c.flags.filter(flag=CommentFlag.MODERATOR_DELETION, user__username="normaluser").count(), 1)
    9298
     
    103109        self.assertEqual(received_signals, [signals.comment_was_flagged])
    104110
    105111    def testDeletedView(self):
    106         self.createSomeComments()
    107         response = self.client.get("/deleted/", data={"c":1})
     112        comments = self.createSomeComments()
     113        pk = comments[0].pk       
     114        response = self.client.get("/deleted/", data={"c":pk})
    108115        self.assertTemplateUsed(response, "comments/deleted.html")
    109116
    110117class ApproveViewTests(CommentTestCase):
    111118
    112119    def testApprovePermissions(self):
    113120        """The delete view should only be accessible to 'moderators'"""
    114         self.createSomeComments()
     121        comments = self.createSomeComments()
     122        pk = comments[0].pk       
    115123        self.client.login(username="normaluser", password="normaluser")
    116         response = self.client.get("/approve/1/")
    117         self.assertEqual(response["Location"], "http://testserver/accounts/login/?next=/approve/1/")
     124        response = self.client.get("/approve/%d/" % pk)
     125        self.assertEqual(response["Location"], "http://testserver/accounts/login/?next=/approve/%d/" % pk)
    118126
    119127        makeModerator("normaluser")
    120         response = self.client.get("/approve/1/")
     128        response = self.client.get("/approve/%d/" % pk)
    121129        self.assertEqual(response.status_code, 200)
    122130
    123131    def testApprovePost(self):
     
    127135
    128136        makeModerator("normaluser")
    129137        self.client.login(username="normaluser", password="normaluser")
    130         response = self.client.post("/approve/1/")
    131         self.assertEqual(response["Location"], "http://testserver/approved/?c=1")
    132         c = Comment.objects.get(pk=1)
     138        response = self.client.post("/approve/%d/" % c1.pk)
     139        self.assertEqual(response["Location"], "http://testserver/approved/?c=%d" % c1.pk)
     140        c = Comment.objects.get(pk=c1.pk)
    133141        self.failUnless(c.is_public)
    134142        self.assertEqual(c.flags.filter(flag=CommentFlag.MODERATOR_APPROVAL, user__username="normaluser").count(), 1)
    135143
     
    146154        self.assertEqual(received_signals, [signals.comment_was_flagged])
    147155
    148156    def testApprovedView(self):
    149         self.createSomeComments()
    150         response = self.client.get("/approved/", data={"c":1})
     157        comments = self.createSomeComments()
     158        pk = comments[0].pk       
     159        response = self.client.get("/approved/", data={"c":pk})
    151160        self.assertTemplateUsed(response, "comments/approved.html")
    152161
    153162
  • tests/regressiontests/comment_tests/tests/comment_view_tests.py

     
     1import re
    12from django.conf import settings
    23from django.contrib.auth.models import User
    34from django.contrib.comments import signals
     
    56from regressiontests.comment_tests.models import Article
    67from regressiontests.comment_tests.tests import CommentTestCase
    78
     9post_redirect_re = re.compile(r'^http://testserver/posted/\?c=(?P<pk>\d+$)')
     10
    811class CommentViewTests(CommentTestCase):
    912
    1013    def testPostCommentHTTPMethods(self):
     
    181184        a = Article.objects.get(pk=1)
    182185        data = self.getValidData(a)
    183186        response = self.client.post("/post/", data)
    184         self.assertEqual(response["Location"], "http://testserver/posted/?c=1")
    185 
     187        location = response["Location"]
     188        match = post_redirect_re.match(location)
     189        self.failUnless(match != None, "Unexpected redirect location: %s" % location)
     190       
    186191        data["next"] = "/somewhere/else/"
    187192        data["comment"] = "This is another comment"
    188193        response = self.client.post("/post/", data)
    189         self.assertEqual(response["Location"], "http://testserver/somewhere/else/?c=2")
     194        location = response["Location"]       
     195        match = re.search(r"^http://testserver/somewhere/else/\?c=\d+$", location)
     196        self.failUnless(match != None, "Unexpected redirect location: %s" % location)
    190197
    191198    def testCommentDoneView(self):
    192199        a = Article.objects.get(pk=1)
    193200        data = self.getValidData(a)
    194201        response = self.client.post("/post/", data)
    195         response = self.client.get("/posted/", {'c':1})
     202        location = response["Location"]       
     203        match = post_redirect_re.match(location)
     204        self.failUnless(match != None, "Unexpected redirect location: %s" % location)
     205        pk = int(match.group('pk'))
     206        response = self.client.get(location)
    196207        self.assertTemplateUsed(response, "comments/posted.html")
    197         self.assertEqual(response.context[0]["comment"], Comment.objects.get(pk=1))
     208        self.assertEqual(response.context[0]["comment"], Comment.objects.get(pk=pk))
    198209
Back to Top