1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2026-11-08 11:16:47 +00:00
webvirtcloud/appsettings/test_get_settings.py
catborise e84db7542d fix(appsettings,vrtManager,storages): error handlers that hid the real failure
Reviewing the error handlers outside instances/ turned up three that masked or
swallowed the failure they caught:

- appsettings/settings.get_settings() runs on every request (middleware) and
  loads app_settings from the database. Its bare `except: pass` left `entries`
  unbound on a database error, so the next line raised UnboundLocalError
  instead; it also caught KeyboardInterrupt/SystemExit. It now catches
  DatabaseError and returns, keeping the already-loaded values.
- vrtManager.network.refresh_dhcp_leases raised a formatted string
  (`raise f"..."`), which Python rejects with TypeError, hiding the real
  DHCPLeases failure. It now raises util.OperationError, which the API/HTML
  error handling already renders as a libvirt error, and clears self.leases.
- storages.views.get_volumes caught libvirtError and answered 200 with an empty
  body, so the caller could not tell a failed pool read from an empty pool. It
  now returns 400 with the error.

The other broad handlers reviewed (appsettings/nwfilters/virtsecrets views,
storages/upload cleanup and recovery paths, vrtManager display getters) report
the error or are best-effort and were left as they are.

Tests: get_settings() survives a database error during the query and during
iteration without raising and still loads a real value; refresh_dhcp_leases
raises OperationError (keeping the cause) not TypeError; get_volumes returns 400
on a listing failure and the sorted volumes on success. The tests fail on the
previous code.
2026-10-07 11:29:45 +03:00

36 lines
1.6 KiB
Python

"""get_settings() runs on every request (middleware). A database error must not
leave the loop reading an unbound variable (the old bare except did), and must
not crash the request chain over a transient read."""
from unittest.mock import patch
from django.db import DatabaseError
from django.test import TestCase
from appsettings.models import AppSettings
from appsettings.settings import app_settings, get_settings
class GetSettingsTestCase(TestCase):
def test_a_database_error_does_not_raise(self):
app_settings.MARKER = "kept"
with patch("appsettings.settings.AppSettings.objects") as objects:
objects.all.side_effect = DatabaseError("db down")
get_settings() # must not raise UnboundLocalError or DatabaseError
self.assertEqual(app_settings.MARKER, "kept")
def test_settings_are_loaded_when_the_database_works(self):
AppSettings.objects.update_or_create(key="TEST_MARKER_KEY", defaults={"name": "m", "value": "from-db"})
try:
get_settings()
self.assertEqual(app_settings.TEST_MARKER_KEY, "from-db")
finally:
if hasattr(app_settings, "TEST_MARKER_KEY"):
delattr(app_settings, "TEST_MARKER_KEY")
def test_a_query_that_fails_during_iteration_does_not_raise(self):
app_settings.MARKER2 = "kept"
with patch("appsettings.settings.AppSettings.objects") as objects:
objects.all.return_value.__iter__.side_effect = DatabaseError("cursor died")
get_settings()
self.assertEqual(app_settings.MARKER2, "kept")