82 lines
5.1 KiB
Swift
82 lines
5.1 KiB
Swift
import Foundation
|
|
|
|
@main
|
|
struct PlaybackProgressChecks {
|
|
static func require(_ condition: @autoclosure () -> Bool, _ message: String) {
|
|
if !condition() { fatalError("FAIL: " + message) }
|
|
}
|
|
|
|
static func main() throws {
|
|
let suite = "terebi.progress-check.\(UUID().uuidString)"
|
|
let defaults = UserDefaults(suiteName: suite)!
|
|
defer { defaults.removePersistentDomain(forName: suite) }
|
|
let directory = FileManager.default.temporaryDirectory.appendingPathComponent(suite)
|
|
try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true)
|
|
defer { try? FileManager.default.removeItem(at: directory) }
|
|
let file = directory.appendingPathComponent("video.mp4")
|
|
let otherFile = directory.appendingPathComponent("other.mp4")
|
|
let alias = directory.appendingPathComponent("alias.mp4")
|
|
try Data().write(to: file)
|
|
try FileManager.default.createSymbolicLink(at: alias, withDestinationURL: file)
|
|
let youtube = URL(string: "https://www.youtube.com/watch?v=jNQXAC9IVRw")!
|
|
|
|
let progress = PlaybackProgress(defaults: defaults)
|
|
let independent = PlaybackProgress(defaults: UserDefaults(suiteName: suite)!)
|
|
let independentFile = directory.appendingPathComponent("independent.mp4")
|
|
progress.save(123.25, for: file)
|
|
progress.save(18, for: otherFile)
|
|
progress.save(9.5, for: youtube)
|
|
let reopened = PlaybackProgress(defaults: UserDefaults(suiteName: suite)!)
|
|
require(reopened.position(for: file) == 123.25, "fractional local progress survives a fresh store")
|
|
require(reopened.position(for: alias) == 123.25, "symlink and original file share progress")
|
|
require(reopened.position(for: otherFile) == 18, "local files keep separate positions")
|
|
require(reopened.position(for: youtube) == 9.5, "canonical YouTube URL persists independently of local files")
|
|
independent.save(27, for: independentFile)
|
|
let shared = PlaybackProgress(defaults: defaults)
|
|
require(shared.position(for: file) == 123.25 && shared.position(for: youtube) == 9.5,
|
|
"an independently initialized player cannot overwrite another video's bookmarks")
|
|
require(shared.position(for: independentFile) == 27,
|
|
"independent player progress is also retained")
|
|
|
|
progress.save(nil, for: alias)
|
|
let completed = PlaybackProgress(defaults: defaults)
|
|
require(completed.position(for: file) == nil, "completion clears progress through either file identity")
|
|
require(completed.position(for: otherFile) == 18 && completed.position(for: youtube) == 9.5,
|
|
"clearing one video preserves other videos")
|
|
require(completed.position(for: independentFile) == 27,
|
|
"clearing progress in one player preserves a different player's bookmark")
|
|
for position in [Double.nan, Double.infinity, -Double.infinity, -1, 0] {
|
|
progress.save(position, for: file)
|
|
require(PlaybackProgress(defaults: defaults).position(for: file) == nil,
|
|
"invalid and zero positions never become resumable bookmarks")
|
|
}
|
|
let isolated = UserDefaults(suiteName: suite + ".isolated")!
|
|
defer { isolated.removePersistentDomain(forName: suite + ".isolated") }
|
|
require(PlaybackProgress(defaults: isolated).position(for: youtube) == nil,
|
|
"injected preference domains remain isolated")
|
|
isolated.set([file.standardizedFileURL.absoluteString: 42.5, youtube.absoluteString: 15],
|
|
forKey: "playbackPositions")
|
|
let migrated = PlaybackProgress(defaults: isolated)
|
|
require(migrated.position(for: alias) == 42.5 && migrated.position(for: youtube) == 15,
|
|
"existing local and YouTube bookmarks survive the shared-history migration")
|
|
migrated.save(43, for: file)
|
|
let migratedAgain = PlaybackProgress(defaults: isolated)
|
|
require(migratedAgain.position(for: file) == 43 && migratedAgain.position(for: youtube) == 15,
|
|
"opening another player preserves both migrated bookmarks and newer progress")
|
|
progress.recordRecent(file, title: "Original")
|
|
progress.recordRecent(youtube, title: "YouTube title")
|
|
independent.recordRecent(alias, title: "Renamed")
|
|
require(reopened.recentMedia == [
|
|
.init(url: file.resolvingSymlinksInPath(), title: "Renamed"), .init(url: youtube, title: "YouTube title")
|
|
], "recent media persists titles, shares file identities, and moves reopened items to the front")
|
|
for index in 0..<6 {
|
|
progress.recordRecent(directory.appendingPathComponent("\(index).mp4"), title: "Video \(index)")
|
|
}
|
|
require(reopened.recentMedia.map(\.title) == (0..<6).reversed().map { "Video \($0)" },
|
|
"recent media retains only the six most recently opened items in order")
|
|
require(PlaybackProgress(defaults: isolated).recentMedia.isEmpty,
|
|
"recent media respects the injected preference domain")
|
|
print("Playback progress checks passed")
|
|
}
|
|
}
|