package httpapi import ( "testing" "time" "github.com/syncova/syncova/packages/repository" ) // TestCollectLevelBuildsTreeWithoutDirectoryEntries haelt fest, dass der Baum // aus den Pfaden entsteht und nicht aus Verzeichniseintraegen. // // Ein Manifest kann eine Datei enthalten, deren Elternverzeichnis nicht als // eigener Eintrag vorliegt — etwa bei einer Quelle, die nur Dateien meldet. Wer // nur die Eintraege vom Typ "directory" auflistet, verliert dann ganze // Teilbaeume, und die Datei ist ueber die Oberflaeche nicht mehr erreichbar. func TestCollectLevelBuildsTreeWithoutDirectoryEntries(testInstance *testing.T) { manifestEntries := []repository.ManifestEntry{ // Kein Eintrag fuer "berichte" selbst. {Path: "berichte/2026/jahr.pdf", EntryType: "file", SizeBytes: 900}, {Path: "berichte/2025/jahr.pdf", EntryType: "file", SizeBytes: 100}, {Path: "notiz.txt", EntryType: "file", SizeBytes: 6}, } rootLevel := collectLevel(manifestEntries, "") if len(rootLevel) != 2 { testInstance.Fatalf("erwartet 2 Eintraege auf der Wurzel, erhalten %d", len(rootLevel)) } // Verzeichnisse stehen vorn. if !rootLevel[0].IsDirectory || rootLevel[0].Name != "berichte" { testInstance.Errorf("das Verzeichnis berichte fehlt oder steht nicht vorn: %+v", rootLevel[0]) } // Die Kennzahlen summieren den ganzen Teilbaum: Ein Betreiber will vor dem // Zurueckholen wissen, wie viel an einem Ordner haengt. if rootLevel[0].ChildCount != 2 || rootLevel[0].TotalBytes != 1000 { testInstance.Errorf("Kennzahlen des Ordners falsch: %d Objekte, %d Byte", rootLevel[0].ChildCount, rootLevel[0].TotalBytes) } // Und eine Ebene tiefer erscheinen die Jahresordner. deeperLevel := collectLevel(manifestEntries, "berichte") if len(deeperLevel) != 2 { testInstance.Fatalf("erwartet 2 Jahresordner, erhalten %d", len(deeperLevel)) } } // TestCollectLevelRespectsDirectoryBoundary haelt die Verzeichnisgrenze fest. // // "dokumente" darf nicht auch "dokumentation" treffen — sonst holte eine // Wiederherstellung Daten zurueck, die niemand ausgewaehlt hat. func TestCollectLevelRespectsDirectoryBoundary(testInstance *testing.T) { manifestEntries := []repository.ManifestEntry{ {Path: "dokumente/a.txt", EntryType: "file", SizeBytes: 1}, {Path: "dokumentation/b.txt", EntryType: "file", SizeBytes: 1}, } level := collectLevel(manifestEntries, "dokumente") if len(level) != 1 || level[0].Name != "a.txt" { testInstance.Errorf("die Verzeichnisgrenze wird nicht beachtet: %+v", level) } } // TestCollectLevelKeepsFileMetadata prueft die Angaben je Datei. func TestCollectLevelKeepsFileMetadata(testInstance *testing.T) { modificationTime := time.Date(2026, 8, 18, 10, 0, 0, 0, time.UTC) level := collectLevel([]repository.ManifestEntry{ {Path: "notiz.txt", EntryType: "file", SizeBytes: 42, Mode: "0644", ModifiedAt: modificationTime}, }, "") if len(level) != 1 { testInstance.Fatalf("erwartet einen Eintrag, erhalten %d", len(level)) } // Der Pfad ist genau der Wert, den eine Wiederherstellung als // `path_prefix` erwartet — eine Abweichung faellt sonst erst beim // Zurueckschreiben auf. if level[0].Path != "notiz.txt" || level[0].SizeBytes != 42 || level[0].Mode != "0644" { testInstance.Errorf("Angaben der Datei unvollstaendig: %+v", level[0]) } if level[0].ModifiedAt != "2026-08-18T10:00:00Z" { testInstance.Errorf("Zeitstempel falsch: %q", level[0].ModifiedAt) } }