Quelltext des aktuellen Standes
<?php
declare(strict_types=1);
use OpenNIT\Services\MdmSyncDefaults;
use OpenNIT\Services\MdmSyncSafety;
/**
* Deckt die Schutzmechanismen ab, die Relution- und Intune-Sync gemeinsam nutzen:
* Plausibilitätsgrenze der Ausmusterung und Vorrang eines von Hand gesetzten Status.
*
* Maßgeblich ist, dass die Vorgaben das Verhalten bestehender Installationen
* nicht verändern – deshalb prüfen die Fälle gezielt die Grenzwerte.
*/
return static function (): void {
/** Erzeugt ein Testobjekt, das den Trait einbindet und seine Methoden freigibt. */
$subject = static function (): object {
return new class {
use MdmSyncSafety;
public array $log = [];
public array $errors = [];
public function allow(int $candidates, int $managed, int $maxPercent): bool
{
return $this->decommissionAllowed($candidates, $managed, $maxPercent);
}
public function mayStatus(array $specs, string $current): bool
{
return $this->mayOverwriteStatus($specs, $current);
}
public function markTruncated(): void
{
$this->truncated = true;
}
};
};
// ----------------------------------------------------------------
// Plausibilitätsgrenze der Ausmusterung
// ----------------------------------------------------------------
test('Ausmusterung: kleine Stückzahlen bleiben unabhängig vom Prozentsatz erlaubt', function () use ($subject) {
// 10 von 20 sind 50 %, liegen aber unter der absoluten Untergrenze.
assertTrue($subject()->allow(10, 20, 20));
});
test('Ausmusterung: im Rahmen der Grenze erlaubt', function () use ($subject) {
assertTrue($subject()->allow(30, 1000, 20)); // 3 %
assertTrue($subject()->allow(200, 1000, 20)); // exakt 20 %
});
test('Ausmusterung: oberhalb der Grenze abgelehnt und protokolliert', function () use ($subject) {
$s = $subject();
assertFalse($s->allow(400, 1000, 20)); // 40 %
assertTrue(count($s->log) === 1);
assertTrue(str_contains($s->log[0], 'Ausmusterung übersprungen'));
});
test('Ausmusterung: Grenze 0 schaltet die Prüfung ab', function () use ($subject) {
assertTrue($subject()->allow(999, 1000, 0));
});
test('Ausmusterung: nichts auszumustern ist immer erlaubt', function () use ($subject) {
assertTrue($subject()->allow(0, 1000, 20));
});
test('Ausmusterung: nach einem abgebrochenen Lauf grundsätzlich abgelehnt', function () use ($subject) {
$s = $subject();
$s->markTruncated();
// Selbst ein winziger, sonst unbedenklicher Umfang bleibt gesperrt.
assertFalse($s->allow(1, 1000, 20));
assertTrue(str_contains($s->log[0], 'Laufzeitgrenze'));
});
test('Ausmusterung: Vorgabewerte sind die dokumentierten', function () {
assertSame(20, MdmSyncDefaults::DECOMMISSION_MAX_PERCENT);
assertSame(25, MdmSyncDefaults::DECOMMISSION_MIN_ABSOLUTE);
});
// ----------------------------------------------------------------
// Vorrang eines von Hand gesetzten Status
// ----------------------------------------------------------------
test('Status: ohne Merker schreibt der Sync wie bisher', function () use ($subject) {
// Bestandsverhalten vor der ersten Ausführung mit Merker.
assertTrue($subject()->mayStatus([], 'active'));
assertTrue($subject()->mayStatus(['os_name' => 'iOS'], 'storage'));
});
test('Status: unveränderter Wert darf weiter gepflegt werden', function () use ($subject) {
assertTrue($subject()->mayStatus(['mdm_managed_status' => 'active'], 'active'));
});
test('Status: von Hand geänderter Wert bleibt stehen', function () use ($subject) {
assertFalse($subject()->mayStatus(['mdm_managed_status' => 'active'], 'storage'));
});
test('Status: ein zurückkehrendes Gerät wird wieder aktiviert', function () use ($subject) {
// Die Ausmusterung schreibt den Merker mit – der Sync bleibt zuständig.
assertTrue($subject()->mayStatus(['mdm_managed_status' => 'decommissioned'], 'decommissioned'));
});
};