So erzeugen Sie eine beschädigte Datei zum Testen
Ein Validator, dem man nur gesunde Dateien gezeigt hat, ist nicht wirklich getestet. So bekommen Sie eine Datei, die absichtlich kaputt ist, genau die Größe hat, die Sie verlangen, und ein Manifest mitbringt, das sagt, was Ihr System damit tun soll.
Die kurze Antwort
tfg generate --format png --size 2mb --damage zero-head --out ./out schreibt ein PNG
von genau 2097152 Byte, dessen erste Bytes Nullen sind, und das Manifest daneben hält fest, dass
Ihr System es ablehnen soll.
Der übliche Weg
Warum eine von Hand beschädigte Datei ein schlechter Test ist
Üblich sind ein Hex-Editor, ein Skript, das ein paar zufällige Bytes kippt, oder eine Datei, die mit
head oder truncate gekürzt wird. Das funktioniert einmal, und dann
kostet es Sie:
- Es ist jedes Mal anders. Ein zufälliges Byte landet bei jedem Lauf woanders, ein Fehler vom Dienstag kommt am Mittwoch womöglich nicht wieder.
- Es verändert die Größe. Eine gekürzte Datei ist kleiner als das Limit, unter dem sie liegen sollte, also antwortet die Größenprüfung vor der Inhaltsprüfung, und der Test besteht aus dem falschen Grund.
- Es fällt oft nicht auf. Reiner Text lässt sich mit einem geänderten Byte in der Mitte weiterlesen, und ein nachsichtiger Bildleser zeichnet es einfach, sodass die Datei, die kaputt sein sollte, angenommen wird.
- Es sagt nichts darüber, was geschehen soll. Die Datei besteht nur aus Bytes, und wer den Test später liest, muss raten, ob Annahme oder Ablehnung gemeint war.
Was Sie bekommen
Eine beschädigte Datei hat trotzdem die verlangte Größe
Die Datei wird normal erzeugt und erst danach auf dem Weg zur Festplatte beschädigt. Sie behält die verlangte Größe, und derselbe Befehl schreibt wieder dieselben Bytes.
tfg generate --format png --size 2mb --damage zero-head --out ./out
tfg generate --format pdf --size 1mb --count 5 --damage zero-head:bytes=16 --out ./broken
Einstellungen stehen nach einem Doppelpunkt. Die Option lässt sich wiederholen, und die Beschädigungen werden in der Reihenfolge angewendet, in der Sie sie schreiben. Es funktioniert mit allen 26 Formaten.
Was möglich ist
Welche Beschädigungen gibt es?
Das ist die Liste, die das Programm ausgibt, beim Erstellen dieser Seite aus ihm gelesen. tfg
damage gibt dieselbe aus, und tfg damage <id> sagt, was eine davon
annimmt.
| Beschädigung | Was sie mit den Bytes macht | Kleinste Datei | Einstellungen |
|---|---|---|---|
zero-head |
Überschreibt die ersten Bytes der Datei mit Nullen und lässt ihre Länge unverändert. Die meisten Leser schauen zuerst dorthin, deshalb bemerkt fast alles diese Beschädigung. | 8 | bytes |
zero-head schreibt Nullen über den Anfang der Datei. Die meisten Leser schauen zuerst
dorthin, auf die Signatur und den Header, die sagen, was die Datei ist, deshalb bemerkt es fast
jeder Leser. Reiner Text und Logs haben keine Signatur und werden ebenfalls abgewiesen, weil
eine Folge von Nullbytes kein Text ist. Unter vier Bytes entstehen bei manchen Formaten Schäden,
über die sich kein Leser beschwert, deshalb beginnt die Einstellung bei vier.
Was das Manifest sagt
Ein Manifest, das sagt, was geschehen soll
Jede beschädigte Datei bekommt einen Eintrag, der besagt, dass Ihr System sie ablehnen soll, mit der Beschädigung daneben:
"expected": {
"outcome": "reject",
"reason": "content_malformed",
"confidence": "certain"
},
"damage": [
{
"type": "zero-head",
"settings": {
"bytes": "8"
}
}
]
Zwei Anfragen werden abgelehnt, bevor etwas geschrieben wird, denn jede würde eine Datei hinterlassen, die das Manifest falsch beschreibt:
- eine Datei, die kleiner ist, als die Beschädigung braucht, und unverändert herauskäme
-
expected: acceptneben einer Beschädigung, weil nichts es erfüllen könnte. Schreiben Siesanitize, wenn Ihr System die Datei reparieren soll, oderunspecified, wenn genau das Ihre Frage ist
In einem Rezept
Gesunde und kaputte Dateien in einem Lauf
Legen Sie beides in ein Rezept, dann trägt das Manifest die Erwartung jeder Datei, und der Test braucht keine Liste, welche welche ist:
version: 1
targets:
- id: healthy
format: pdf
size: 1mb
expected: accept
- id: broken
format: pdf
size: 1mb
damage:
- zero-head
In einem Test
Daraus einen Test machen
Der Test liest das Manifest und prüft, ob das, was geschah, dem Erklärten entspricht. Er braucht keine Liste von Dateinamen:
import json, os
directory = "healthy-and-broken"
manifest = json.load(open(os.path.join(directory, "manifest.json")))
for entry in manifest["files"]:
response = upload(os.path.join(directory, entry["path"]))
if entry["expected"]["outcome"] == "reject":
assert not response.ok
else:
assert response.ok
Eine gute Ablehnung ist eine saubere. Eine Meldung, die sagt, was falsch war, ist die gewünschte Antwort. Ein Serverfehler, ein Hänger oder eine halb gespeicherte Datei ist der Fehler, den dieser Test finden soll.
Weiter
Wohin es von hier geht
- Das Preset upload-validation stellt einem Formular die beiden anderen Fragen, die nach Größe und die nach Typ.
- Testdateien in CI führt ein Rezept wie dieses in einer Pipeline aus.
-
Die Dokumentation kennt jede Option von
tfg generate.