[FIX] bus, website_livechat: prevent psycopg2 errors during tests

`psycopg2` errors sometimes happen during tests. This is caused by
race conditions between several `cr.execute()`/`cr.fetch*`.

This is even worse with websockets that are long lived connections
that sometimes open a cursor in the middle of the test.

Before websockets, longpolling was just disabled during tests. This
commits disable websockets as well in order to prevent those errors
as much as possible.

Some live chat tours were updated in [1] after the websockets intro-
duction due to some race conditions. This was reverted as the fix
relied on a hack on websockets that are now unavailable.

fixes runbot-25357,24809

[1]: https://github.com/odoo/odoo/pull/103521

closes odoo/odoo#143647

X-original-commit: e3b07a301036fcce76ebbbd856b507326b88160a
Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
Signed-off-by: Matthieu Stockbauer (tsm) <tsm@odoo.com>
This commit is contained in:
tsm-odoo
2023-11-30 05:17:40 +00:00
parent 5ba7e9e16c
commit 0feaa4f650
5 changed files with 12 additions and 19 deletions
-5
View File
@@ -1,7 +1,6 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import json
from werkzeug.exceptions import ServiceUnavailable
from odoo.http import Controller, request, route, SessionExpiredException
from odoo.addons.base.models.assetsbundle import AssetsBundle
@@ -16,10 +15,6 @@ class WebsocketController(Controller):
Handle the websocket handshake, upgrade the connection if
successfull.
"""
is_headful_browser = request.httprequest.user_agent and 'Headless' not in request.httprequest.user_agent.string
if request.registry.in_test_mode() and is_headful_browser:
# Prevent browsers from interfering with the unittests
raise ServiceUnavailable()
return WebsocketConnectionHandler.open_connection(request)
@route('/websocket/health', type='http', auth='none', save_session=False)
+1
View File
@@ -358,6 +358,7 @@ QUnit.test("Can reconnect after late close event", async (assert) => {
QUnit.test("Fallback on simple worker when shared worker failed to initialize", async (assert) => {
addBusServicesToRegistry();
patchWebsocketWorkerWithCleanup();
const originalSharedWorker = browser.SharedWorker;
const originalWorker = browser.Worker;
patchWithCleanup(browser, {
+4 -2
View File
@@ -12,12 +12,12 @@ except ImportError:
websocket = None
import odoo.tools
from odoo.tests import HOST, common
from odoo.tests import HOST, HttpCase
from ..websocket import CloseCode, Websocket, WebsocketConnectionHandler
from ..models.bus import dispatch, hashable, channel_with_db
class WebsocketCase(common.HttpCase):
class WebsocketCase(HttpCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
@@ -25,6 +25,8 @@ class WebsocketCase(common.HttpCase):
cls._logger.warning("websocket-client module is not installed")
raise unittest.SkipTest("websocket-client module is not installed")
cls._WEBSOCKET_URL = f"ws://{HOST}:{odoo.tools.config['http_port']}/websocket"
websocket_allowed_patch = patch.object(WebsocketConnectionHandler, "websocket_allowed", return_value=True)
cls.startClassPatcher(websocket_allowed_patch)
def setUp(self):
super().setUp()
@@ -183,17 +183,6 @@ class TestWebsocketCaryall(WebsocketCase):
self.assertEqual(notifications[0]['message']['type'], 'notif_type')
self.assertEqual(notifications[0]['message']['payload'], 'another_message')
def test_opening_websocket_connection_during_tests(self):
# During tests, browsers can't open websocket connections.
headers = ['User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36']
with self.assertRaises(WebSocketBadStatusException) as error_catcher:
self.websocket_connect(header=headers)
self.assertEqual(error_catcher.exception.status_code, 503)
# But ChromeHeadless still can.
headers = ['User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/102.0.0.0 Safari/537.36']
self.websocket_connect()
def test_subscribe_higher_last_notification_id(self):
server_last_notification_id = self.env['bus.bus'].sudo().search([], limit=1, order='id desc').id or 0
client_last_notification_id = server_last_notification_id + 1
+7 -1
View File
@@ -19,7 +19,7 @@ from urllib.parse import urlparse
from weakref import WeakSet
from werkzeug.local import LocalStack
from werkzeug.exceptions import BadRequest, HTTPException
from werkzeug.exceptions import BadRequest, HTTPException, ServiceUnavailable
import odoo
from odoo import api
@@ -821,6 +821,10 @@ class WebsocketConnectionHandler:
'sec-websocket-version', 'upgrade', 'origin',
}
@classmethod
def websocket_allowed(cls, request):
return not request.registry.in_test_mode()
@classmethod
def open_connection(cls, request):
"""
@@ -831,6 +835,8 @@ class WebsocketConnectionHandler:
versions the client supports and those we support.
:raise: BadRequest if the handshake data is incorrect.
"""
if not cls.websocket_allowed(request):
raise ServiceUnavailable("Websocket is disabled in test mode")
cls._handle_public_configuration(request)
try:
response = cls._get_handshake_response(request.httprequest.headers)