Skip to content

Commit

Permalink
Merge pull request #5 from 0xLeif/develop
Browse files Browse the repository at this point in the history
0.3.0 Release
  • Loading branch information
0xLeif authored Mar 3, 2021
2 parents e123195 + dc6c164 commit e693d4d
Show file tree
Hide file tree
Showing 3 changed files with 191 additions and 65 deletions.
9 changes: 7 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,14 @@ let package = Package(
name: "Chain",
dependencies: [
"E"
]),
]
),
.testTarget(
name: "ChainTests",
dependencies: ["Chain"]),
dependencies: [
"E",
"Chain"
]
),
]
)
101 changes: 77 additions & 24 deletions Sources/Chain/Chain.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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))"} ?? ""):"
}

return output
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")
}
}
}
}
146 changes: 107 additions & 39 deletions Tests/ChainTests/ChainTests.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import XCTest
import E
@testable import Chain

final class ChainTests: XCTestCase {
Expand All @@ -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!")

Expand All @@ -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()
Expand All @@ -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)
]
}

0 comments on commit e693d4d

Please sign in to comment.