This commit is contained in:
Quentin Jin 2019-04-06 10:43:19 +08:00
parent a3fdd633a6
commit 328439049a
7 changed files with 40 additions and 44 deletions

View File

@ -282,12 +282,12 @@ extension Plan {
public static func after(_ delay: Interval) -> Plan { public static func after(_ delay: Interval) -> Plan {
return Plan.of(delay) return Plan.of(delay)
} }
/// Creates a plan that executes the task after the given interval then repeat the execution. /// Creates a plan that executes the task after the given interval then repeat the execution.
public static func after(_ delay: Interval, repeating interval: Interval) -> Plan { public static func after(_ delay: Interval, repeating interval: Interval) -> Plan {
return Plan.after(delay).concat(Plan.every(interval)) return Plan.after(delay).concat(Plan.every(interval))
} }
/// Creates a plan that executes the task at the given date. /// Creates a plan that executes the task at the given date.
public static func at(_ date: Date) -> Plan { public static func at(_ date: Date) -> Plan {
return Plan.of(date) return Plan.of(date)

View File

@ -7,7 +7,7 @@ public struct ActionKey {
} }
extension BagKey { extension BagKey {
fileprivate func asActionKey() -> ActionKey { fileprivate func asActionKey() -> ActionKey {
return ActionKey(bagKey: self) return ActionKey(bagKey: self)
} }
@ -30,24 +30,24 @@ open class Task {
private lazy var _suspensionCount: UInt64 = 0 private lazy var _suspensionCount: UInt64 = 0
private lazy var _executionCount: Int = 0 private lazy var _executionCount: Int = 0
private var _firstExecutionDate: Date? private var _firstExecutionDate: Date?
private var _lastExecutionDate: Date? private var _lastExecutionDate: Date?
private var _estimatedNextExecutionDate: Date? private var _estimatedNextExecutionDate: Date?
/// The date of creation. /// The date of creation.
public let creationDate = Date() public let creationDate = Date()
/// The date of first execution. /// The date of first execution.
open var firstExecutionDate: Date? { open var firstExecutionDate: Date? {
return _lock.withLock { _firstExecutionDate } return _lock.withLock { _firstExecutionDate }
} }
/// The date of last execution. /// The date of last execution.
open var lastExecutionDate: Date? { open var lastExecutionDate: Date? {
return _lock.withLock { _lastExecutionDate } return _lock.withLock { _lastExecutionDate }
} }
/// The date of estimated next execution. /// The date of estimated next execution.
open var estimatedNextExecutionDate: Date? { open var estimatedNextExecutionDate: Date? {
return _lock.withLock { _estimatedNextExecutionDate } return _lock.withLock { _estimatedNextExecutionDate }
@ -111,7 +111,7 @@ open class Task {
_timer.schedule(after: interval) _timer.schedule(after: interval)
_estimatedNextExecutionDate = Date().adding(interval) _estimatedNextExecutionDate = Date().adding(interval)
} }
_timer.resume() _timer.resume()
TaskCenter.default.add(self) TaskCenter.default.add(self)
@ -127,7 +127,7 @@ open class Task {
taskCenter?.remove(self) taskCenter?.remove(self)
} }
private func elapse() { private func elapse() {
scheduleNextExecution() scheduleNextExecution()
execute() execute()
@ -230,7 +230,6 @@ open class Task {
TaskCenter.default.remove(self) TaskCenter.default.remove(self)
} }
// MARK: - Action // MARK: - Action
/// The number of actions in this task. /// The number of actions in this task.

View File

@ -78,6 +78,6 @@ extension DispatchQueue {
} }
extension TimeZone { extension TimeZone {
static let shanghai = TimeZone(identifier: "Asia/Shanghai")! static let shanghai = TimeZone(identifier: "Asia/Shanghai")!
} }

View File

@ -4,7 +4,6 @@ import XCTest
final class MonthdayTests: XCTestCase { final class MonthdayTests: XCTestCase {
func testIs() { func testIs() {
// ! Be careful the time zone problem.
let d = Date(year: 2019, month: 1, day: 1) let d = Date(year: 2019, month: 1, day: 1)
XCTAssertTrue(d.is(.january(1), in: TimeZone.shanghai)) XCTAssertTrue(d.is(.january(1), in: TimeZone.shanghai))
} }

View File

@ -4,43 +4,42 @@ import XCTest
final class PlanTests: XCTestCase { final class PlanTests: XCTestCase {
private let leeway = 0.01.seconds private let leeway = 0.01.seconds
func testOfIntervals() { func testOfIntervals() {
let ints = [1.second, 2.hours, 3.days, 4.weeks] let ints = [1.second, 2.hours, 3.days, 4.weeks]
let p = Plan.of(ints) let p = Plan.of(ints)
XCTAssertTrue(p.makeIterator().isAlmostEqual(to: ints, leeway: leeway)) XCTAssertTrue(p.makeIterator().isAlmostEqual(to: ints, leeway: leeway))
} }
func testOfDates() { func testOfDates() {
let ints = [1.second, 2.hours, 3.days, 4.weeks] let ints = [1.second, 2.hours, 3.days, 4.weeks]
let d0 = Date() + ints[0] let d0 = Date() + ints[0]
let d1 = d0 + ints[1] let d1 = d0 + ints[1]
let d2 = d1 + ints[2] let d2 = d1 + ints[2]
let d3 = d2 + ints[3] let d3 = d2 + ints[3]
let p = Plan.of(d0, d1, d2, d3) let p = Plan.of(d0, d1, d2, d3)
XCTAssertTrue(p.makeIterator().isAlmostEqual(to: ints, leeway: leeway)) XCTAssertTrue(p.makeIterator().isAlmostEqual(to: ints, leeway: leeway))
} }
func testDates() { func testDates() {
let dates = Plan.of(1.days, 2.weeks).dates.makeIterator() let dates = Plan.of(1.days, 2.weeks).dates.makeIterator()
var n = dates.next() var n = dates.next()
XCTAssertNotNil(n) XCTAssertNotNil(n)
XCTAssertTrue(n!.intervalSinceNow.isAlmostEqual(to: 1.days, leeway: leeway)) XCTAssertTrue(n!.intervalSinceNow.isAlmostEqual(to: 1.days, leeway: leeway))
n = dates.next() n = dates.next()
XCTAssertNotNil(n) XCTAssertNotNil(n)
XCTAssertTrue(n!.intervalSinceNow.isAlmostEqual(to: 2.weeks + 1.days, leeway: leeway)) XCTAssertTrue(n!.intervalSinceNow.isAlmostEqual(to: 2.weeks + 1.days, leeway: leeway))
} }
func testDistant() { func testDistant() {
let distantPast = Plan.distantPast.makeIterator().next() let distantPast = Plan.distantPast.makeIterator().next()
XCTAssertNotNil(distantPast) XCTAssertNotNil(distantPast)
XCTAssertTrue(distantPast!.isAlmostEqual(to: Date.distantPast.intervalSinceNow, leeway: leeway)) XCTAssertTrue(distantPast!.isAlmostEqual(to: Date.distantPast.intervalSinceNow, leeway: leeway))
let distantFuture = Plan.distantFuture.makeIterator().next() let distantFuture = Plan.distantFuture.makeIterator().next()
XCTAssertNotNil(distantFuture) XCTAssertNotNil(distantFuture)
XCTAssertTrue(distantFuture!.isAlmostEqual(to: Date.distantFuture.intervalSinceNow, leeway: leeway)) XCTAssertTrue(distantFuture!.isAlmostEqual(to: Date.distantFuture.intervalSinceNow, leeway: leeway))
@ -65,7 +64,7 @@ final class PlanTests: XCTestCase {
let p1 = Plan.of(1.second, 1.second, 1.minutes, 1.seconds, 58.seconds, 1.hour) let p1 = Plan.of(1.second, 1.second, 1.minutes, 1.seconds, 58.seconds, 1.hour)
XCTAssertTrue(p0.isAlmostEqual(to: p1, leeway: leeway)) XCTAssertTrue(p0.isAlmostEqual(to: p1, leeway: leeway))
} }
func testFirst() { func testFirst() {
var count = 10 var count = 10
let p = Plan.every(1.second).first(count) let p = Plan.every(1.second).first(count)
@ -76,7 +75,7 @@ final class PlanTests: XCTestCase {
} }
XCTAssertNil(i.next()) XCTAssertNil(i.next())
} }
func testUntil() { func testUntil() {
let until = Date() + 10.seconds let until = Date() + 10.seconds
let p = Plan.every(1.second).until(until).dates let p = Plan.every(1.second).until(until).dates
@ -91,7 +90,7 @@ final class PlanTests: XCTestCase {
let p1 = Plan.of(Date()) let p1 = Plan.of(Date())
XCTAssertTrue(p0.isAlmostEqual(to: p1, leeway: leeway)) XCTAssertTrue(p0.isAlmostEqual(to: p1, leeway: leeway))
} }
func testAt() { func testAt() {
let p = Plan.at(Date() + 1.second) let p = Plan.at(Date() + 1.second)
let next = p.makeIterator().next() let next = p.makeIterator().next()
@ -136,7 +135,7 @@ final class PlanTests: XCTestCase {
func testOffset() { func testOffset() {
let p1 = Plan.after(1.second).first(100) let p1 = Plan.after(1.second).first(100)
let p2 = p1.offset(by: 1.second).first(100) let p2 = p1.offset(by: 1.second).first(100)
for (d1, d2) in zip(p1.dates, p2.dates) { for (d1, d2) in zip(p1.dates, p2.dates) {
XCTAssertTrue(d2.interval(since: d1).isAlmostEqual(to: 1.second, leeway: leeway)) XCTAssertTrue(d2.interval(since: d1).isAlmostEqual(to: 1.second, leeway: leeway))
} }

View File

@ -2,23 +2,23 @@ import XCTest
@testable import Schedule @testable import Schedule
final class TaskTests: XCTestCase { final class TaskTests: XCTestCase {
let leeway = 0.01.second let leeway = 0.01.second
func testMetrics() { func testMetrics() {
let e = expectation(description: "testMetrics") let e = expectation(description: "testMetrics")
let date = Date() let date = Date()
let task = Plan.after(0.01.second, repeating: 0.01.second).do(queue: .global()) { let task = Plan.after(0.01.second, repeating: 0.01.second).do(queue: .global()) {
e.fulfill() e.fulfill()
} }
XCTAssertTrue(task.creationDate.interval(since: date).isAlmostEqual(to: 0.second, leeway: leeway)) XCTAssertTrue(task.creationDate.interval(since: date).isAlmostEqual(to: 0.second, leeway: leeway))
waitForExpectations(timeout: 0.1) waitForExpectations(timeout: 0.1)
XCTAssertNotNil(task.firstExecutionDate) XCTAssertNotNil(task.firstExecutionDate)
XCTAssertTrue(task.firstExecutionDate!.interval(since: date).isAlmostEqual(to: 0.01.second, leeway: leeway)) XCTAssertTrue(task.firstExecutionDate!.interval(since: date).isAlmostEqual(to: 0.01.second, leeway: leeway))
XCTAssertNotNil(task.lastExecutionDate) XCTAssertNotNil(task.lastExecutionDate)
XCTAssertTrue(task.lastExecutionDate!.interval(since: date).isAlmostEqual(to: 0.01.second, leeway: leeway)) XCTAssertTrue(task.lastExecutionDate!.interval(since: date).isAlmostEqual(to: 0.01.second, leeway: leeway))
} }
@ -31,7 +31,7 @@ final class TaskTests: XCTestCase {
e.fulfill() e.fulfill()
} }
waitForExpectations(timeout: 0.1) waitForExpectations(timeout: 0.1)
_ = task _ = task
} }
@ -43,20 +43,20 @@ final class TaskTests: XCTestCase {
if count == 3 { e.fulfill() } if count == 3 { e.fulfill() }
} }
waitForExpectations(timeout: 0.1) waitForExpectations(timeout: 0.1)
_ = task _ = task
} }
func testTaskCenter() { func testTaskCenter() {
let task = Plan.never.do { } let task = Plan.never.do { }
XCTAssertTrue(task.taskCenter === TaskCenter.default) XCTAssertTrue(task.taskCenter === TaskCenter.default)
task.removeFromTaskCenter(TaskCenter()) task.removeFromTaskCenter(TaskCenter())
XCTAssertNotNil(task.taskCenter) XCTAssertNotNil(task.taskCenter)
task.removeFromTaskCenter(task.taskCenter!) task.removeFromTaskCenter(task.taskCenter!)
XCTAssertNil(task.taskCenter) XCTAssertNil(task.taskCenter)
let center = TaskCenter() let center = TaskCenter()
task.addToTaskCenter(center) task.addToTaskCenter(center)
XCTAssertTrue(task.taskCenter === center) XCTAssertTrue(task.taskCenter === center)
@ -71,7 +71,7 @@ final class TaskTests: XCTestCase {
e.fulfill() e.fulfill()
} }
waitForExpectations(timeout: 0.1) waitForExpectations(timeout: 0.1)
_ = task _ = task
} }
@ -100,14 +100,14 @@ final class TaskTests: XCTestCase {
task.resume() task.resume()
XCTAssertEqual(task.suspensionCount, 2) XCTAssertEqual(task.suspensionCount, 2)
} }
func testCancel() { func testCancel() {
let task = Plan.never.do { } let task = Plan.never.do { }
XCTAssertFalse(task.isCancelled) XCTAssertFalse(task.isCancelled)
task.cancel() task.cancel()
XCTAssertTrue(task.isCancelled) XCTAssertTrue(task.isCancelled)
} }
func testExecuteNow() { func testExecuteNow() {
let e = expectation(description: "testExecuteNow") let e = expectation(description: "testExecuteNow")
let task = Plan.never.do { let task = Plan.never.do {
@ -132,7 +132,7 @@ final class TaskTests: XCTestCase {
} }
waitForExpectations(timeout: 1) waitForExpectations(timeout: 1)
} }
func testReschedule() { func testReschedule() {
let e = expectation(description: "testReschedule") let e = expectation(description: "testReschedule")
var i = 0 var i = 0
@ -150,7 +150,7 @@ final class TaskTests: XCTestCase {
} }
waitForExpectations(timeout: 1) waitForExpectations(timeout: 1)
} }
func testAddAndRemoveActions() { func testAddAndRemoveActions() {
let e = expectation(description: "testAddAndRemoveActions") let e = expectation(description: "testAddAndRemoveActions")
let task = Plan.after(0.1.second).do { } let task = Plan.after(0.1.second).do { }

View File

@ -4,7 +4,6 @@ import XCTest
final class WeekdayTests: XCTestCase { final class WeekdayTests: XCTestCase {
func testIs() { func testIs() {
// ! Be careful the time zone problem.
let d = Date(year: 2019, month: 1, day: 1) let d = Date(year: 2019, month: 1, day: 1)
XCTAssertTrue(d.is(.tuesday, in: TimeZone.shanghai)) XCTAssertTrue(d.is(.tuesday, in: TimeZone.shanghai))
} }