From 63aad305bd2f14b3e6cf4d9141aa2b377ea9bd9e Mon Sep 17 00:00:00 2001 From: Chandragupt Singh Date: Sat, 6 Jun 2026 23:46:49 +0530 Subject: [PATCH 1/4] Fix intermittent 500 errors in get_test_results() from SQLAlchemy lazy loading --- mod_test/controllers.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/mod_test/controllers.py b/mod_test/controllers.py index 267ce43c..3f2d3702 100644 --- a/mod_test/controllers.py +++ b/mod_test/controllers.py @@ -6,7 +6,7 @@ from flask import (Blueprint, Response, abort, g, jsonify, redirect, request, url_for) from sqlalchemy import and_, select - +from sqlalchemy.orm import selectinload from decorators import template_renderer from exceptions import TestNotFoundException from mod_auth.controllers import check_access_rights, login_required @@ -61,13 +61,21 @@ def get_test_results(test) -> List[Dict[str, Any]]: :type test: Test """ populated_categories = select(regressionTestLinkTable.c.category_id) - categories = Category.query.filter(Category.id.in_(populated_categories)).order_by(Category.name.asc()).all() + categories = Category.query.options( + selectinload(Category.regression_tests) + ).filter( + Category.id.in_(populated_categories) + ).order_by(Category.name.asc()).all() results = [{ 'category': category, 'tests': [{ 'test': rt, 'result': next((r for r in test.results if r.regression_test_id == rt.id), None), - 'files': TestResultFile.query.filter( + 'files': TestResultFile.query.options( + selectinload(TestResultFile.regression_test_output).selectinload( + RegressionTestOutput.multiple_files + ) + ).filter( and_(TestResultFile.test_id == test.id, TestResultFile.regression_test_id == rt.id) ).all() } for rt in category.regression_tests if rt.id in test.get_customized_regressiontests()] @@ -88,7 +96,7 @@ def get_test_results(test) -> List[Dict[str, Any]]: test_error = True if len(category_test['files']) > 0: for result_file in category_test['files']: - if result_file.got is not None and result.exit_code == 0: + if result_file.got is not None and (result is None or result.exit_code == 0): file_error = True for file in result_file.regression_test_output.multiple_files: if file.file_hashes == result_file.got: From 89f8365e67d1664907ef9ea605898242d24edf40 Mon Sep 17 00:00:00 2001 From: Chandragupt Singh Date: Sun, 7 Jun 2026 01:25:59 +0530 Subject: [PATCH 2/4] Fix import ordering (isort) --- mod_test/controllers.py | 1 + 1 file changed, 1 insertion(+) diff --git a/mod_test/controllers.py b/mod_test/controllers.py index 3f2d3702..e97d8d55 100644 --- a/mod_test/controllers.py +++ b/mod_test/controllers.py @@ -7,6 +7,7 @@ url_for) from sqlalchemy import and_, select from sqlalchemy.orm import selectinload + from decorators import template_renderer from exceptions import TestNotFoundException from mod_auth.controllers import check_access_rights, login_required From f82c0ee0d368f343d67661e0c6c5c872e2dc2250 Mon Sep 17 00:00:00 2001 From: Chandragupt Singh Date: Sun, 7 Jun 2026 01:55:18 +0530 Subject: [PATCH 3/4] Fix import ordering, use joinedload for scalar relationship, update test assertion --- mod_test/controllers.py | 4 ++-- tests/test_test/test_controllers.py | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/mod_test/controllers.py b/mod_test/controllers.py index e97d8d55..7aca79bd 100644 --- a/mod_test/controllers.py +++ b/mod_test/controllers.py @@ -6,7 +6,7 @@ from flask import (Blueprint, Response, abort, g, jsonify, redirect, request, url_for) from sqlalchemy import and_, select -from sqlalchemy.orm import selectinload +from sqlalchemy.orm import joinedload, selectinload from decorators import template_renderer from exceptions import TestNotFoundException @@ -73,7 +73,7 @@ def get_test_results(test) -> List[Dict[str, Any]]: 'test': rt, 'result': next((r for r in test.results if r.regression_test_id == rt.id), None), 'files': TestResultFile.query.options( - selectinload(TestResultFile.regression_test_output).selectinload( + joinedload(TestResultFile.regression_test_output).selectinload( RegressionTestOutput.multiple_files ) ).filter( diff --git a/tests/test_test/test_controllers.py b/tests/test_test/test_controllers.py index 7d940d14..15a4cade 100644 --- a/tests/test_test/test_controllers.py +++ b/tests/test_test/test_controllers.py @@ -122,9 +122,10 @@ def test_ccextractor_version_not_found(self): self.assertEqual(response.status_code, 404) self.assert_template_used('test/test_not_found.html') + @mock.patch('mod_test.controllers.selectinload') @mock.patch('mod_test.controllers.GeneralData') @mock.patch('mod_test.controllers.Category') - def test_data_for_test(self, mock_category, mock_gen_data): + def test_data_for_test(self, mock_category, mock_gen_data, mock_selectinload): """Test get_data_for_test method.""" from mod_test.controllers import get_data_for_test @@ -144,7 +145,7 @@ def test_data_for_test(self, mock_category, mock_gen_data): self.assertIsInstance(result, dict) self.assertIn('avg_minutes', result) self.assertEqual(result['avg_minutes'], 6) # (300 + 60) / 60 = 6 minutes - mock_category.query.filter.assert_called_once() + mock_category.query.options.assert_called_once() self.assertEqual(mock_gen_data.query.filter.call_count, 2) @mock.patch('mod_test.controllers.Test') From 055295cb0452d4db837f457da2ef7a93fe99b5af Mon Sep 17 00:00:00 2001 From: Chandragupt Singh Date: Sun, 7 Jun 2026 21:34:39 +0530 Subject: [PATCH 4/4] Fix file comparison skipped for non-zero expected_rc regression tests --- mod_test/controllers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod_test/controllers.py b/mod_test/controllers.py index 7aca79bd..4c2477b8 100644 --- a/mod_test/controllers.py +++ b/mod_test/controllers.py @@ -97,7 +97,7 @@ def get_test_results(test) -> List[Dict[str, Any]]: test_error = True if len(category_test['files']) > 0: for result_file in category_test['files']: - if result_file.got is not None and (result is None or result.exit_code == 0): + if result_file.got is not None and (result is None or result.exit_code == result.expected_rc): file_error = True for file in result_file.regression_test_output.multiple_files: if file.file_hashes == result_file.got: