1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2026-11-08 19:26:48 +00:00
webvirtcloud/appsettings/tests/test_migrations.py
catborise b2deb042e8 feat(operations): the Logs page's rows and expired sessions are removed
Nothing removed the Logs page's rows, which every action and every
failed login adds, or the database sessions past their expiry. The job
worker's housekeeping now deletes the rows older than Log Retention
Days, a new setting under Lists and pages (1-3650, 365 by default), and
the expired sessions.
2026-11-05 10:36:34 +03:00

118 lines
5.7 KiB
Python

"""The default settings rows of the first migrations carry fixed ids, which a
PostgreSQL id sequence does not see. A later migration that inserts without
an id must not collide with them."""
import importlib
import unittest
from types import SimpleNamespace
from django.apps import apps
from django.db import connection
from django.test import TestCase, TransactionTestCase
from appsettings.models import AppSettings
login_lockout = importlib.import_module("appsettings.migrations.0014_login_lockout_settings")
@unittest.skipUnless(connection.vendor == "postgresql", "id sequences are a PostgreSQL concern")
class SequenceAfterFixedIdsTestCase(TransactionTestCase):
serialized_rollback = True
def test_login_lockout_settings_insert_after_fixed_ids(self):
with connection.schema_editor() as schema_editor:
login_lockout.del_settings(apps, schema_editor)
# the state after the fixed-id inserts: rows exist, the sequence starts at 1
with connection.cursor() as cursor:
cursor.execute("SELECT setval(pg_get_serial_sequence('appsettings_appsettings', 'id'), 1, false)")
login_lockout.add_settings(apps, schema_editor)
self.assertEqual(AppSettings.objects.filter(key__startswith="LOGIN_").count(), 2)
nic_type = importlib.import_module("appsettings.migrations.0016_nic_type_rtl8139")
class NicTypeTestCase(TestCase):
def test_the_misspelt_nic_type_becomes_rtl8139(self):
setting = AppSettings.objects.get(key="INSTANCE_NIC_DEFAULT_TYPE")
self.assertEqual(setting.choices, "default,e1000,e1000e,rtl8139,virtio")
AppSettings.objects.filter(pk=setting.pk).update(value="rt18139", choices="default,e1000,e1000e,rt18139,virtio")
nic_type.fix_rtl8139(apps, SimpleNamespace(connection=connection))
setting.refresh_from_db()
self.assertEqual((setting.value, setting.choices), ("rtl8139", "default,e1000,e1000e,rtl8139,virtio"))
class SnapshotFreeSpaceSettingsTestCase(TestCase):
def test_the_rows_fit_their_columns(self):
# PostgreSQL refuses a value longer than the column, sqlite does not
for key in ("SNAPSHOT_FREE_SPACE_PERCENT", "SNAPSHOT_FREE_SPACE_MIN_GIB"):
setting = AppSettings.objects.get(key=key)
for field in ("name", "key", "value", "description"):
limit = AppSettings._meta.get_field(field).max_length
if limit:
self.assertLessEqual(len(getattr(setting, field)), limit, f"{key} {field}")
class WorkerSettingsTestCase(TestCase):
def test_the_rows_fit_their_columns(self):
for key in ("WORKER_CONCURRENCY", "JOB_RETENTION_DAYS", "LOG_RETENTION_DAYS"):
setting = AppSettings.objects.get(key=key)
for field in ("name", "key", "value", "description"):
limit = AppSettings._meta.get_field(field).max_length
if limit:
self.assertLessEqual(len(getattr(setting, field)), limit, f"{key} {field}")
choices_fix = importlib.import_module("appsettings.migrations.0020_fix_setting_choices")
class ChoicesFixTestCase(TestCase):
"""Choices that offered values the panel cannot use, and a text setting
that showed as a True/False list."""
def test_the_broken_choices_are_fixed_and_their_values_moved(self):
broken = {
"CLONE_INSTANCE_DEFAULT_PREFIX": ("instance", "True,False"),
"INSTANCE_VOLUME_DEFAULT_SCSI_CONTROLLER": ("virtio-blk", "virtio-scsi, lsilogic, virtio-blk"),
"INSTANCE_MACHINE_DEFAULT_TYPE": ("x86_64", "q35,x86_64,virt"),
"INSTANCE_CDROM_ADD": ("virtio", "None,ide,sata,scsi,virtio"),
}
for key, (value, choices) in broken.items():
AppSettings.objects.filter(key=key).update(value=value, choices=choices)
choices_fix.fix_choices(apps, SimpleNamespace(connection=connection))
fixed = {s.key: (s.value, s.choices) for s in AppSettings.objects.filter(key__in=broken)}
self.assertEqual(fixed, {
"CLONE_INSTANCE_DEFAULT_PREFIX": ("instance", ""),
"INSTANCE_VOLUME_DEFAULT_SCSI_CONTROLLER": ("virtio-scsi", "virtio-scsi,lsilogic"),
"INSTANCE_MACHINE_DEFAULT_TYPE": ("q35", "q35,pc,virt"),
"INSTANCE_CDROM_ADD": ("sata", "None,ide,sata,scsi"),
})
descriptions = importlib.import_module("appsettings.migrations.0021_setting_descriptions")
class DescriptionsTestCase(TestCase):
def test_every_setting_says_what_it_does_within_its_column(self):
limit = AppSettings._meta.get_field("description").max_length
removed = {"VIEW_INSTANCE_DETAIL_BOTTOM_BAR"} # by 0023
for key, text in descriptions.DESCRIPTIONS.items():
with self.subTest(key=key):
self.assertLessEqual(len(text), limit)
if key not in removed:
self.assertEqual(AppSettings.objects.get(key=key).description, text)
self.assertFalse(AppSettings.objects.filter(key__in=removed).exists())
cpu_mode = importlib.import_module("appsettings.migrations.0022_cpu_mode_choices")
class CpuModeChoicesTestCase(TestCase):
def test_the_default_cpu_mode_is_one_the_new_vm_dialog_offers(self):
for old, new in (("no-model", "host-model"), ("custom", "host-model"), ("host-passthrough", "host-passthrough")):
with self.subTest(old=old):
AppSettings.objects.filter(key="INSTANCE_CPU_DEFAULT_MODE").update(
value=old, choices="no-model,host-model,host-passthrough,custom")
cpu_mode.fix_cpu_mode(apps, SimpleNamespace(connection=connection))
setting = AppSettings.objects.get(key="INSTANCE_CPU_DEFAULT_MODE")
self.assertEqual((setting.value, setting.choices), (new, "host-model,host-passthrough,maximum"))