OpenNIT

Quelltext des aktuellen Standes

Fassung 1.1.1

UserSettingCapacityTest.php

4 KB
<?php

declare(strict_types=1);

use OpenNIT\Core\SchemaInspector;

/**
 * Deckt die Kapazität der Wertspalte für Benutzereinstellungen ab.
 *
 * Mehrere Einstellungen liegen als ein einziger JSON-Wert in
 * `user_settings.setting_value` und wachsen mit der Nutzung: gespeicherte
 * Filter-Ansichten des Inventars, Dashboard-Belegung, Schnellzugriff, eigene
 * Themen-Sortierung, benutzerdefiniertes Menü-Layout. Da die Anwendung mit
 * STRICT_TRANS_TABLES arbeitet, weist die Datenbank einen zu langen Wert ab,
 * statt ihn zu kürzen. Die Spalte muss deshalb mindestens so viel fassen, wie
 * die Anwendung selbst durchlässt.
 */
return static function (): void {

    /** Kapazität der Spalte, wie sie sich aus den Migrationen ergibt. */
    $kapazitaet = static function (): ?int {
        $klasse = new ReflectionClass(SchemaInspector::class);
        $inspektor = $klasse->newInstanceWithoutConstructor();
        $feld = $klasse->getProperty('migrationsDir');
        $feld->setAccessible(true);
        $feld->setValue($inspektor, dirname(__DIR__) . '/database/migrations');

        $spalten = $inspektor->expectedSchema()['wide_columns'];
        return $spalten['user_settings.setting_value']['cap'] ?? null;
    };

    // ----------------------------------------------------------------
    // Deklarierte Kapazität
    // ----------------------------------------------------------------

    test('Die Wertspalte fasst mindestens TEXT', function () use ($kapazitaet) {
        // Nur Spalten ab TEXT werden vom Schema-Abgleich überwacht; darunter
        // fiele die Spalte aus der Drift-Erkennung heraus.
        $cap = $kapazitaet();

        assertTrue($cap !== null, 'Die Spalte ist nicht als breite Spalte deklariert');
        assertTrue($cap >= 65535, 'Deklarierte Kapazität: ' . var_export($cap, true));
    });

    // ----------------------------------------------------------------
    // Was die Anwendung durchlässt
    // ----------------------------------------------------------------

    test('Die zulässige Höchstzahl gespeicherter Ansichten passt hinein', function () use ($kapazitaet) {
        // Obergrenzen aus AssetController::savedViewSave(): 20 Ansichten,
        // je 60 Zeichen Name und 500 Zeichen Filter. Mehrbyte-Zeichen zählen
        // dort nach Zeichen, in der Spalte nach Bytes – deshalb der Aufschlag.
        $views = [];
        for ($i = 0; $i < 20; $i++) {
            $views[] = [
                'name'  => str_repeat('ä', 60),
                'query' => str_repeat('ä', 500),
            ];
        }

        assertTrue(strlen(json_encode($views)) <= $kapazitaet(), 'Die Höchstbelegung passt nicht in die Spalte');
    });

    test('Das größte zulässige Menü-Layout passt hinein', function () use ($kapazitaet) {
        // ApiController::normalizeNavLayout() weist alles über 8192 Zeichen ab;
        // bis dahin muss die Spalte den Wert aufnehmen können.
        assertTrue(8192 <= $kapazitaet(), 'Ein zulässiges Menü-Layout passt nicht in die Spalte');
    });

    // ----------------------------------------------------------------
    // Grund für die Verbreiterung
    // ----------------------------------------------------------------

    test('Die frühere Breite hätte für wenige Ansichten gereicht', function () {
        // Begründet die Migration: Die Filterleiste sendet alle acht Felder mit,
        // auch die leeren – der Filter ist deshalb unabhängig vom tatsächlich
        // Gefilterten rund 80 Zeichen lang und das JSON war nach vier Ansichten
        // an der alten Grenze von 500 Zeichen.
        $query = 'q=&category=3&manufacturer=&type=&location=12&status=active&assignment=&warranty=';

        $views = [];
        for ($i = 0; $i < 4; $i++) {
            $views[] = ['name' => 'Ansicht ' . ($i + 1), 'query' => $query];
        }
        assertTrue(strlen(json_encode($views)) <= 500, 'Vier Ansichten passten schon vorher nicht');

        $views[] = ['name' => 'Ansicht 5', 'query' => $query];
        assertTrue(strlen(json_encode($views)) > 500, 'Die fünfte Ansicht hätte auch vorher gepasst');
    });
};