summaryrefslogtreecommitdiff
path: root/odoo/addons/base/tests/test_cache.py
diff options
context:
space:
mode:
authorChristophe Simonis <chs@odoo.com>2019-01-29 13:17:12 +0100
committerChristophe Simonis <chs@odoo.com>2019-01-29 13:17:12 +0100
commitcd5c8a02f9560b2a8b5c39182adee7ade1bf595c (patch)
treec654b3d46020aa30fcc7c2724d200a93a807859b /odoo/addons/base/tests/test_cache.py
parent6c6ef6588fc374e86acdeeacba2842690b6f1a53 (diff)
parent36d96e015032d42449fe149c050df75050276fdc (diff)
[MERGE] forward port branch 11.0 up to 36d96e01503
Diffstat (limited to 'odoo/addons/base/tests/test_cache.py')
-rw-r--r--odoo/addons/base/tests/test_cache.py145
1 files changed, 145 insertions, 0 deletions
diff --git a/odoo/addons/base/tests/test_cache.py b/odoo/addons/base/tests/test_cache.py
new file mode 100644
index 00000000000..3c8fbd9f603
--- /dev/null
+++ b/odoo/addons/base/tests/test_cache.py
@@ -0,0 +1,145 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+import os
+import psutil
+
+from odoo.tests.common import TransactionCase
+
+
+class TestRecordCache(TransactionCase):
+
+ def test_cache(self):
+ """ Check the record cache object. """
+ Model = self.env['res.partner']
+ name = type(Model).name
+ ref = type(Model).ref
+
+ cache = self.env.cache
+
+ def check1(record, field, value):
+ # value is None means no value in cache
+ self.assertEqual(cache.contains(record, field), value is not None)
+ self.assertEqual(cache.contains_value(record, field), value is not None)
+ self.assertEqual(cache.get_value(record, field), value)
+ try:
+ self.assertEqual(cache.get(record, field), value)
+ self.assertIsNotNone(value)
+ except KeyError:
+ self.assertIsNone(value)
+ self.assertIsNone(cache.get_special(record, field))
+ self.assertEqual(field in cache.get_fields(record), value is not None)
+ self.assertEqual(record in cache.get_records(record, field), value is not None)
+
+ def check(record, name_val, ref_val):
+ """ check the values of fields 'name' and 'ref' on record. """
+ check1(record, name, name_val)
+ check1(record, ref, ref_val)
+
+ foo1, bar1 = Model.browse([1, 2])
+ foo2, bar2 = Model.sudo(self.env.ref('base.user_demo')).browse([1, 2])
+ self.assertNotEqual(foo1.env.uid, foo2.env.uid)
+
+ # cache is empty
+ cache.invalidate()
+ check(foo1, None, None)
+ check(foo2, None, None)
+ check(bar1, None, None)
+ check(bar2, None, None)
+ self.assertCountEqual(cache.get_missing_ids(foo1 + bar1, name), [1, 2])
+ self.assertCountEqual(cache.get_missing_ids(foo2 + bar2, name), [1, 2])
+
+ # set values in one environment only
+ for rec in [foo1, bar1]:
+ cache.set(rec, name, 'NAME1')
+ cache.set(rec, ref, 'REF1')
+ check(foo1, 'NAME1', 'REF1')
+ check(foo2, None, None)
+ check(bar1, 'NAME1', 'REF1')
+ check(bar2, None, None)
+ self.assertCountEqual(cache.get_missing_ids(foo1 + bar1, name), [])
+ self.assertCountEqual(cache.get_missing_ids(foo2 + bar2, name), [1, 2])
+
+ # set values in both environments
+ for rec in [foo2, bar2]:
+ cache.set(rec, name, 'NAME2')
+ cache.set(rec, ref, 'REF2')
+ check(foo1, 'NAME1', 'REF1')
+ check(foo2, 'NAME2', 'REF2')
+ check(bar1, 'NAME1', 'REF1')
+ check(bar2, 'NAME2', 'REF2')
+ self.assertCountEqual(cache.get_missing_ids(foo1 + bar1, name), [])
+ self.assertCountEqual(cache.get_missing_ids(foo2 + bar2, name), [])
+
+ # remove value in one environment
+ cache.remove(foo1, name)
+ check(foo1, None, 'REF1')
+ check(foo2, 'NAME2', 'REF2')
+ check(bar1, 'NAME1', 'REF1')
+ check(bar2, 'NAME2', 'REF2')
+ self.assertCountEqual(cache.get_missing_ids(foo1 + bar1, name), [1])
+ self.assertCountEqual(cache.get_missing_ids(foo2 + bar2, name), [])
+
+ # partial invalidation
+ cache.invalidate([(name, None), (ref, foo1.ids)])
+ check(foo1, None, None)
+ check(foo2, None, None)
+ check(bar1, None, 'REF1')
+ check(bar2, None, 'REF2')
+
+ # total invalidation
+ cache.invalidate()
+ check(foo1, None, None)
+ check(foo2, None, None)
+ check(bar1, None, None)
+ check(bar2, None, None)
+
+ # set a special value
+ cache.set_special(foo1, name, lambda: '42')
+ self.assertTrue(cache.contains(foo1, name))
+ self.assertFalse(cache.contains_value(foo1, name))
+ self.assertEqual(cache.get(foo1, name), '42')
+ self.assertIsNone(cache.get_value(foo1, name))
+ self.assertIsNotNone(cache.get_special(foo1, name))
+
+ # copy cache
+ for rec in [foo1, bar1]:
+ cache.set(rec, name, 'NAME1')
+ cache.set(rec, ref, 'REF1')
+ check(foo1, 'NAME1', 'REF1')
+ check(foo2, None, None)
+ check(bar1, 'NAME1', 'REF1')
+ check(bar2, None, None)
+
+ cache.copy(foo1 + bar1, foo2.env)
+ check(foo1, 'NAME1', 'REF1')
+ check(foo2, 'NAME1', 'REF1')
+ check(bar1, 'NAME1', 'REF1')
+ check(bar2, 'NAME1', 'REF1')
+
+ def test_memory(self):
+ """ Check memory consumption of the cache. """
+ NB_RECORDS = 100000
+ MAX_MEMORY = 100
+
+ cache = self.env.cache
+ model = self.env['res.partner']
+ records = [model.new() for index in range(NB_RECORDS)]
+
+ process = psutil.Process(os.getpid())
+ rss0 = process.memory_info().rss
+
+ char_names = [
+ 'name', 'display_name', 'email', 'website', 'phone', 'mobile',
+ 'street', 'street2', 'city', 'zip', 'vat', 'ref',
+ ]
+ for name in char_names:
+ field = model._fields[name]
+ for record in records:
+ cache.set(record, field, 'test')
+
+ mem_usage = process.memory_info().rss - rss0
+ self.assertLess(
+ mem_usage, MAX_MEMORY * 1024 * 1024,
+ "Caching %s records must take less than %sMB of memory" % (NB_RECORDS, MAX_MEMORY),
+ )