Skip to content
This repository has been archived by the owner on Aug 29, 2022. It is now read-only.

Commit

Permalink
Merge pull request #202 from bignerdranch/zwaldowski/sad-playground
Browse files Browse the repository at this point in the history
Remove playground descriptions, improve reflection
  • Loading branch information
zwaldowski committed Apr 2, 2018
2 parents 3dcbe4e + fe45996 commit fbc7cd5
Show file tree
Hide file tree
Showing 5 changed files with 170 additions and 36 deletions.
27 changes: 12 additions & 15 deletions Sources/Deferred/Future.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public typealias PreferredExecutor = DispatchQueue
/// access, though ideally all members of the future could be called from any
/// thread.
///
public protocol FutureProtocol: CustomDebugStringConvertible, CustomReflectable, CustomPlaygroundQuickLookable {
public protocol FutureProtocol: CustomDebugStringConvertible, CustomReflectable {
/// A type that represents the result of some asynchronous operation.
associatedtype Value

Expand Down Expand Up @@ -136,31 +136,28 @@ extension FutureProtocol {
extension FutureProtocol {
/// A textual representation of this instance, suitable for debugging.
public var debugDescription: String {
var ret = "\(Self.self)"
if Value.self == Void.self && isFilled {
ret += " (filled)"
var ret = ""
ret.append(contentsOf: "\(Self.self)".prefix(while: { $0 != "<" }))
ret.append("(")
if Value.self == Void.self, isFilled {
ret.append("filled")
} else if let value = peek() {
ret += "(\(String(reflecting: value)))"
debugPrint(value, terminator: "", to: &ret)
} else {
ret += " (not filled)"
ret.append("not filled")
}
ret.append(")")
return ret
}

/// Return the `Mirror` for `self`.
public var customMirror: Mirror {
switch peek() {
case let value? where Value.self != Void.self:
if Value.self != Void.self, let value = peek() {
return Mirror(self, children: [ "value": value ], displayStyle: .optional)
case let value:
return Mirror(self, children: [ "isFilled": value != nil ], displayStyle: .tuple)
} else {
return Mirror(self, children: [ "isFilled": peek() != nil ], displayStyle: .tuple)
}
}

/// A custom playground Quick Look for this instance.
public var customPlaygroundQuickLook: PlaygroundQuickLook {
return PlaygroundQuickLook(reflecting: peek() as Any)
}
}

extension FutureProtocol {
Expand Down
21 changes: 11 additions & 10 deletions Sources/Deferred/Protected.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,20 +37,21 @@ public final class Protected<T> {
}
}

extension Protected: CustomDebugStringConvertible, CustomReflectable, CustomPlaygroundQuickLookable {
extension Protected: CustomDebugStringConvertible, CustomReflectable {
public var debugDescription: String {
return lock.withAttemptedReadLock {
"\(type(of: self))(\(String(reflecting: unsafeValue)))"
} ?? "\(type(of: self)) (lock contended)"
var ret = "Protected("
if lock.withAttemptedReadLock({
debugPrint(unsafeValue, terminator: "", to: &ret)
}) == nil {
ret.append("locked")
}
ret.append(")")
return ret
}

public var customMirror: Mirror {
return lock.withAttemptedReadLock {
Mirror(self, children: [ "item": unsafeValue ], displayStyle: .optional)
} ?? Mirror(self, children: [ "lockContended": true ], displayStyle: .tuple)
}

public var customPlaygroundQuickLook: PlaygroundQuickLook {
return PlaygroundQuickLook(reflecting: lock.withAttemptedReadLock({ unsafeValue }) as Any)
Mirror(self, unlabeledChildren: [ unsafeValue ], displayStyle: .optional)
} ?? Mirror(self, children: [ "locked": true ], displayStyle: .tuple)
}
}
50 changes: 49 additions & 1 deletion Tests/DeferredTests/DeferredTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,13 @@ class DeferredTests: XCTestCase {
("testIsFilledCanBeCalledMultipleTimesNotFilled", testIsFilledCanBeCalledMultipleTimesNotFilled),
("testIsFilledCanBeCalledMultipleTimesWhenFilled", testIsFilledCanBeCalledMultipleTimesWhenFilled),
("testFillAndIsFilledPostcondition", testFillAndIsFilledPostcondition),
("testSimultaneousFill", testSimultaneousFill)
("testSimultaneousFill", testSimultaneousFill),
("testDebugDescriptionUnfilled", testDebugDescriptionUnfilled),
("testDebugDescriptionFilled", testDebugDescriptionFilled),
("testDebugDescriptionFilledWhenValueIsVoid", testDebugDescriptionFilledWhenValueIsVoid),
("testReflectionUnfilled", testReflectionUnfilled),
("testReflectionFilled", testReflectionFilled),
("testReflectionFilledWhenValueIsVoid", testReflectionFilledWhenValueIsVoid)
]

#if os(OSX) || (os(iOS) && !(arch(i386) || arch(x86_64))) || (os(watchOS) && !(arch(i386) || arch(x86_64))) || (os(tvOS) && !arch(x86_64))
Expand Down Expand Up @@ -371,6 +377,48 @@ class DeferredTests: XCTestCase {
XCTAssertEqual(finishGroup.wait(timeout: .distantFuture), .success)
waitForExpectationsShort()
}

func testDebugDescriptionUnfilled() {
let deferred = Deferred<Int>()
XCTAssertEqual("\(deferred)", "Deferred(not filled)")
}

func testDebugDescriptionFilled() {
let deferred = Deferred<Int>(filledWith: 42)
XCTAssertEqual("\(deferred)", "Deferred(42)")
}

func testDebugDescriptionFilledWhenValueIsVoid() {
let deferred = Deferred<Void>(filledWith: ())
XCTAssertEqual("\(deferred)", "Deferred(filled)")
}

func testReflectionUnfilled() {
let deferred = Deferred<Int>()

let magicMirror = Mirror(reflecting: deferred)
XCTAssertEqual(magicMirror.displayStyle, .tuple)
XCTAssertNil(magicMirror.superclassMirror)
XCTAssertEqual(magicMirror.descendant("isFilled") as? Bool, false)
}

func testReflectionFilled() {
let deferred = Deferred<Int>(filledWith: 42)

let magicMirror = Mirror(reflecting: deferred)
XCTAssertEqual(magicMirror.displayStyle, .optional)
XCTAssertNil(magicMirror.superclassMirror)
XCTAssertEqual(magicMirror.descendant(0) as? Int, 42)
}

func testReflectionFilledWhenValueIsVoid() {
let deferred = Deferred<Void>(filledWith: ())

let magicMirror = Mirror(reflecting: deferred)
XCTAssertEqual(magicMirror.displayStyle, .tuple)
XCTAssertNil(magicMirror.superclassMirror)
XCTAssertEqual(magicMirror.descendant("isFilled") as? Bool, true)
}
}

// swiftlint:enable type_body_length
64 changes: 55 additions & 9 deletions Tests/DeferredTests/ExistentialFutureTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,19 @@ import XCTest
@testable import Deferred

class ExistentialFutureTests: XCTestCase {
static var allTests: [(String, (ExistentialFutureTests) -> () throws -> Void)] {
return [
("testFilledAnyFutureWaitAlwaysReturns", testFilledAnyFutureWaitAlwaysReturns),
("testAnyWaitWithTimeout", testAnyWaitWithTimeout),
("testFilledAnyFutureUpon", testFilledAnyFutureUpon),
("testUnfilledAnyUponCalledWhenFilled", testUnfilledAnyUponCalledWhenFilled),
("testFillAndIsFilledPostcondition", testFillAndIsFilledPostcondition)
]
}
static let allTests: [(String, (ExistentialFutureTests) -> () throws -> Void)] = [
("testFilledAnyFutureWaitAlwaysReturns", testFilledAnyFutureWaitAlwaysReturns),
("testAnyWaitWithTimeout", testAnyWaitWithTimeout),
("testFilledAnyFutureUpon", testFilledAnyFutureUpon),
("testUnfilledAnyUponCalledWhenFilled", testUnfilledAnyUponCalledWhenFilled),
("testFillAndIsFilledPostcondition", testFillAndIsFilledPostcondition),
("testDebugDescriptionUnfilled", testDebugDescriptionUnfilled),
("testDebugDescriptionFilled", testDebugDescriptionFilled),
("testDebugDescriptionFilledWhenValueIsVoid", testDebugDescriptionFilledWhenValueIsVoid),
("testReflectionUnfilled", testReflectionUnfilled),
("testReflectionFilled", testReflectionFilled),
("testReflectionFilledWhenValueIsVoid", testReflectionFilledWhenValueIsVoid)
]

var anyFuture: Future<Int>!

Expand Down Expand Up @@ -92,4 +96,46 @@ class ExistentialFutureTests: XCTestCase {
XCTAssertNotNil(anyFuture.wait(until: .now()))
XCTAssertNotNil(anyFuture.waitShort()) // pass
}

func testDebugDescriptionUnfilled() {
let future = Future<Int>()
XCTAssertEqual("\(future)", "Future(not filled)")
}

func testDebugDescriptionFilled() {
let future = Future<Int>(value: 42)
XCTAssertEqual("\(future)", "Future(42)")
}

func testDebugDescriptionFilledWhenValueIsVoid() {
let future = Future<Void>(value: ())
XCTAssertEqual("\(future)", "Future(filled)")
}

func testReflectionUnfilled() {
let future = Future<Int>()

let magicMirror = Mirror(reflecting: future)
XCTAssertEqual(magicMirror.displayStyle, .tuple)
XCTAssertNil(magicMirror.superclassMirror)
XCTAssertEqual(magicMirror.descendant("isFilled") as? Bool, false)
}

func testReflectionFilled() {
let future = Future<Int>(value: 42)

let magicMirror = Mirror(reflecting: future)
XCTAssertEqual(magicMirror.displayStyle, .optional)
XCTAssertNil(magicMirror.superclassMirror)
XCTAssertEqual(magicMirror.descendant(0) as? Int, 42)
}

func testReflectionFilledWhenValueIsVoid() {
let future = Future<Void>(value: ())

let magicMirror = Mirror(reflecting: future)
XCTAssertEqual(magicMirror.displayStyle, .tuple)
XCTAssertNil(magicMirror.superclassMirror)
XCTAssertEqual(magicMirror.descendant("isFilled") as? Bool, true)
}
}
44 changes: 43 additions & 1 deletion Tests/DeferredTests/ProtectedTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ import Foundation
class ProtectedTests: XCTestCase {
static var allTests: [(String, (ProtectedTests) -> () throws -> Void)] {
return [
("testConcurrentReadingWriting", testConcurrentReadingWriting)
("testConcurrentReadingWriting", testConcurrentReadingWriting),
("testDebugDescription", testDebugDescription),
("testDebugDescriptionWhenLocked", testDebugDescriptionWhenLocked),
("testReflection", testReflection),
("testReflectionWhenLocked", testReflectionWhenLocked)
]
}

Expand Down Expand Up @@ -75,4 +79,42 @@ class ProtectedTests: XCTestCase {

waitForExpectationsShort()
}

func testDebugDescription() {
let protected = Protected<Int>(initialValue: 42)
XCTAssertEqual("\(protected)", "Protected(42)")
}

func testDebugDescriptionWhenLocked() {
let customLock = NSLock()
let protected = Protected<Int>(initialValue: 42, lock: customLock)

customLock.lock()
defer { customLock.unlock() }

XCTAssertEqual("\(protected)", "Protected(locked)")
}

func testReflection() {
let protected = Protected<Int>(initialValue: 42)

let magicMirror = Mirror(reflecting: protected)
XCTAssertEqual(magicMirror.displayStyle, .optional)
XCTAssertNil(magicMirror.superclassMirror)
XCTAssertEqual(magicMirror.descendant(0) as? Int, 42)
}

func testReflectionWhenLocked() {
let customLock = NSLock()
let protected = Protected<Int>(initialValue: 42, lock: customLock)

customLock.lock()
defer { customLock.unlock() }

let magicMirror = Mirror(reflecting: protected)
XCTAssertEqual(magicMirror.displayStyle, .tuple)
XCTAssertNil(magicMirror.superclassMirror)
XCTAssertEqual(magicMirror.descendant("locked") as? Bool, true)
}

}

0 comments on commit fbc7cd5

Please sign in to comment.