From 86f0b4bd20cdec86dfb5bdb7978d1f6ff4af111a Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Fri, 14 Aug 2026 22:41:54 +0800
Subject: [PATCH] [verified] feat: export performance diagnostics

---
 C1.source/Tests/AlignerCoreTests/AlignerCoreTests.swift |   84 ++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 84 insertions(+), 0 deletions(-)

diff --git a/C1.source/Tests/AlignerCoreTests/AlignerCoreTests.swift b/C1.source/Tests/AlignerCoreTests/AlignerCoreTests.swift
index 7c025f4..c0197df 100644
--- a/C1.source/Tests/AlignerCoreTests/AlignerCoreTests.swift
+++ b/C1.source/Tests/AlignerCoreTests/AlignerCoreTests.swift
@@ -9,6 +9,90 @@
         XCTAssertEqual(AlignerAppInfo.minimumMacOSVersion, "14.0")
     }
 
+    func testPerformanceDiagnosticArchiveWriterCreatesInspectableArchive() throws {
+        let fileManager = FileManager.default
+        let rootURL = fileManager.temporaryDirectory.appendingPathComponent(UUID().uuidString, isDirectory: true)
+        let logURL = rootURL.appendingPathComponent("events.log")
+        let archiveURL = rootURL.appendingPathComponent("diagnostics.zip")
+        let extractionURL = rootURL.appendingPathComponent("extracted", isDirectory: true)
+        defer { try? fileManager.removeItem(at: rootURL) }
+
+        try fileManager.createDirectory(at: rootURL, withIntermediateDirectories: true)
+        try "event=quickSwitch.snapshot.success durationMilliseconds=42\n".write(to: logURL, atomically: true, encoding: .utf8)
+        let summary = try JSONSerialization.data(withJSONObject: ["schemaVersion": 1], options: [])
+
+        _ = try PerformanceDiagnosticArchiveWriter.write(
+            to: archiveURL,
+            summaryJSON: summary,
+            eventLogURLs: [logURL]
+        )
+        XCTAssertTrue(fileManager.fileExists(atPath: archiveURL.path))
+
+        let unzipProcess = Process()
+        unzipProcess.executableURL = URL(fileURLWithPath: "/usr/bin/ditto")
+        unzipProcess.arguments = ["-x", "-k", archiveURL.path, extractionURL.path]
+        try unzipProcess.run()
+        unzipProcess.waitUntilExit()
+        XCTAssertEqual(unzipProcess.terminationStatus, 0)
+        let contentsURL = extractionURL.appendingPathComponent("Aligner-Diagnostics", isDirectory: true)
+        XCTAssertTrue(fileManager.fileExists(atPath: contentsURL.appendingPathComponent("summary.json").path))
+        XCTAssertTrue(fileManager.fileExists(atPath: contentsURL.appendingPathComponent("performance-events.log").path))
+        XCTAssertTrue(fileManager.fileExists(atPath: contentsURL.appendingPathComponent("README.txt").path))
+    }
+
+    func testPerformanceDiagnosticArchiveWriterDoesNotOverwriteExistingArchive() throws {
+        let fileManager = FileManager.default
+        let rootURL = fileManager.temporaryDirectory.appendingPathComponent(UUID().uuidString, isDirectory: true)
+        let archiveURL = rootURL.appendingPathComponent("diagnostics.zip")
+        defer { try? fileManager.removeItem(at: rootURL) }
+
+        try fileManager.createDirectory(at: rootURL, withIntermediateDirectories: true)
+        try Data("existing archive".utf8).write(to: archiveURL)
+        let summary = try JSONSerialization.data(withJSONObject: ["schemaVersion": 1], options: [])
+
+        XCTAssertThrowsError(
+            try PerformanceDiagnosticArchiveWriter.write(
+                to: archiveURL,
+                summaryJSON: summary,
+                eventLogURLs: []
+            )
+        )
+        XCTAssertEqual(try Data(contentsOf: archiveURL), Data("existing archive".utf8))
+    }
+
+    func testPerformanceDiagnosticArchiveWriterFiltersSensitiveLogFields() throws {
+        let fileManager = FileManager.default
+        let rootURL = fileManager.temporaryDirectory.appendingPathComponent(UUID().uuidString, isDirectory: true)
+        let sourceLogURL = rootURL.appendingPathComponent("events.log")
+        let archiveURL = rootURL.appendingPathComponent("diagnostics.zip")
+        let extractionURL = rootURL.appendingPathComponent("extracted", isDirectory: true)
+        defer { try? fileManager.removeItem(at: rootURL) }
+
+        try fileManager.createDirectory(at: rootURL, withIntermediateDirectories: true)
+        try "event=quickSwitch.snapshot.success ts=2026-08-14T00:00:00Z durationMilliseconds=42 reportPathBasename=private-notes.txt title=secret\n".write(to: sourceLogURL, atomically: true, encoding: .utf8)
+        let summary = try JSONSerialization.data(withJSONObject: ["schemaVersion": 1], options: [])
+        _ = try PerformanceDiagnosticArchiveWriter.write(
+            to: archiveURL,
+            summaryJSON: summary,
+            eventLogURLs: [sourceLogURL]
+        )
+
+        let unzipProcess = Process()
+        unzipProcess.executableURL = URL(fileURLWithPath: "/usr/bin/ditto")
+        unzipProcess.arguments = ["-x", "-k", archiveURL.path, extractionURL.path]
+        try unzipProcess.run()
+        unzipProcess.waitUntilExit()
+        XCTAssertEqual(unzipProcess.terminationStatus, 0)
+        let exportedLogURL = extractionURL
+            .appendingPathComponent("Aligner-Diagnostics", isDirectory: true)
+            .appendingPathComponent("performance-events.log")
+        let exportedLog = try String(contentsOf: exportedLogURL, encoding: .utf8)
+        XCTAssertTrue(exportedLog.contains("event=quickSwitch.snapshot.success"))
+        XCTAssertTrue(exportedLog.contains("durationMilliseconds=42"))
+        XCTAssertFalse(exportedLog.contains("private-notes.txt"))
+        XCTAssertFalse(exportedLog.contains("title=secret"))
+    }
+
     func testRound0OnlyDefinesQuickSwitchEntryPoint() {
         XCTAssertEqual(EntryPoint.allCases, [.quickSwitch])
     }

--
Gitblit v1.9.3