OpenNIT

Quelltext des aktuellen Standes

Fassung 1.1.1

MigrationErrorClassificationTest.php

3 KB
<?php

declare(strict_types=1);

use OpenNIT\Content\UpdateManager;

/**
 * Deckt die Einordnung von SQL-Fehlern während eines Migrationslaufs ab.
 *
 * Ein als harmlos eingestufter Fehler führt dazu, dass die Migration als
 * angewendet vermerkt wird und nie wieder läuft. Diese Nachsicht darf deshalb
 * nur Anweisungen betreffen, deren Ziel bereits erreicht ist – niemals solche,
 * deren Wirkung ausgeblieben ist.
 */
return static function (): void {

    $einordnen = static function (string $meldung, string $statement = ''): bool {
        $ref = new ReflectionClass(UpdateManager::class);
        $m   = $ref->getMethod('isIgnorableSqlError');
        $m->setAccessible(true);
        return (bool)$m->invokeArgs($ref->newInstanceWithoutConstructor(), [$meldung, $statement]);
    };

    test('Bereits vorhandene Strukturen sind harmlos', function () use ($einordnen) {
        assertTrue($einordnen("Table 'assets' already exists"));
        assertTrue($einordnen("Duplicate column name 'status'", 'ALTER TABLE assets ADD COLUMN status VARCHAR(20)'));
        assertTrue($einordnen("Duplicate key name 'idx_status'", 'ALTER TABLE assets ADD INDEX idx_status (status)'));
        assertTrue($einordnen("Can't DROP 'alt'; check that column/key exists"));
    });

    test('Doppelwerte beim Anlegen eines eindeutigen Schlüssels sind ein harter Fehler', function () use ($einordnen) {
        // Der Schlüssel entsteht nicht – die Migration darf nicht als erledigt gelten.
        assertFalse($einordnen(
            "Duplicate entry '7-2' for key 'uniq_page_version'",
            'ALTER TABLE page_versions ADD UNIQUE KEY uniq_page_version (page_id, version_number)'
        ));
        assertFalse($einordnen(
            "Duplicate entry '3' for key 'PRIMARY'",
            'ALTER TABLE foo ADD PRIMARY KEY (id)'
        ));
        assertFalse($einordnen(
            "Duplicate entry 'x' for key 'uk_foo'",
            'ALTER TABLE foo ADD CONSTRAINT uk_foo UNIQUE (name)'
        ));
    });

    test('Ein bereits vorhandener Datensatz bleibt harmlos', function () use ($einordnen) {
        // Hier ist der Zielzustand erreicht, die Anweisung also wirkungslos.
        assertTrue($einordnen(
            "Duplicate entry 'mail_host' for key 'PRIMARY'",
            "INSERT INTO system_settings (`key`, `value`) VALUES ('mail_host', '')"
        ));
    });

    test('Fehlende Rechte auf Views und Trigger bleiben harmlos', function () use ($einordnen) {
        assertTrue($einordnen('SQLSTATE[HY000]: 1419 ... SUPER privilege'));
        assertTrue($einordnen('log_bin_trust_function_creators'));
    });
};