Signal-iOS/SignalServiceKit/tests/Util/ChainedPromiseTest.swift
Harry 7ee39eef63
Add SystemStoryManager
* Add OnboardingStoryManager

* mark onboarding story viewed

* Add tests and fix issues that came up from testing

* up test timeout for slower CI

* rename SystemStoryManager and put into dependency injecton container

* Use viewed state on StoryMessage itself. Have SystemStoryManager observe app lifecyle events to automatically manage the onboarding story

* use iOS assets which are now in s3

* todo cleanup

* increment timestamp for uniqueness

* pr comments

* change literal delimiter

* Add ChainedPromise utility, tests, and use in SystemStoryManager

* discretionarily observe app backgrounding in SystemStoryManager

* renaming from PR comments
2022-08-30 14:49:59 -07:00

126 lines
4.1 KiB
Swift

//
// Copyright (c) 2022 Open Whisper Systems. All rights reserved.
//
import Foundation
import XCTest
@testable import SignalServiceKit
public class ChainedPromiseTest: SSKBaseTestSwift {
func testChainSingleVoidPromise() throws {
let chainedPromise = ChainedPromise<Void>()
let promise = chainedPromise.enqueue {
return .value(())
}
expectSuccess(promise, description: "", timeout: 0.1)
}
func testChainSingleValuePromise() throws {
let chainedPromise = ChainedPromise<String>(initialValue: "")
let promise = chainedPromise.enqueue(recoverValue: "fail") { _ in
.value("hello")
}
let value = expectSuccess(promise, description: "", timeout: 0.1)
XCTAssertEqual(value, "hello")
}
func testChainingPromiseSuccess() throws {
let chainedPromise = ChainedPromise<Void>()
let (firstPromise, firstFuture) = Promise<Void>.pending()
_ = chainedPromise.enqueue {
return firstPromise
}
let failIfExecuteSecondPromise = AtomicBool(true)
let (secondPromise, secondFuture) = Promise<Void>.pending()
let secondResultPromise = chainedPromise.enqueue {
XCTAssertFalse(failIfExecuteSecondPromise.get())
return secondPromise
}
failIfExecuteSecondPromise.set(false)
firstFuture.resolve(())
secondFuture.resolve(())
expectSuccess(secondResultPromise, description: "", timeout: 0.1)
}
func testChainingPromiseFailure() throws {
let chainedPromise = ChainedPromise<Void>()
let (firstPromise, firstFuture) = Promise<Void>.pending()
let firstResultPromise = chainedPromise.enqueue {
return firstPromise
}
let failIfExecuteSecondPromise = AtomicBool(true)
let (secondPromise, secondFuture) = Promise<Void>.pending()
let secondResultPromise = chainedPromise.enqueue {
XCTAssertFalse(failIfExecuteSecondPromise.get())
return secondPromise
}
failIfExecuteSecondPromise.set(false)
firstFuture.resolve(with: Promise<Void>.init(error: NSError()))
secondFuture.resolve(())
expectFailure(firstResultPromise, description: "first result failure", timeout: 0.1)
expectSuccess(secondResultPromise, description: "", timeout: 0.1)
}
func testChainingPromiseChainedValue() throws {
let chainedPromise = ChainedPromise<Int>(initialValue: 1)
let (firstPromise, firstFuture) = Promise<Int>.pending()
_ = chainedPromise.enqueue(recoverValue: -1) {
XCTAssertEqual($0, 1)
return firstPromise
}
let (secondPromise, secondFuture) = Promise<Int>.pending()
let secondResultPromise = chainedPromise.enqueue(recoverValue: -1) {
XCTAssertEqual($0, 2)
return secondPromise
}
firstFuture.resolve(2)
secondFuture.resolve(3)
XCTAssertEqual(expectSuccess(secondResultPromise, description: "", timeout: 0.1), 3)
}
func testChainingPromiseLongChain() throws {
let chainedPromise = ChainedPromise<Void>()
// Set an initial promise to gate the others
let (firstPromise, firstFuture) = Promise<Void>.pending()
let firstResultPromise = chainedPromise.enqueue {
return firstPromise
}
let hasResolvedUpTo = AtomicUInt(0)
var pendingFutures = [Future<Void>]()
var resultPromises = [Promise<Void>]()
(1...10).forEach { i in
let (promise, future) = Promise<Void>.pending()
resultPromises.append(chainedPromise.enqueue {
XCTAssertEqual(hasResolvedUpTo.get(), UInt(i - 1))
return promise
})
pendingFutures.append(future)
}
firstFuture.resolve(())
expectSuccess(firstResultPromise, description: "initial", timeout: 0.1)
pendingFutures.enumerated().forEach { i, future in
hasResolvedUpTo.set(UInt(i + 1))
future.resolve(())
expectSuccess(resultPromises[i], description: "\(i)-th promise", timeout: 0.1)
}
}
}