import Foundation import RastrilloNative import RastrilloTestSupport import XCTest final class FaultingBlobStoreTests: XCTestCase { func testACrashFreezesTheCommittedViewAndEverythingAfterFails() throws { let store = FaultingBlobStore(crashAt: 2) try store.write(Data("a".utf8), to: "x/1") try store.write(Data("b".utf8), to: "x/2") XCTAssertThrowsError(try store.write(Data("c".utf8), to: "x/3")) { XCTAssertEqual($0 as? SimulatedCrash, SimulatedCrash(operation: 2)) } XCTAssertThrowsError(try store.read("x/1"), "A dead process does nothing more") { XCTAssertTrue($0 is SimulatedCrash) } XCTAssertTrue(store.hasCrashed) XCTAssertEqual(store.committed.contents.keys.sorted(), ["x/1", "x/2"], "The crashed write never happened") XCTAssertEqual(store.operations, [.write("x/1"), .write("x/2")]) } func testCrashAfterCountsFromNow() throws { let store = FaultingBlobStore() try store.write(Data("a".utf8), to: "x/1") store.crash(after: 1) try store.remove("x/1") XCTAssertThrowsError(try store.list("x")) XCTAssertEqual(store.committed.contents, [:]) } func testUnavailableAnswersEveryOperationAndChangesNothing() throws { let store = FaultingBlobStore() try store.write(Data("a".utf8), to: "x/1") store.unavailable = true XCTAssertThrowsError(try store.read("x/1")) { XCTAssertEqual($0 as? BlobStoreError, .unavailable) } XCTAssertThrowsError(try store.remove("x/1")) { XCTAssertEqual($0 as? BlobStoreError, .unavailable) } XCTAssertThrowsError(try store.list("x")) { XCTAssertEqual($0 as? BlobStoreError, .unavailable) } store.unavailable = false XCTAssertEqual(try store.read("x/1"), Data("a".utf8)) } func testMemoryStoreListsOneLevelAndRemovesDirectories() throws { let store = MemoryBlobStore() try store.write(Data(), to: "outbox/1.entry") try store.write(Data(), to: "outbox/2.entry") try store.write(Data(), to: "cache/docs/a/replica") XCTAssertEqual(try store.list("outbox"), ["1.entry", "2.entry"]) XCTAssertEqual(try store.list("cache/docs"), []) try store.remove("cache") XCTAssertEqual(store.contents.keys.sorted(), ["outbox/1.entry", "outbox/2.entry"]) } }