oca-technical/odoo-bringout-oca-queue-test_queue_job/test_queue_job/tests/test_job.py
2025-08-29 15:43:03 +02:00

796 lines
32 KiB
Python

# Copyright 2016 Camptocamp SA
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html)
import hashlib
from datetime import datetime, timedelta
from unittest import mock
import odoo.tests.common as common
from odoo.addons.queue_job import identity_exact
from odoo.addons.queue_job.delay import DelayableGraph
from odoo.addons.queue_job.exception import (
FailedJobError,
NoSuchJobError,
RetryableJobError,
)
from odoo.addons.queue_job.job import (
CANCELLED,
DONE,
ENQUEUED,
FAILED,
PENDING,
RETRY_INTERVAL,
STARTED,
WAIT_DEPENDENCIES,
Job,
)
from .common import JobCommonCase
class TestJobsOnTestingMethod(JobCommonCase):
"""Test Job"""
def test_new_job(self):
"""
Create a job
"""
test_job = Job(self.method)
self.assertEqual(test_job.func.__func__, self.method.__func__)
def test_eta(self):
"""When an `eta` is datetime, it uses it"""
now = datetime.now()
method = self.env["res.users"].mapped
job_a = Job(method, eta=now)
self.assertEqual(job_a.eta, now)
def test_eta_integer(self):
"""When an `eta` is an integer, it adds n seconds up to now"""
datetime_path = "odoo.addons.queue_job.job.datetime"
with mock.patch(datetime_path, autospec=True) as mock_datetime:
mock_datetime.now.return_value = datetime(2015, 3, 15, 16, 41, 0)
job_a = Job(self.method, eta=60)
self.assertEqual(job_a.eta, datetime(2015, 3, 15, 16, 42, 0))
def test_eta_timedelta(self):
"""When an `eta` is a timedelta, it adds it up to now"""
datetime_path = "odoo.addons.queue_job.job.datetime"
with mock.patch(datetime_path, autospec=True) as mock_datetime:
mock_datetime.now.return_value = datetime(2015, 3, 15, 16, 41, 0)
delta = timedelta(hours=3)
job_a = Job(self.method, eta=delta)
self.assertEqual(job_a.eta, datetime(2015, 3, 15, 19, 41, 0))
def test_perform_args(self):
test_job = Job(self.method, args=("o", "k"), kwargs={"c": "!"})
result = test_job.perform()
self.assertEqual(result, (("o", "k"), {"c": "!"}))
def test_retryable_error(self):
test_job = Job(self.method, kwargs={"raise_retry": True}, max_retries=3)
self.assertEqual(test_job.retry, 0)
with self.assertRaises(RetryableJobError):
test_job.perform()
self.assertEqual(test_job.retry, 1)
with self.assertRaises(RetryableJobError):
test_job.perform()
self.assertEqual(test_job.retry, 2)
with self.assertRaises(FailedJobError):
test_job.perform()
self.assertEqual(test_job.retry, 3)
def test_infinite_retryable_error(self):
test_job = Job(self.method, kwargs={"raise_retry": True}, max_retries=0)
self.assertEqual(test_job.retry, 0)
with self.assertRaises(RetryableJobError):
test_job.perform()
self.assertEqual(test_job.retry, 1)
def test_on_instance_method(self):
class A:
def method(self):
pass
with self.assertRaises(TypeError):
Job(A.method)
def test_on_model_method(self):
job_ = Job(self.env["test.queue.job"].testing_method)
self.assertEqual(job_.model_name, "test.queue.job")
self.assertEqual(job_.method_name, "testing_method")
def test_invalid_function(self):
with self.assertRaises(TypeError):
Job(1)
def test_set_pending(self):
job_a = Job(self.method)
job_a.set_pending(result="test")
self.assertEqual(job_a.state, PENDING)
self.assertFalse(job_a.date_enqueued)
self.assertFalse(job_a.date_started)
self.assertEqual(job_a.retry, 0)
self.assertEqual(job_a.result, "test")
def test_set_enqueued(self):
job_a = Job(self.method)
datetime_path = "odoo.addons.queue_job.job.datetime"
with mock.patch(datetime_path, autospec=True) as mock_datetime:
mock_datetime.now.return_value = datetime(2015, 3, 15, 16, 41, 0)
job_a.set_enqueued()
self.assertEqual(job_a.state, ENQUEUED)
self.assertEqual(job_a.date_enqueued, datetime(2015, 3, 15, 16, 41, 0))
self.assertFalse(job_a.date_started)
def test_set_started(self):
job_a = Job(self.method)
datetime_path = "odoo.addons.queue_job.job.datetime"
with mock.patch(datetime_path, autospec=True) as mock_datetime:
mock_datetime.now.return_value = datetime(2015, 3, 15, 16, 41, 0)
job_a.set_started()
self.assertEqual(job_a.state, STARTED)
self.assertEqual(job_a.date_started, datetime(2015, 3, 15, 16, 41, 0))
def test_worker_pid(self):
"""When a job is started, it gets the PID of the worker that starts it"""
method = self.env["res.users"].mapped
job_a = Job(method)
self.assertFalse(job_a.worker_pid)
with mock.patch("os.getpid", autospec=True) as mock_getpid:
mock_getpid.return_value = 99999
job_a.set_started()
self.assertEqual(job_a.worker_pid, 99999)
# reset the pid
job_a.set_pending()
self.assertFalse(job_a.worker_pid)
def test_set_done(self):
job_a = Job(self.method)
job_a.date_started = datetime(2015, 3, 15, 16, 40, 0)
datetime_path = "odoo.addons.queue_job.job.datetime"
with mock.patch(datetime_path, autospec=True) as mock_datetime:
mock_datetime.now.return_value = datetime(2015, 3, 15, 16, 41, 0)
job_a.set_done(result="test")
self.assertEqual(job_a.state, DONE)
self.assertEqual(job_a.result, "test")
self.assertEqual(job_a.date_done, datetime(2015, 3, 15, 16, 41, 0))
self.assertEqual(job_a.exec_time, 60.0)
self.assertFalse(job_a.exc_info)
def test_set_failed(self):
job_a = Job(self.method)
job_a.set_failed(
exc_info="failed test",
exc_name="FailedTest",
exc_message="Sadly this job failed",
)
self.assertEqual(job_a.state, FAILED)
self.assertEqual(job_a.exc_info, "failed test")
self.assertEqual(job_a.exc_name, "FailedTest")
self.assertEqual(job_a.exc_message, "Sadly this job failed")
def test_postpone(self):
job_a = Job(self.method)
datetime_path = "odoo.addons.queue_job.job.datetime"
with mock.patch(datetime_path, autospec=True) as mock_datetime:
mock_datetime.now.return_value = datetime(2015, 3, 15, 16, 41, 0)
job_a.postpone(result="test", seconds=60)
self.assertEqual(job_a.eta, datetime(2015, 3, 15, 16, 42, 0))
self.assertEqual(job_a.result, "test")
self.assertFalse(job_a.exc_info)
def test_company_simple(self):
company = self.env.ref("base.main_company")
eta = datetime.now() + timedelta(hours=5)
test_job = Job(
self.env["test.queue.job"].with_company(company).testing_method,
args=("o", "k"),
kwargs={"return_context": 1},
priority=15,
eta=eta,
description="My description",
)
test_job.worker_pid = 99999 # normally set on "set_start"
test_job.store()
job_read = Job.load(self.env, test_job.uuid)
self.assertEqual(test_job.func.__func__, job_read.func.__func__)
result_ctx = job_read.func(*tuple(test_job.args), **test_job.kwargs)
self.assertEqual(result_ctx.get("allowed_company_ids"), company.ids)
def test_company_complex(self):
company1 = self.env.ref("base.main_company")
company2 = company1.create({"name": "Queue job company"})
companies = company1 | company2
self.env.user.write({"company_ids": [(6, False, companies.ids)]})
# Ensure the main company still the first
self.assertEqual(self.env.user.company_id, company1)
eta = datetime.now() + timedelta(hours=5)
test_job = Job(
self.env["test.queue.job"].with_company(company2).testing_method,
args=("o", "k"),
kwargs={"return_context": 1},
priority=15,
eta=eta,
description="My description",
)
test_job.worker_pid = 99999 # normally set on "set_start"
test_job.store()
job_read = Job.load(self.env, test_job.uuid)
self.assertEqual(test_job.func.__func__, job_read.func.__func__)
result_ctx = job_read.func(*tuple(test_job.args), **test_job.kwargs)
self.assertEqual(result_ctx.get("allowed_company_ids"), company2.ids)
def test_store(self):
test_job = Job(self.method)
test_job.store()
stored = self.queue_job.search([("uuid", "=", test_job.uuid)])
self.assertEqual(len(stored), 1)
def test_store_extra_data(self):
test_job = Job(self.method)
test_job.store()
stored = self.queue_job.search([("uuid", "=", test_job.uuid)])
self.assertEqual(stored.additional_info, "JUST_TESTING")
test_job.set_failed(exc_info="failed test", exc_name="FailedTest")
test_job.store()
stored.invalidate_recordset()
self.assertEqual(stored.additional_info, "JUST_TESTING_BUT_FAILED")
def test_read(self):
eta = datetime.now() + timedelta(hours=5)
test_job = Job(
self.method,
args=("o", "k"),
kwargs={"c": "!"},
priority=15,
eta=eta,
description="My description",
)
test_job.worker_pid = 99999 # normally set on "set_start"
test_job.company_id = self.env.ref("base.main_company").id
test_job.store()
job_read = Job.load(self.env, test_job.uuid)
self.assertEqual(test_job.uuid, job_read.uuid)
self.assertEqual(test_job.model_name, job_read.model_name)
self.assertEqual(test_job.func.__func__, job_read.func.__func__)
self.assertEqual(test_job.args, job_read.args)
self.assertEqual(test_job.kwargs, job_read.kwargs)
self.assertEqual(test_job.method_name, job_read.method_name)
self.assertEqual(test_job.description, job_read.description)
self.assertEqual(test_job.state, job_read.state)
self.assertEqual(test_job.priority, job_read.priority)
self.assertEqual(test_job.exc_info, job_read.exc_info)
self.assertEqual(test_job.result, job_read.result)
self.assertEqual(test_job.user_id, job_read.user_id)
self.assertEqual(test_job.company_id, job_read.company_id)
self.assertEqual(test_job.worker_pid, 99999)
delta = timedelta(seconds=1) # DB does not keep milliseconds
self.assertAlmostEqual(
test_job.date_created, job_read.date_created, delta=delta
)
self.assertAlmostEqual(
test_job.date_started, job_read.date_started, delta=delta
)
self.assertAlmostEqual(
test_job.date_enqueued, job_read.date_enqueued, delta=delta
)
self.assertAlmostEqual(test_job.date_done, job_read.date_done, delta=delta)
self.assertAlmostEqual(test_job.eta, job_read.eta, delta=delta)
test_date = datetime(2015, 3, 15, 21, 7, 0)
job_read.date_enqueued = test_date
job_read.date_started = test_date
job_read.date_done = test_date
job_read.store()
job_read = Job.load(self.env, test_job.uuid)
self.assertAlmostEqual(job_read.date_started, test_date, delta=delta)
self.assertAlmostEqual(job_read.date_enqueued, test_date, delta=delta)
self.assertAlmostEqual(job_read.date_done, test_date, delta=delta)
self.assertAlmostEqual(job_read.exec_time, 0.0)
def test_job_unlinked(self):
test_job = Job(self.method, args=("o", "k"), kwargs={"c": "!"})
test_job.store()
stored = self.queue_job.search([("uuid", "=", test_job.uuid)])
stored.unlink()
with self.assertRaises(NoSuchJobError):
Job.load(self.env, test_job.uuid)
def test_unicode(self):
test_job = Job(
self.method,
args=("öô¿‽", "ñě"),
kwargs={"c": "ßø"},
priority=15,
description="My dé^Wdescription",
)
test_job.store()
job_read = Job.load(self.env, test_job.uuid)
self.assertEqual(test_job.args, job_read.args)
self.assertEqual(job_read.args, ("öô¿‽", "ñě"))
self.assertEqual(test_job.kwargs, job_read.kwargs)
self.assertEqual(job_read.kwargs, {"c": "ßø"})
self.assertEqual(test_job.description, job_read.description)
self.assertEqual(job_read.description, "My dé^Wdescription")
def test_accented_bytestring(self):
test_job = Job(
self.method,
args=("öô¿‽", "ñě"),
kwargs={"c": "ßø"},
priority=15,
description="My dé^Wdescription",
)
test_job.store()
job_read = Job.load(self.env, test_job.uuid)
self.assertEqual(job_read.args, ("öô¿‽", "ñě"))
self.assertEqual(job_read.kwargs, {"c": "ßø"})
self.assertEqual(job_read.description, "My dé^Wdescription")
def test_job_delay(self):
self.cr.execute("delete from queue_job")
job_ = self.env["test.queue.job"].with_delay().testing_method()
stored = self.queue_job.search([])
self.assertEqual(len(stored), 1)
self.assertEqual(stored.uuid, job_.uuid, "Incorrect returned Job UUID")
def test_job_delay_model_method(self):
self.cr.execute("delete from queue_job")
delayable = self.env["test.queue.job"].with_delay()
job_instance = delayable.testing_method("a", k=1)
self.assertTrue(job_instance)
result = job_instance.perform()
self.assertEqual(result, (("a",), {"k": 1}))
def test_job_identity_key_str(self):
id_key = "e294e8444453b09d59bdb6efbfec1323"
test_job_1 = Job(
self.method,
priority=15,
description="Test I am the first one",
identity_key=id_key,
)
test_job_1.store()
job1 = Job.load(self.env, test_job_1.uuid)
self.assertEqual(job1.identity_key, id_key)
def test_job_identity_key_func_exact(self):
hasher = hashlib.sha1()
hasher.update(b"test.queue.job")
hasher.update(b"testing_method")
hasher.update(str(sorted([])).encode("utf-8"))
hasher.update(str((1, "foo")).encode("utf-8"))
hasher.update(str(sorted({"bar": "baz"}.items())).encode("utf-8"))
expected_key = hasher.hexdigest()
test_job_1 = Job(
self.method,
args=[1, "foo"],
kwargs={"bar": "baz"},
identity_key=identity_exact,
)
self.assertEqual(test_job_1.identity_key, expected_key)
test_job_1.store()
job1 = Job.load(self.env, test_job_1.uuid)
self.assertEqual(job1.identity_key, expected_key)
class TestJobs(JobCommonCase):
"""Test jobs on other methods or with different job configuration"""
def test_description(self):
"""If no description is given to the job, it
should be computed from the function
"""
# if a docstring is defined for the function
# it's used as description
job_a = Job(self.env["test.queue.job"].testing_method)
self.assertEqual(job_a.description, "Method used for tests")
# if no docstring, the description is computed
job_b = Job(self.env["test.queue.job"].no_description)
self.assertEqual(job_b.description, "test.queue.job.no_description")
# case when we explicitly specify the description
description = "My description"
job_a = Job(self.env["test.queue.job"].testing_method, description=description)
self.assertEqual(job_a.description, description)
def test_retry_pattern(self):
"""When we specify a retry pattern, the eta must follow it"""
datetime_path = "odoo.addons.queue_job.job.datetime"
method = self.env["test.queue.job"].job_with_retry_pattern
with mock.patch(datetime_path, autospec=True) as mock_datetime:
mock_datetime.now.return_value = datetime(2015, 6, 1, 15, 10, 0)
test_job = Job(method, max_retries=0)
test_job.retry += 1
test_job.postpone(self.env)
self.assertEqual(test_job.retry, 1)
self.assertEqual(test_job.eta, datetime(2015, 6, 1, 15, 11, 0))
test_job.retry += 1
test_job.postpone(self.env)
self.assertEqual(test_job.retry, 2)
self.assertEqual(test_job.eta, datetime(2015, 6, 1, 15, 13, 0))
test_job.retry += 1
test_job.postpone(self.env)
self.assertEqual(test_job.retry, 3)
self.assertEqual(test_job.eta, datetime(2015, 6, 1, 15, 10, 10))
test_job.retry += 1
test_job.postpone(self.env)
self.assertEqual(test_job.retry, 4)
self.assertEqual(test_job.eta, datetime(2015, 6, 1, 15, 10, 10))
test_job.retry += 1
test_job.postpone(self.env)
self.assertEqual(test_job.retry, 5)
self.assertEqual(test_job.eta, datetime(2015, 6, 1, 15, 15, 0))
def test_retry_pattern_no_zero(self):
"""When we specify a retry pattern without 0, uses RETRY_INTERVAL"""
method = self.env["test.queue.job"].job_with_retry_pattern__no_zero
test_job = Job(method, max_retries=0)
test_job.retry += 1
self.assertEqual(test_job.retry, 1)
self.assertEqual(test_job._get_retry_seconds(), RETRY_INTERVAL)
test_job.retry += 1
self.assertEqual(test_job.retry, 2)
self.assertEqual(test_job._get_retry_seconds(), RETRY_INTERVAL)
test_job.retry += 1
self.assertEqual(test_job.retry, 3)
self.assertEqual(test_job._get_retry_seconds(), 180)
test_job.retry += 1
self.assertEqual(test_job.retry, 4)
self.assertEqual(test_job._get_retry_seconds(), 180)
def test_job_delay_model_method_multi(self):
rec1 = self.env["test.queue.job"].create({"name": "test1"})
rec2 = self.env["test.queue.job"].create({"name": "test2"})
recs = rec1 + rec2
job_instance = recs.with_delay().mapped("name")
self.assertTrue(job_instance)
self.assertEqual(job_instance.args, ("name",))
self.assertEqual(job_instance.recordset, recs)
self.assertEqual(job_instance.model_name, "test.queue.job")
self.assertEqual(job_instance.method_name, "mapped")
self.assertEqual(["test1", "test2"], job_instance.perform())
def test_job_identity_key_no_duplicate(self):
"""If a job with same identity key in queue do not add a new one"""
id_key = "e294e8444453b09d59bdb6efbfec1323"
rec1 = self.env["test.queue.job"].create({"name": "test1"})
job_1 = rec1.with_delay(identity_key=id_key).mapped("name")
self.assertTrue(job_1)
job_2 = rec1.with_delay(identity_key=id_key).mapped("name")
self.assertEqual(job_2.uuid, job_1.uuid)
def test_job_with_mutable_arguments(self):
"""Job with mutable arguments do not mutate on perform()"""
delayable = self.env["test.queue.job"].with_delay()
job_instance = delayable.job_alter_mutable([1], mutable_kwarg={"a": 1})
self.assertTrue(job_instance)
result = job_instance.perform()
self.assertEqual(result, ([1, 2], {"a": 1, "b": 2}))
job_instance.set_done()
# at this point, the 'args' and 'kwargs' of the job instance
# might have been modified, but they must never be modified in
# the queue_job table after their creation, so a new 'load' will
# get the initial values.
job_instance.store()
# jobs are always loaded before being performed, so we simulate
# this behavior here to check if we have the correct initial arguments
job_instance = Job.load(self.env, job_instance.uuid)
self.assertEqual(([1],), job_instance.args)
self.assertEqual({"mutable_kwarg": {"a": 1}}, job_instance.kwargs)
def test_store_env_su_no_sudo(self):
demo_user = self.env.ref("base.user_demo")
self.env = self.env(user=demo_user)
delayable = self.env["test.queue.job"].with_delay()
test_job = delayable.testing_method()
stored = test_job.db_record()
job_instance = Job.load(self.env, stored.uuid)
self.assertFalse(job_instance.recordset.env.su)
self.assertTrue(job_instance.user_id, demo_user)
def test_store_env_su_sudo(self):
demo_user = self.env.ref("base.user_demo")
self.env = self.env(user=demo_user)
delayable = self.env["test.queue.job"].sudo().with_delay()
test_job = delayable.testing_method()
stored = test_job.db_record()
job_instance = Job.load(self.env, stored.uuid)
self.assertTrue(job_instance.recordset.env.su)
self.assertTrue(job_instance.user_id, demo_user)
class TestJobModel(JobCommonCase):
def test_job_change_state(self):
stored = self._create_job()
stored._change_job_state(DONE, result="test")
self.assertEqual(stored.state, DONE)
self.assertEqual(stored.result, "test")
stored._change_job_state(PENDING, result="test2")
self.assertEqual(stored.state, PENDING)
self.assertEqual(stored.result, "test2")
with self.assertRaises(ValueError):
# only PENDING and DONE supported
stored._change_job_state(STARTED)
def test_button_done(self):
stored = self._create_job()
stored.button_done()
self.assertEqual(stored.state, DONE)
self.assertEqual(
stored.result, "Manually set to done by %s" % self.env.user.name
)
def test_button_done_enqueue_waiting_dependencies(self):
job_root = Job(self.env["test.queue.job"].testing_method)
job_child = Job(self.env["test.queue.job"].testing_method)
job_child.add_depends({job_root})
DelayableGraph._ensure_same_graph_uuid([job_root, job_child])
job_root.store()
job_child.store()
self.assertEqual(job_child.state, WAIT_DEPENDENCIES)
record_root = job_root.db_record()
record_child = job_child.db_record()
# Trigger button done
record_root.button_done()
# Check the state
self.assertEqual(record_root.state, DONE)
self.assertEqual(record_child.state, PENDING)
def test_button_cancel_dependencies(self):
job_root = Job(self.env["test.queue.job"].testing_method)
job_child = Job(self.env["test.queue.job"].testing_method)
job_child.add_depends({job_root})
DelayableGraph._ensure_same_graph_uuid([job_root, job_child])
job_root.store()
job_child.store()
self.assertEqual(job_child.state, WAIT_DEPENDENCIES)
record_root = job_root.db_record()
record_child = job_child.db_record()
# Trigger button cancelled
record_root.button_cancelled()
# Check the state
self.assertEqual(record_root.state, CANCELLED)
self.assertEqual(record_child.state, CANCELLED)
def test_requeue(self):
stored = self._create_job()
stored.write({"state": "failed"})
stored.requeue()
self.assertEqual(stored.state, PENDING)
def test_requeue_wait_dependencies_not_touched(self):
job_root = Job(self.env["test.queue.job"].testing_method)
job_child = Job(self.env["test.queue.job"].testing_method)
job_child.add_depends({job_root})
job_root.store()
job_child.store()
DelayableGraph._ensure_same_graph_uuid([job_root, job_child])
record_root = job_root.db_record()
record_child = job_child.db_record()
self.assertEqual(record_root.state, PENDING)
self.assertEqual(record_child.state, WAIT_DEPENDENCIES)
record_root.write({"state": "failed"})
(record_root + record_child).requeue()
self.assertEqual(record_root.state, PENDING)
self.assertEqual(record_child.state, WAIT_DEPENDENCIES)
def test_message_when_write_fail(self):
stored = self._create_job()
stored.write({"state": "failed"})
self.assertEqual(stored.state, FAILED)
messages = stored.message_ids
self.assertEqual(len(messages), 1)
def test_follower_when_write_fail(self):
"""Check that inactive users doesn't are not followers even if
they are linked to an active partner"""
group = self.env.ref("queue_job.group_queue_job_manager")
vals = {
"name": "xx",
"login": "xx",
"groups_id": [(6, 0, [group.id])],
"active": False,
}
inactiveusr = self.user.create(vals)
inactiveusr.partner_id.active = True
self.assertFalse(inactiveusr in group.users)
stored = self._create_job()
stored.write({"state": "failed"})
followers = stored.message_follower_ids.mapped("partner_id")
self.assertFalse(inactiveusr.partner_id in followers)
self.assertFalse({u.partner_id for u in group.users} - set(followers))
def test_wizard_requeue(self):
stored = self._create_job()
stored.write({"state": "failed"})
model = self.env["queue.requeue.job"]
model = model.with_context(active_model="queue.job", active_ids=stored.ids)
model.create({}).requeue()
self.assertEqual(stored.state, PENDING)
def test_context_uuid(self):
delayable = self.env["test.queue.job"].with_delay()
test_job = delayable.testing_method(return_context=True)
result = test_job.perform()
key_present = "job_uuid" in result
self.assertTrue(key_present)
self.assertEqual(result["job_uuid"], test_job._uuid)
def test_override_channel(self):
delayable = self.env["test.queue.job"].with_delay(channel="root.sub.sub")
test_job = delayable.testing_method(return_context=True)
self.assertEqual("root.sub.sub", test_job.channel)
def test_job_change_user_id(self):
demo_user = self.env.ref("base.user_demo")
stored = self._create_job()
stored.user_id = demo_user
self.assertEqual(stored.records.env.uid, demo_user.id)
class TestJobStorageMultiCompany(common.TransactionCase):
"""Test storage of jobs"""
def setUp(self):
super().setUp()
self.queue_job = self.env["queue.job"]
grp_queue_job_manager = self.ref("queue_job.group_queue_job_manager")
User = self.env["res.users"]
Company = self.env["res.company"]
Partner = self.env["res.partner"]
main_company = self.env.ref("base.main_company")
self.partner_user = Partner.create(
{"name": "Simple User", "email": "simple.user@example.com"}
)
self.simple_user = User.create(
{
"partner_id": self.partner_user.id,
"company_ids": [(4, main_company.id)],
"login": "simple_user",
"name": "simple user",
"groups_id": [],
}
)
self.other_partner_a = Partner.create(
{"name": "My Company a", "is_company": True, "email": "test@tes.ttest"}
)
self.other_company_a = Company.create(
{
"name": "My Company a",
"partner_id": self.other_partner_a.id,
"currency_id": self.ref("base.EUR"),
}
)
self.other_user_a = User.create(
{
"partner_id": self.other_partner_a.id,
"company_id": self.other_company_a.id,
"company_ids": [(4, self.other_company_a.id)],
"login": "my_login a",
"name": "my user A",
"groups_id": [(4, grp_queue_job_manager)],
}
)
self.other_partner_b = Partner.create(
{"name": "My Company b", "is_company": True, "email": "test@tes.ttest"}
)
self.other_company_b = Company.create(
{
"name": "My Company b",
"partner_id": self.other_partner_b.id,
"currency_id": self.ref("base.EUR"),
}
)
self.other_user_b = User.create(
{
"partner_id": self.other_partner_b.id,
"company_id": self.other_company_b.id,
"company_ids": [(4, self.other_company_b.id)],
"login": "my_login_b",
"name": "my user B",
"groups_id": [(4, grp_queue_job_manager)],
}
)
def _create_job(self, env):
self.cr.execute("delete from queue_job")
env["test.queue.job"].with_delay().testing_method()
stored = self.queue_job.search([])
self.assertEqual(len(stored), 1)
return stored
def test_job_default_company_id(self):
"""the default company is the one from the current user_id"""
stored = self._create_job(self.env)
self.assertEqual(
stored.company_id.id,
self.ref("base.main_company"),
"Incorrect default company_id",
)
env = self.env(user=self.other_user_b.id)
stored = self._create_job(env)
self.assertEqual(
stored.company_id.id,
self.other_company_b.id,
"Incorrect default company_id",
)
def test_job_no_company_id(self):
"""if we put an empty company_id in the context
jobs are created without company_id
"""
env = self.env(context={"company_id": None})
stored = self._create_job(env)
self.assertFalse(stored.company_id, "Company_id should be empty")
def test_job_specific_company_id(self):
"""If a company_id specified in the context
it's used by default for the job creation"""
env = self.env(context={"company_id": self.other_company_a.id})
stored = self._create_job(env)
self.assertEqual(
stored.company_id.id, self.other_company_a.id, "Incorrect company_id"
)
def test_job_subscription(self):
# if the job is created without company_id, all members of
# queue_job.group_queue_job_manager must be followers
User = self.env["res.users"]
no_company_context = dict(self.env.context, company_id=None)
no_company_env = self.env(user=self.simple_user, context=no_company_context)
stored = self._create_job(no_company_env)
stored._message_post_on_failure()
users = (
User.search(
[("groups_id", "=", self.ref("queue_job.group_queue_job_manager"))]
)
+ stored.user_id
)
self.assertEqual(len(stored.message_follower_ids), len(users))
expected_partners = [u.partner_id for u in users]
self.assertSetEqual(
set(stored.message_follower_ids.mapped("partner_id")),
set(expected_partners),
)
followers_id = stored.message_follower_ids.mapped("partner_id.id")
self.assertIn(self.other_partner_a.id, followers_id)
self.assertIn(self.other_partner_b.id, followers_id)
# jobs created for a specific company_id are followed only by
# company's members
company_a_context = dict(self.env.context, company_id=self.other_company_a.id)
company_a_env = self.env(user=self.simple_user, context=company_a_context)
stored = self._create_job(company_a_env)
stored.with_user(self.other_user_a.id)
stored._message_post_on_failure()
# 2 because simple_user (creator of job) + self.other_partner_a
self.assertEqual(len(stored.message_follower_ids), 2)
users = self.simple_user + self.other_user_a
expected_partners = [u.partner_id for u in users]
self.assertSetEqual(
set(stored.message_follower_ids.mapped("partner_id")),
set(expected_partners),
)
followers_id = stored.message_follower_ids.mapped("partner_id.id")
self.assertIn(self.other_partner_a.id, followers_id)
self.assertNotIn(self.other_partner_b.id, followers_id)