dff213cc61
user://tests liegt im echten Benutzerordner des Spiels, neben Spielstand, Schlüssel und Aufzeichnungen des Spielers. TestFiles.remove_dir löschte jeden Pfad, den es bekam; ein falsches Argument hätte echte Spielerdateien gelöscht. Tests, die früh mit einem Laufzeitfehler abbrachen, ließen ihren Ordner zurück (es lagen 15 solche Ordner im Benutzerordner). - remove_dir vereinfacht den Pfad (simplify_path) und verweigert alles, was nicht user://tests oder darunter liegt, mit push_error und ohne zu löschen. Die Wurzel steht in der Konstante TestFiles.ROOT, die auch temporary_dir benutzt. - run_tests.gd entfernt user://tests zu Beginn von _run_all, vor dem Fehlerzähler, aber nur wenn der Ordner existiert, weil Godot beim Auflisten eines fehlenden Ordners einen Fehler meldet. - CLAUDE.md sagt jetzt, dass die Tests unter user://tests schreiben und nie die echten Dateien des Spielers anfassen. Das Verweigern wurde einmal von Hand geprüft, mit einem Wegwerfskript auf selbst angelegten Ordnern: Ohne Schutz löschte remove_dir sie, mit Schutz bleiben sie samt Datei stehen und es erscheint ein Fehler, auch für einen Geschwisterordner user://tests_probe und für user://tests/../…. Danach waren die 15 Altlasten verschwunden und die Ausgabe fehlerfrei, auch ohne vorhandenen Ordner user://tests. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
30 lines
1.2 KiB
GDScript
30 lines
1.2 KiB
GDScript
class_name TestFiles
|
|
extends RefCounted
|
|
## Temporary folders below user://tests for tests that write files. That
|
|
## folder lies inside the game's real user folder, next to the player's own
|
|
## key, save and recordings, so nothing outside it may be deleted here.
|
|
|
|
## The only folder the tests write to and remove_dir deletes from.
|
|
const ROOT := "user://tests"
|
|
|
|
|
|
static func temporary_dir(label: String) -> String:
|
|
var path := ROOT.path_join("%s-%d" % [label, Time.get_ticks_usec()])
|
|
DirAccess.make_dir_recursive_absolute(path)
|
|
return path
|
|
|
|
|
|
## Deletes the folder `path` with everything in it. Refuses every path that is
|
|
## not ROOT or below it, with an error and without deleting anything: a wrong
|
|
## argument must never delete the player's real files.
|
|
static func remove_dir(path: String) -> void:
|
|
var clean := path.simplify_path()
|
|
if clean != ROOT and not clean.begins_with(ROOT + "/"):
|
|
push_error("TestFiles.remove_dir refuses %s: it is not %s or below it" % [path, ROOT])
|
|
return
|
|
for file in DirAccess.get_files_at(clean):
|
|
DirAccess.remove_absolute(clean.path_join(file))
|
|
for directory in DirAccess.get_directories_at(clean):
|
|
remove_dir(clean.path_join(directory))
|
|
DirAccess.remove_absolute(clean)
|