[IMP] base: Clear precommits on test cleanup

Precommit hooks would stock data until a call to ``cr.flush`` was made.
Notably, this happens when the ``assertRaises`` method is called.
Functions were applied on records already cleared from the cache.

This change adds a cleanup call for `TransactionCase` as it keeps
the same cursor for all tests. Cursor precommits can now
be safely executed inside tests.

Task-2834304

Forward port of #117555

closes odoo/odoo#118290

X-original-commit: ff5d0c75fcea5842c5236b1b3f7480ef5a3dc415
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
Signed-off-by: Thiry Renaud (reth) <reth@odoo.com>
This commit is contained in:
Renaud Thiry
2023-04-13 04:08:25 +02:00
parent 1c1604466f
commit dddb2f5355
3 changed files with 37 additions and 2 deletions
+1 -1
View File
@@ -184,7 +184,7 @@ class TestRatingPerformance(TestRatingCommon):
@users('employee') @users('employee')
@warmup @warmup
def test_rating_last_value_perfs_with_rating_mixin(self): def test_rating_last_value_perfs_with_rating_mixin(self):
with self.assertQueryCount(employee=1312): # tmf 1312 / com 1312 with self.assertQueryCount(employee=1319): # tmf 1319 / com 1319
self.create_ratings('mail.test.rating') self.create_ratings('mail.test.rating')
with self.assertQueryCount(employee=2004): # tmf 2004 with self.assertQueryCount(employee=2004): # tmf 2004
+24
View File
@@ -255,3 +255,27 @@ class TestCursorHooks(common.TransactionCase):
self.prepare_hooks(cr) self.prepare_hooks(cr)
cr.close() cr.close()
self.assertEqual(self.log, ['preR', 'postR']) self.assertEqual(self.log, ['preR', 'postR'])
class TestCursorHooksTransactionCaseCleanup(common.TransactionCase):
"""Check savepoint cases handle commit hooks properly."""
def test_isolation_first(self):
def mutate_second_test_ref():
for name in ['precommit', 'postcommit', 'prerollback', 'postrollback']:
del self.env.cr.precommit.data.get(f'test_cursor_hooks_savepoint_case_cleanup_test_second_{name}', [''])[0]
self.env.cr.precommit.add(mutate_second_test_ref)
def test_isolation_second(self):
references = [['not_empty']] * 4
cr = self.env.cr
commit_callbacks = [cr.precommit, cr.postcommit, cr.prerollback, cr.postrollback]
callback_names = ['precommit', 'postcommit', 'prerollback', 'postrollback']
for callback_name, callbacks, reference in zip(callback_names, commit_callbacks, references):
callbacks.data.setdefault(f"test_cursor_hooks_savepoint_case_cleanup_test_second_{callback_name}", reference)
for callback in commit_callbacks:
callback.run()
for callback_name, reference in zip(callback_names, references):
self.assertTrue(bool(reference), f"{callback_name} failed to clean up between transaction tests")
self.assertTrue(reference[0] == 'not_empty', f"{callback_name} failed to clean up between transaction tests")
+12 -1
View File
@@ -28,7 +28,7 @@ import time
import unittest import unittest
from . import case from . import case
import warnings import warnings
from collections import defaultdict from collections import defaultdict, deque
from concurrent.futures import Future, CancelledError, wait from concurrent.futures import Future, CancelledError, wait
try: try:
from concurrent.futures import InvalidStateError from concurrent.futures import InvalidStateError
@@ -735,6 +735,17 @@ class TransactionCase(BaseCase):
self.addCleanup(self.registry.clear_caches) self.addCleanup(self.registry.clear_caches)
# This prevents precommit functions and data from piling up
# until cr.flush is called in 'assertRaises' clauses
# (these are not cleared in self.env.clear or envs.clear)
cr = self.env.cr
def _reset(cb, funcs, data):
cb._funcs = funcs
cb.data = data
for callback in [cr.precommit, cr.postcommit, cr.prerollback, cr.postrollback]:
self.addCleanup(_reset, callback, deque(callback._funcs), dict(callback.data))
# flush everything in setUpClass before introducing a savepoint # flush everything in setUpClass before introducing a savepoint
self.env.flush_all() self.env.flush_all()