Merge pull request #5 from 0xLeif/develop

0.3.0 Release
This commit is contained in:
Zach Eriksen 2021-03-02 20:36:53 -06:00 committed by GitHub
commit e693d4dcc8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 192 additions and 66 deletions

View File

@ -23,9 +23,14 @@ let package = Package(
name: "Chain",
dependencies: [
"E"
]),
]
),
.testTarget(
name: "ChainTests",
dependencies: ["Chain"]),
dependencies: [
"E",
"Chain"
]
),
]
)

View File

@ -13,62 +13,115 @@ public extension Chain {
func run(
name: String? = nil,
input: Variable? = nil,
shouldFlattenOutput: Bool = false
logging: Bool = false
) -> Variable {
var logInfo: String {
"[\(Date())] Chain\(name.map { " (\($0)) "} ?? ""):"
}
var output: Variable = .array([])
log(functionName: "run",
name: name,
logging: logging)
switch self {
case .end:
print("\(logInfo) End")
output = output.update {
.array($0 + [Variable.void])
}
case .complete(let completion):
print("\(logInfo) Complete")
output = output.update {
.array($0 + [completion?.run(input) ?? Variable.void])
}
case .link(let action,
let next):
print("\(logInfo) Link")
let actionOutput: Variable = action.run(input) ?? Variable.void
output = output.update {
.array($0 + [actionOutput] + [next.run(name: name, input: actionOutput)])
.array($0 + [actionOutput] + [next.run(name: name,
input: actionOutput,
logging: logging)])
}
case .background(let action,
let next):
print("\(logInfo) Background")
DispatchQueue.global().async {
let actionOutput: Variable = action.run(input) ?? Variable.void
output = output.update {
.array($0 + [actionOutput])
}
DispatchQueue.main.async {
output = output.update {
.array($0 + [next.run(name: name, input: actionOutput)])
}
_ = next.run(name: name,
input: actionOutput,
logging: logging)
}
}
case .multi(let links):
print("\(logInfo) Multi")
output = output.update {
.array($0 + links.map { $0.run(name: name) })
.array($0 + links.map { $0.run(name: name,
logging: logging) })
}
}
// Flatten Output
if shouldFlattenOutput {
return output.flatten
}
return output
}
func runHead(
name: String? = nil,
input: Variable? = nil,
logging: Bool = false
) -> Variable {
log(functionName: "runHead",
name: name,
logging: logging)
switch self {
case .end:
return .void
case .complete(let function):
return function?.run(input) ?? .void
case .background(let function, _):
return Chain.background(function, .end).run(name: name, input: input, logging: logging)
case .link(let function, _):
return function.run(input) ?? .void
case .multi(let chains):
return .array(chains.compactMap { $0.runHead(input: input) })
}
}
func dropHead() -> Chain? {
switch self {
case .end, .complete(_):
return nil
case .background(_, let next), .link(_, let next):
return next
case .multi(let chains):
guard !chains.isEmpty else {
return nil
}
return .multi(chains.compactMap { $0.dropHead() })
}
}
}
internal extension Chain {
func log(
functionName: String,
name: String?,
logging: Bool
) {
var logInfo: String {
"[\(Date())] Chain.\(functionName)\(name.map { " (\($0))"} ?? ""):"
}
if logging {
switch self {
case .end:
print("\(logInfo) End")
case .complete:
print("\(logInfo) Complete")
case .link:
print("\(logInfo) Link")
case .background:
print("\(logInfo) Background")
case .multi:
print("\(logInfo) Multi")
}
}
}
}

View File

@ -1,4 +1,5 @@
import XCTest
import E
@testable import Chain
final class ChainTests: XCTestCase {
@ -7,39 +8,51 @@ final class ChainTests: XCTestCase {
var isLooping = false
let output = Chain.link(
.void { print(0) },
.out {
print(0)
return 0
},
.link(
.void { print(1) },
.out {
print(1)
return 1
},
.multi(
[
.background(
.void {
print("Loading...")
sleep(5)
sleep(1)
print("Loading Done!")
isLooping = false
},
.complete(.void {
XCTAssertEqual(isLooping, false)
})
.complete(
.out {
XCTAssertEqual(isLooping, false)
return .string("Done Loading")
}
)
),
.link(
.void {
.out {
isLooping = true
while isLooping { }
return .string("Done Looping")
},
.complete(.void {
text = "Hello, World!"
})
.complete(
.out {
text = "Hello, World!"
return "Complete"
}
)
)
]
)
)
)
.run(name: "ChainTests-testExample")
.run(name: "ChainTests-testExample", logging: true)
XCTAssertEqual(text, "Hello, World!")
@ -54,33 +67,41 @@ final class ChainTests: XCTestCase {
func testOutput() {
let output = Chain.link(
.out { "First" },
.link( .in {
print("Value: \($0)")
}, .multi(
[
.multi([
.end,
.end,
.end
]),
.link(.out {
"Link"
}, .link(
.out { "Last" },
.complete(.inout { value in
guard case .string(let value) = value else {
XCTFail()
return .void
}
return .string("\(value) !!!")
})
))
]
))
.link(
.in {
print("Value: \($0)")
},
.multi(
[
.multi(
[
.end,
.end,
.end
]
),
.link(
.out { "Link" },
.link(
.out { "Last" },
.complete(
.inout { value in
guard case .string(let value) = value else {
XCTFail()
return .void
}
return .string("\(value) !!!")
}
)
)
)
]
)
)
)
.run(name: "ChainTests-testOutput", shouldFlattenOutput: true)
.run(name: "ChainTests-testOutput", logging: true)
.flatten
guard case .array(let values) = output else {
XCTFail()
@ -92,7 +113,54 @@ final class ChainTests: XCTestCase {
XCTAssertEqual(values.count, 8)
}
func testChainStep() {
let chain = Chain.link(
.out {
"First"
},
.link(
.inout {
.string("Value: \($0)")
},
.end
)
)
XCTAssertEqual(chain.run(logging: true).flatten, .array([.string("First"), .string("Value: string(\"First\")"), .void]))
XCTAssertEqual(chain.runHead(logging: true), .string("First"))
XCTAssertEqual(chain.dropHead()?.runHead(input: .float(3.14), logging: true), .string("Value: float(3.14)"))
}
func testBackgroundOutput() {
let chain = Chain.link(
.out {
"First"
},
.background(
.inout {
sleep(3)
return .string("Value: \($0)")
},
.complete(
.inout {
print("HERE: \($0)")
return "HERE"
}
)
)
)
XCTAssertEqual(chain.run(name: "chain.run", logging: true).flatten, .array([.string("First")]))
XCTAssertEqual(chain.runHead(name: "chain.runHead", logging: true), .string("First"))
XCTAssertEqual(chain.dropHead()?.runHead(name: "chain.dropHead()?.runHead", input: .float(3.14), logging: true), .array([]))
sleep(6)
}
static var allTests = [
("testExample", testExample),
("testOutput", testOutput),
("testChainStep", testChainStep),
("testBackgroundOutput", testBackgroundOutput)
]
}