From 3c58197d81d2382b05aab26271fbeb596fabce90 Mon Sep 17 00:00:00 2001 From: Xavier-Do Date: Mon, 17 Jan 2022 08:20:26 +0000 Subject: [PATCH] [IMP] web: add tests for database manager Database manager may easily be broken since it wasn't tested and is a special case (can be rendered without databases). This commit adds a basic test to check that the database manager is rendered as expected. Testing database rendering is not enough, in some cases the database operations may be broken. Another test will be executed on runbot to test basic create/duplicate/delete operations. The test is tagged as "-standard" since it can be a risk to execute such operation automatically with other tests. closes odoo/odoo#82874 Signed-off-by: Raphael Collet --- addons/web/controllers/main.py | 6 ++ addons/web/tests/__init__.py | 1 + addons/web/tests/test_db_manager.py | 121 ++++++++++++++++++++++++++++ 3 files changed, 128 insertions(+) create mode 100644 addons/web/tests/test_db_manager.py diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py index 2f7a8a4e237..83b59fc60a1 100644 --- a/addons/web/controllers/main.py +++ b/addons/web/controllers/main.py @@ -1134,6 +1134,12 @@ class Database(http.Controller): try: dispatch_rpc('db','drop', [master_pwd, name]) request._cr = None # dropping a database leads to an unusable cursor + # if the user is connected to the dropped database, redirect will raise an operational error + # trying to access the registry of this database. + # Removing db from this request will prevent an invalid error message. (logout looks like a good idea in this case) + # https://github.com/odoo/odoo/pull/54102 is proposing a complete fix for this issue. + if request.session.db == name: + request.session.logout() return request.redirect('/web/database/manager') except Exception as e: error = "Database deletion error: %s" % (str(e) or repr(e)) diff --git a/addons/web/tests/__init__.py b/addons/web/tests/__init__.py index 62810336e66..031e1b56852 100644 --- a/addons/web/tests/__init__.py +++ b/addons/web/tests/__init__.py @@ -1,5 +1,6 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. +from . import test_db_manager from . import test_health from . import test_image from . import test_js diff --git a/addons/web/tests/test_db_manager.py b/addons/web/tests/test_db_manager.py new file mode 100644 index 00000000000..0ff8512e12a --- /dev/null +++ b/addons/web/tests/test_db_manager.py @@ -0,0 +1,121 @@ +# -*- encoding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +import operator +import re +import secrets +from unittest.mock import patch + +import requests + +import odoo +from odoo.tests.common import BaseCase, HttpCase, tagged +from odoo.tools import config + + +class TestDatabaseManager(HttpCase): + def test_database_manager(self): + res = self.url_open('/web/database/manager') + self.assertEqual(res.status_code, 200) + + # check that basic existing db actions are present + self.assertIn('.o_database_backup', res.text) + self.assertIn('.o_database_duplicate', res.text) + self.assertIn('.o_database_delete', res.text) + + # check that basic db actions are present + self.assertIn('.o_database_create', res.text) + self.assertIn('.o_database_restore', res.text) + + +@tagged('-at_install', 'post_install', '-standard', 'database_operations') +class TestDatabaseOperations(BaseCase): + def setUp(self): + self.password = secrets.token_hex() + + # monkey-patch password verification + self.verify_admin_password_patcher = patch( + 'odoo.tools.config.verify_admin_password', self.password.__eq__, + ) + self.verify_admin_password_patcher.start() + self.addCleanup(self.verify_admin_password_patcher.stop) + + self.db_name = config['db_name'] + self.assertTrue(self.db_name) + + # monkey-patch db-filter + self.addCleanup(operator.setitem, config, 'dbfilter', config['dbfilter']) + config['dbfilter'] = self.db_name + '-.*' + + self.base_databases = self.list_dbs() + self.session = requests.Session() + self.session.get(self.url('/web/database/manager')) + + def tearDown(self): + self.assertEqual( + self.list_dbs(), + self.base_databases, + 'No database should have been created or removed at the end of this test', + ) + + def list_dbs(self): + return set(odoo.service.db.list_dbs(True)) + + def list_dbs_filtered(self): + return set(db for db in self.list_dbs() if re.match(db, config['dbfilter'])) + + def url(self, path): + return HttpCase.base_url() + path + + def assertDbs(self, dbs): + self.assertEqual(self.list_dbs() - self.base_databases, set(dbs)) + + def test_database_creation(self): + # check verify_admin_password patch + self.assertTrue(odoo.tools.config.verify_admin_password(self.password)) + + # create a database + test_db_name = self.db_name + '-test-database-creation' + self.assertNotIn(test_db_name, self.list_dbs_filtered()) + res = self.session.post(self.url('/web/database/create'), data={ + 'master_pwd': self.password, + 'name': test_db_name, + 'login': 'admin', + 'password': 'admin', + 'lang': 'en_US', + 'phone': '', + }, allow_redirects=False) + self.assertEqual(res.status_code, 303) + self.assertIn('/web', res.headers['Location']) + self.assertDbs([test_db_name]) + + # delete the created database + res = self.session.post(self.url('/web/database/drop'), data={ + 'master_pwd': self.password, + 'name': test_db_name, + }, allow_redirects=False) + self.assertEqual(res.status_code, 303) + self.assertIn('/web/database/manager', res.headers['Location']) + self.assertDbs([]) + + def test_database_duplicate(self): + # duplicate this database + test_db_name = self.db_name + '-test-database-duplicate' + self.assertNotIn(test_db_name, self.list_dbs_filtered()) + res = self.session.post(self.url('/web/database/duplicate'), data={ + 'master_pwd': self.password, + 'name': self.db_name, + 'new_name': test_db_name, + }, allow_redirects=False) + self.assertEqual(res.status_code, 303) + self.assertIn('/web/database/manager', res.headers['Location']) + self.assertDbs([test_db_name]) + + # delete the created database + res = self.session.post(self.url('/web/database/drop'), data={ + 'master_pwd': self.password, + 'name': test_db_name, + }, allow_redirects=False) + self.assertEqual(res.status_code, 303) + self.assertIn('/web/database/manager', res.headers['Location']) + self.assertDbs([])