Skip to content

Commit fd214cb

Browse files
committed
[ADD] queue_job: HttpCase regression tests for /queue_job/runjob
Adds test_run_job_controller_http.py covering #922: - test_runjob_pins_default_env_to_superuser asserts that when _acquire_job is entered, env.transaction.default_env.uid is SUPERUSER_ID -- the state a job would inherit at perform time. - test_runjob_without_updating_default_env_leaves_uid_none patches Request.update_env to a no-op and verifies default_env.uid stays None, isolating default_env repointing as the load-bearing behavior of runjob. Tests use HttpCase so _auth_method_none, session handling, and update_env run for real. _acquire_job is patched to return None so the endpoint exits cleanly without performing DB work (its internal commit is forbidden inside tests).
1 parent 415420f commit fd214cb

2 files changed

Lines changed: 86 additions & 0 deletions

File tree

queue_job/tests/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from . import test_run_job_controller_http
12
from . import test_run_rob_controller
23
from . import test_runner_channels
34
from . import test_runner_runner
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
2+
3+
from unittest import mock
4+
5+
from odoo import SUPERUSER_ID, http
6+
from odoo.tests.common import HttpCase, tagged
7+
8+
from ..controllers.main import RunJobController
9+
10+
11+
@tagged("-at_install", "post_install")
12+
class TestRunJobHttp(HttpCase):
13+
"""End-to-end tests for the ``/queue_job/runjob`` endpoint.
14+
15+
``runjob`` is declared ``auth="none"``, so ``_auth_method_none`` pins
16+
``transaction.default_env`` to an env with ``uid=None``. The controller
17+
must additionally repoint ``default_env`` to a superuser env, otherwise
18+
any flush during ``job.perform()`` that goes through
19+
``Transaction.flush() -> default_env.flush_all()`` recomputes stored
20+
fields with ``self.env.user`` as an empty recordset. See #922.
21+
"""
22+
23+
def _capture_default_env_uid_at_acquire(self):
24+
"""Hit ``/queue_job/runjob`` and observe ``transaction.default_env.uid``
25+
at the moment ``_acquire_job`` is entered.
26+
27+
``_acquire_job`` is patched to return ``None`` so the endpoint exits
28+
without performing the job. This avoids the commit inside
29+
``_acquire_job``, which is forbidden inside tests, and is sufficient
30+
to observe the env state established by the request-handling
31+
machinery: nothing between ``update_env`` and ``_acquire_job``
32+
touches ``transaction.default_env``, so the value seen here is the
33+
same value a job would see at ``perform()`` time.
34+
35+
HttpCase runs the HTTP server in the same process, so class-level
36+
``mock.patch`` calls take effect on the server side as well.
37+
"""
38+
captured = {}
39+
40+
def spy(cls, env, job_uuid):
41+
captured["default_env_uid"] = env.transaction.default_env.uid
42+
return None
43+
44+
with mock.patch.object(RunJobController, "_acquire_job", classmethod(spy)):
45+
response = self.url_open(
46+
f"/queue_job/runjob?db={self.env.cr.dbname}&job_uuid=stub"
47+
)
48+
response.raise_for_status()
49+
50+
return captured.get("default_env_uid")
51+
52+
def test_runjob_pins_default_env_to_superuser(self):
53+
"""``runjob`` must set ``transaction.default_env`` to a superuser env.
54+
55+
Verifies that by the time ``_acquire_job`` is entered,
56+
``env.transaction.default_env.uid`` is ``SUPERUSER_ID``. This is the
57+
state that lets flushes triggered by the job recompute stored fields
58+
with a real ``self.env.user`` rather than an empty recordset.
59+
"""
60+
default_env_uid = self._capture_default_env_uid_at_acquire()
61+
self.assertEqual(default_env_uid, SUPERUSER_ID)
62+
63+
def test_runjob_without_updating_default_env_leaves_uid_none(self):
64+
"""Repointing ``default_env`` is the specific mechanism this relies on.
65+
66+
Neutralises ``http.request.update_env`` for the duration of the
67+
request, matching what happens if a ``runjob`` implementation only
68+
obtains a local superuser env via ``http.request.env(user=...)``
69+
without invoking ``update_env``. The observable ``default_env.uid``
70+
then remains at the ``None`` value installed by
71+
``_auth_method_none``. This isolates ``default_env`` repointing as
72+
the load-bearing behavior of ``runjob``: any future refactor that
73+
drops it will trip this test.
74+
"""
75+
76+
def no_op_update_env(self_, user=None, context=None, su=None):
77+
"""Alternative ``Request.update_env`` that intentionally does
78+
nothing. Simulates a controller that never asks the request to
79+
update its environment.
80+
"""
81+
82+
with mock.patch.object(http.Request, "update_env", no_op_update_env):
83+
default_env_uid = self._capture_default_env_uid_at_acquire()
84+
85+
self.assertIsNone(default_env_uid)

0 commit comments

Comments
 (0)