From 13b1979d3534a720826ce36ac98d675dafbcc522 Mon Sep 17 00:00:00 2001 From: Quickthyme Date: Thu, 11 Jul 2019 21:46:12 -0500 Subject: [PATCH] auto throw result failures option Signed-off-by: James Hall --- QLoop.xcodeproj/project.pbxproj | 10 +++++++ Sources/QLoop/Common/QLCommon.swift | 2 ++ Sources/QLoop/QLAnchor.swift | 13 +++++++-- Sources/QLoop/Result+ErrorGettable.swift | 12 ++++++++ Tests/QLoopTests/QLAnchorTests.swift | 36 ++++++++++++++++++++---- 5 files changed, 65 insertions(+), 8 deletions(-) create mode 100644 Sources/QLoop/Result+ErrorGettable.swift diff --git a/QLoop.xcodeproj/project.pbxproj b/QLoop.xcodeproj/project.pbxproj index 5a17670..2d6dcf5 100644 --- a/QLoop.xcodeproj/project.pbxproj +++ b/QLoop.xcodeproj/project.pbxproj @@ -138,6 +138,10 @@ DCC759272241D04100B4750E /* QLoop+ConvenienceInitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCC759262241D04100B4750E /* QLoop+ConvenienceInitTests.swift */; }; DCC759282241D04100B4750E /* QLoop+ConvenienceInitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCC759262241D04100B4750E /* QLoop+ConvenienceInitTests.swift */; }; DCC759292241D04100B4750E /* QLoop+ConvenienceInitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCC759262241D04100B4750E /* QLoop+ConvenienceInitTests.swift */; }; + DCFACAEB22D826C5004D6D7A /* Result+ErrorGettable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCFACAEA22D826C5004D6D7A /* Result+ErrorGettable.swift */; }; + DCFACAEC22D826C5004D6D7A /* Result+ErrorGettable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCFACAEA22D826C5004D6D7A /* Result+ErrorGettable.swift */; }; + DCFACAED22D826C5004D6D7A /* Result+ErrorGettable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCFACAEA22D826C5004D6D7A /* Result+ErrorGettable.swift */; }; + DCFACAEE22D826C5004D6D7A /* Result+ErrorGettable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCFACAEA22D826C5004D6D7A /* Result+ErrorGettable.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -250,6 +254,7 @@ DCD9D7C3223DDE0900BBDEE2 /* QLoop.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = QLoop.md; sourceTree = ""; }; DCD9D7C4223DDF8900BBDEE2 /* QLParallelSegment.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = QLParallelSegment.md; sourceTree = ""; }; DCD9D7C5223DE0C800BBDEE2 /* QLSerialSegment.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = QLSerialSegment.md; sourceTree = ""; }; + DCFACAEA22D826C5004D6D7A /* Result+ErrorGettable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Result+ErrorGettable.swift"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -386,6 +391,7 @@ DC6FAF5D222F4EF5008BB070 /* QLAnchor.swift */, DC5E449E224AFC2B0007FEAD /* QLAnchor+ConvenienceInit.swift */, DC8F2B58223342E000277F70 /* QLPath.swift */, + DCFACAEA22D826C5004D6D7A /* Result+ErrorGettable.swift */, DCF860BF2239D02B0018C1A1 /* Common */, DC374A322231F28A006F1272 /* Iterating */, DCA1FD232230C8E5006015BD /* Segment */, @@ -740,6 +746,7 @@ DCA1FD1F2230C8DB006015BD /* QLSegment.swift in Sources */, DC374A372231F2AD006F1272 /* QLoopIteratorContinueNilMax.swift in Sources */, DCA1FD0C22303D22006015BD /* QLoop.swift in Sources */, + DCFACAEB22D826C5004D6D7A /* Result+ErrorGettable.swift in Sources */, DC413D23223B191300000480 /* QLCommon.swift in Sources */, DC6FAF5E222F4EF5008BB070 /* QLAnchor.swift in Sources */, DC374A412231F361006F1272 /* QLoopIteratorContinueNil.swift in Sources */, @@ -764,6 +771,7 @@ DCA1FD202230C8DB006015BD /* QLSegment.swift in Sources */, DC374A342231F2AD006F1272 /* QLoopIteratorContinueNilMax.swift in Sources */, DCA1FD0D22303D22006015BD /* QLoop.swift in Sources */, + DCFACAEC22D826C5004D6D7A /* Result+ErrorGettable.swift in Sources */, DC413D24223B191300000480 /* QLCommon.swift in Sources */, DC6FAF5F222F4EF5008BB070 /* QLAnchor.swift in Sources */, DC374A3E2231F361006F1272 /* QLoopIteratorContinueNil.swift in Sources */, @@ -788,6 +796,7 @@ DCA1FD212230C8DB006015BD /* QLSegment.swift in Sources */, DC374A352231F2AD006F1272 /* QLoopIteratorContinueNilMax.swift in Sources */, DCA1FD0E22303D22006015BD /* QLoop.swift in Sources */, + DCFACAED22D826C5004D6D7A /* Result+ErrorGettable.swift in Sources */, DC413D25223B191300000480 /* QLCommon.swift in Sources */, DC6FAF60222F4EF5008BB070 /* QLAnchor.swift in Sources */, DC374A3F2231F361006F1272 /* QLoopIteratorContinueNil.swift in Sources */, @@ -812,6 +821,7 @@ DCA1FD222230C8DB006015BD /* QLSegment.swift in Sources */, DC374A362231F2AD006F1272 /* QLoopIteratorContinueNilMax.swift in Sources */, DCA1FD0F22303D22006015BD /* QLoop.swift in Sources */, + DCFACAEE22D826C5004D6D7A /* Result+ErrorGettable.swift in Sources */, DC413D26223B191300000480 /* QLCommon.swift in Sources */, DC6FAF61222F4EF5008BB070 /* QLAnchor.swift in Sources */, DC374A402231F361006F1272 /* QLoopIteratorContinueNil.swift in Sources */, diff --git a/Sources/QLoop/Common/QLCommon.swift b/Sources/QLoop/Common/QLCommon.swift index 913794d..0339917 100644 --- a/Sources/QLoop/Common/QLCommon.swift +++ b/Sources/QLoop/Common/QLCommon.swift @@ -11,6 +11,8 @@ public struct QLCommon { return false #endif }() + + public static var autoThrowResultFailures: Bool = true } } diff --git a/Sources/QLoop/QLAnchor.swift b/Sources/QLoop/QLAnchor.swift index c64595c..4564d53 100644 --- a/Sources/QLoop/QLAnchor.swift +++ b/Sources/QLoop/QLAnchor.swift @@ -8,7 +8,8 @@ public final class QLAnchor: AnyAnchor { public typealias OnChange = (Input?)->() public typealias OnError = (Error)->() - lazy var inputQueue = DispatchQueue(label: "\(self).inputQueue") + lazy var inputQueue = DispatchQueue(label: "\(self).inputQueue", + qos: .userInitiated) public required init(onChange: @escaping OnChange, onError: @escaping OnError) { @@ -24,8 +25,14 @@ public final class QLAnchor: AnyAnchor { } set { inputQueue.sync { self._value = newValue } - DispatchQueue.main.async { - self.onChange(newValue) + if QLCommon.Config.Anchor.autoThrowResultFailures, + let errGettable = newValue as? ErrorGettable, + let err = errGettable.getError() { + self.error = err + } else { + DispatchQueue.main.async { + self.onChange(newValue) + } } if (QLCommon.Config.Anchor.releaseValues) { diff --git a/Sources/QLoop/Result+ErrorGettable.swift b/Sources/QLoop/Result+ErrorGettable.swift new file mode 100644 index 0000000..400e96c --- /dev/null +++ b/Sources/QLoop/Result+ErrorGettable.swift @@ -0,0 +1,12 @@ +internal protocol ErrorGettable { + func getError() -> Error? +} + +extension Result: ErrorGettable { + func getError() -> Error? { + if case let .failure(err) = self { + return err + } + return nil + } +} diff --git a/Tests/QLoopTests/QLAnchorTests.swift b/Tests/QLoopTests/QLAnchorTests.swift index e539ca5..22b1b0e 100644 --- a/Tests/QLoopTests/QLAnchorTests.swift +++ b/Tests/QLoopTests/QLAnchorTests.swift @@ -21,21 +21,48 @@ final class QLAnchorTests: XCTestCase { func test_when_input_set_then_it_invokes_onChange() { var received: Int = -1 let expect = expectation(description: "should set") - let subject = QLAnchor(onChange: { received = $0!; expect.fulfill() }) + subject.value = 99 wait(for: [expect], timeout: 8.0) XCTAssertEqual(received, 99) } + func test_when_input_set_is_result_error_then_it_invokes_onError_and_not_onChange() { + var receivedInput: Result? = nil + var receivedError: Error? = nil + let expect = expectation(description: "should error") + let subject = QLAnchor>(onChange: { receivedInput = $0; expect.fulfill() }, + onError: { receivedError = $0; expect.fulfill() }) + + subject.value = .failure(QLCommon.Error.Unknown) + + wait(for: [expect], timeout: 8.0) + XCTAssertNil(receivedInput) + XCTAssertNotNil(receivedError) + } + + func test_when_input_set_is_result_value_then_it_invokes_onChange_and_not_onError_like_normal() { + var receivedInput: Result? = nil + var receivedError: Error? = nil + let expect = expectation(description: "should value") + let subject = QLAnchor>(onChange: { receivedInput = $0; expect.fulfill() }, + onError: { receivedError = $0; expect.fulfill() }) + + subject.value = .success(11) + + wait(for: [expect], timeout: 8.0) + XCTAssertNotNil(receivedInput) + XCTAssertNil(receivedError) + } + func test_when_error_set_then_it_invokes_onError() { var receivedError: Error? = nil let expect = expectation(description: "should set") - let subject = QLAnchor(onChange: { _ in }, onError: { receivedError = $0; expect.fulfill() }) - subject.onChange(nil) + subject.error = QLCommon.Error.Unknown wait(for: [expect], timeout: 8.0) @@ -45,10 +72,9 @@ final class QLAnchorTests: XCTestCase { func test_when_error_set_nil_then_it_invokes_onError_with_ErrorThrownButNotSet() { var receivedError: Error? = nil let expect = expectation(description: "should set") - let subject = QLAnchor(onChange: { _ in }, onError: { receivedError = $0; expect.fulfill() }) - subject.onChange(nil) + subject.error = nil wait(for: [expect], timeout: 8.0)