‹ projects

reverb-m1

Native wired VR on Apple silicon: Reverb G1 display bring-up and stereo demo
git clone https://umhau.org/code/reverb-m1.git
Log | Files | Refs

LinkRecoveryChecks.swift (3294B)


      1 // Run without touching hardware:
      2 // swiftc Sources/VRWorkstation/{LinkRecovery,MainRunLoop}.swift Tests/LinkRecoveryChecks.swift -o /tmp/vr-recovery-checks-bin
      3 // /tmp/vr-recovery-checks-bin
      4 import Foundation
      5 
      6 func log(_ text: String) { print(text) }
      7 
      8 @main
      9 struct LinkRecoveryChecks {
     10     static func attempt(_ recovery: LinkRecovery) -> Bool {
     11         var result: Bool?
     12         recovery.reset { result = $0 }
     13         let deadline = Date().addingTimeInterval(6)
     14         while result == nil && Date() < deadline {
     15             RunLoop.main.run(until: Date().addingTimeInterval(0.02))
     16         }
     17         precondition(result != nil, "recovery did not complete within six seconds")
     18         return result!
     19     }
     20 
     21     static func main() throws {
     22         let directory = FileManager.default.temporaryDirectory.appendingPathComponent("vr-helper-check-\(UUID().uuidString)")
     23         try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true)
     24         defer { try? FileManager.default.removeItem(at: directory) }
     25         func helper(_ name: String, _ body: String) throws -> URL {
     26             let url = directory.appendingPathComponent(name)
     27             try body.write(to: url, atomically: true, encoding: .utf8)
     28             try FileManager.default.setAttributes([.posixPermissions: 0o700], ofItemAtPath: url.path)
     29             return url
     30         }
     31         let ok = try helper("ok", "#!/bin/sh\nexit 0\n")
     32         let limited = LinkRecovery(helper: ok)
     33         precondition((0..<4).map { _ in attempt(limited) } == [true, true, true, false],
     34                      "helper must run at most three times per minute")
     35 
     36         let stuck = LinkRecovery(helper: try helper("stuck", "#!/bin/sh\nexec /bin/sleep 10\n"))
     37         let start = Date()
     38         precondition(!attempt(stuck), "a timed-out helper must fail")
     39         let seconds = Date().timeIntervalSince(start)
     40         precondition(seconds >= 2.9 && seconds < 5, "helper must be killed after about three seconds")
     41 
     42         let missing = LinkRecovery(helper: directory.appendingPathComponent("missing"))
     43         precondition(!attempt(missing), "a missing helper must fail")
     44         // A headset ADD must cancel startup recovery even before the session binds an ID.
     45         let marker = directory.appendingPathComponent("ran")
     46         let recording = try helper("recording", "#!/bin/sh\n/usr/bin/touch \(marker.path)\n")
     47         let startup = LinkRecovery(helper: recording)
     48         startup.requestRecovery()
     49         startup.displayAdded(42)
     50         Thread.sleep(forTimeInterval: 2.3) // deliberately do not pump main
     51         precondition(!FileManager.default.fileExists(atPath: marker.path), "startup ADD must cancel reset")
     52         startup.trackDisplay(42)
     53         startup.displayRemoved(42)
     54         startup.displayAdded(43)
     55         Thread.sleep(forTimeInterval: 2.3)
     56         precondition(!FileManager.default.fileExists(atPath: marker.path), "changed display ID must cancel reset")
     57         startup.displayRemoved(43)
     58         Thread.sleep(forTimeInterval: 2.5)
     59         precondition(FileManager.default.fileExists(atPath: marker.path), "recovery deadline must fire while main is blocked")
     60         startup.stop()
     61         print("PASS: three resets/minute; stuck helper stopped in \(seconds)s; missing helper rejected")
     62     }
     63 }