Fixed the broken JobRunner tests

Cleaned up the 'isRunningTests' logic so it isn't dependant on having an AppContext
This commit is contained in:
Morgan Pretty 2023-06-20 16:33:06 +10:00
parent fc94d24ddf
commit 0a638bf37b
19 changed files with 90 additions and 177 deletions

View File

@ -342,7 +342,6 @@
C33FDD49255A582000E217F9 /* ParamParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB8F255A581200E217F9 /* ParamParser.swift */; };
C33FDD5B255A582000E217F9 /* OWSOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDBA1255A581400E217F9 /* OWSOperation.h */; settings = {ATTRIBUTES = (Public, ); }; };
C33FDD6E255A582000E217F9 /* NSURLSessionDataTask+StatusCode.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDBB4255A581600E217F9 /* NSURLSessionDataTask+StatusCode.m */; };
C33FDD7C255A582000E217F9 /* SSKAsserts.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDBC2255A581700E217F9 /* SSKAsserts.h */; settings = {ATTRIBUTES = (Public, ); }; };
C33FDD8D255A582000E217F9 /* OWSSignalAddress.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDBD3255A581800E217F9 /* OWSSignalAddress.swift */; };
C33FDD92255A582000E217F9 /* SignalIOS.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDBD8255A581900E217F9 /* SignalIOS.pb.swift */; };
C33FDDB0255A582000E217F9 /* NSURLSessionDataTask+StatusCode.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDBF6255A581C00E217F9 /* NSURLSessionDataTask+StatusCode.h */; settings = {ATTRIBUTES = (Public, ); }; };
@ -831,13 +830,13 @@
FDD2506E283711D600198BDA /* DifferenceKit+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDD2506D283711D600198BDA /* DifferenceKit+Utilities.swift */; };
FDD250702837199200198BDA /* GarbageCollectionJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDD2506F2837199200198BDA /* GarbageCollectionJob.swift */; };
FDD250722837234B00198BDA /* MediaGalleryNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDD250712837234B00198BDA /* MediaGalleryNavigationController.swift */; };
FDDF074A29DAB36900E5E8B5 /* JobRunnerSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDDF074929DAB36900E5E8B5 /* JobRunnerSpec.swift */; };
FDDCBDA829E776BF00303C38 /* seed2-2023-2y.crt in Resources */ = {isa = PBXBuildFile; fileRef = FDDCBDA229E776BF00303C38 /* seed2-2023-2y.crt */; };
FDDCBDA929E776BF00303C38 /* seed1-2023-2y.crt in Resources */ = {isa = PBXBuildFile; fileRef = FDDCBDA329E776BF00303C38 /* seed1-2023-2y.crt */; };
FDDCBDAA29E776BF00303C38 /* seed1-2023-2y.der in Resources */ = {isa = PBXBuildFile; fileRef = FDDCBDA429E776BF00303C38 /* seed1-2023-2y.der */; };
FDDCBDAB29E776BF00303C38 /* seed2-2023-2y.der in Resources */ = {isa = PBXBuildFile; fileRef = FDDCBDA529E776BF00303C38 /* seed2-2023-2y.der */; };
FDDCBDAC29E776BF00303C38 /* seed3-2023-2y.crt in Resources */ = {isa = PBXBuildFile; fileRef = FDDCBDA629E776BF00303C38 /* seed3-2023-2y.crt */; };
FDDCBDAD29E776BF00303C38 /* seed3-2023-2y.der in Resources */ = {isa = PBXBuildFile; fileRef = FDDCBDA729E776BF00303C38 /* seed3-2023-2y.der */; };
FDDF074A29DAB36900E5E8B5 /* JobRunnerSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDDF074929DAB36900E5E8B5 /* JobRunnerSpec.swift */; };
FDE77F6B280FEB28002CFC5D /* ControlMessageProcessRecord.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDE77F6A280FEB28002CFC5D /* ControlMessageProcessRecord.swift */; };
FDED2E3C282E1B5D00B2CD2A /* UICollectionView+ReusableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDED2E3B282E1B5D00B2CD2A /* UICollectionView+ReusableView.swift */; };
FDF0B73C27FFD3D6004C14C5 /* LinkPreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDF0B73B27FFD3D6004C14C5 /* LinkPreview.swift */; };
@ -1446,7 +1445,6 @@
C33FDBB4255A581600E217F9 /* NSURLSessionDataTask+StatusCode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSURLSessionDataTask+StatusCode.m"; sourceTree = "<group>"; };
C33FDBB6255A581600E217F9 /* DataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DataSource.m; sourceTree = "<group>"; };
C33FDBBC255A581600E217F9 /* SSKKeychainStorage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SSKKeychainStorage.swift; sourceTree = "<group>"; };
C33FDBC2255A581700E217F9 /* SSKAsserts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SSKAsserts.h; sourceTree = "<group>"; };
C33FDBD3255A581800E217F9 /* OWSSignalAddress.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OWSSignalAddress.swift; sourceTree = "<group>"; };
C33FDBD8255A581900E217F9 /* SignalIOS.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignalIOS.pb.swift; sourceTree = "<group>"; };
C33FDBDE255A581900E217F9 /* PushNotificationAPI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PushNotificationAPI.swift; sourceTree = "<group>"; };
@ -1919,13 +1917,13 @@
FDD2506D283711D600198BDA /* DifferenceKit+Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DifferenceKit+Utilities.swift"; sourceTree = "<group>"; };
FDD2506F2837199200198BDA /* GarbageCollectionJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GarbageCollectionJob.swift; sourceTree = "<group>"; };
FDD250712837234B00198BDA /* MediaGalleryNavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaGalleryNavigationController.swift; sourceTree = "<group>"; };
FDDF074929DAB36900E5E8B5 /* JobRunnerSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JobRunnerSpec.swift; sourceTree = "<group>"; };
FDDCBDA229E776BF00303C38 /* seed2-2023-2y.crt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "seed2-2023-2y.crt"; sourceTree = "<group>"; };
FDDCBDA329E776BF00303C38 /* seed1-2023-2y.crt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "seed1-2023-2y.crt"; sourceTree = "<group>"; };
FDDCBDA429E776BF00303C38 /* seed1-2023-2y.der */ = {isa = PBXFileReference; lastKnownFileType = file; path = "seed1-2023-2y.der"; sourceTree = "<group>"; };
FDDCBDA529E776BF00303C38 /* seed2-2023-2y.der */ = {isa = PBXFileReference; lastKnownFileType = file; path = "seed2-2023-2y.der"; sourceTree = "<group>"; };
FDDCBDA629E776BF00303C38 /* seed3-2023-2y.crt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "seed3-2023-2y.crt"; sourceTree = "<group>"; };
FDDCBDA729E776BF00303C38 /* seed3-2023-2y.der */ = {isa = PBXFileReference; lastKnownFileType = file; path = "seed3-2023-2y.der"; sourceTree = "<group>"; };
FDDF074929DAB36900E5E8B5 /* JobRunnerSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JobRunnerSpec.swift; sourceTree = "<group>"; };
FDE7214F287E50D50093DF33 /* ProtoWrappers.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = ProtoWrappers.py; sourceTree = "<group>"; };
FDE72150287E50D50093DF33 /* LintLocalizableStrings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LintLocalizableStrings.swift; sourceTree = "<group>"; };
FDE77F68280F9EDA002CFC5D /* JobRunnerError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JobRunnerError.swift; sourceTree = "<group>"; };
@ -3353,7 +3351,6 @@
C33FDB8F255A581200E217F9 /* ParamParser.swift */,
C33FDADE255A580400E217F9 /* SwiftSingletons.swift */,
C33FDB49255A580C00E217F9 /* WeakTimer.swift */,
C33FDBC2255A581700E217F9 /* SSKAsserts.h */,
C33FDA9E255A57FF00E217F9 /* ReverseDispatchQueue.swift */,
C33FDBF6255A581C00E217F9 /* NSURLSessionDataTask+StatusCode.h */,
C33FDBB4255A581600E217F9 /* NSURLSessionDataTask+StatusCode.m */,
@ -4238,7 +4235,6 @@
C33FDDB0255A582000E217F9 /* NSURLSessionDataTask+StatusCode.h in Headers */,
C33FDDD0255A582000E217F9 /* FunctionalUtil.h in Headers */,
C33FDD5B255A582000E217F9 /* OWSOperation.h in Headers */,
C33FDD7C255A582000E217F9 /* SSKAsserts.h in Headers */,
C38EF24C255B6D67007E1867 /* NSAttributedString+OWS.h in Headers */,
C38EF32B255B6DBF007E1867 /* OWSFormat.h in Headers */,
C33FDDCC255A582000E217F9 /* TSConstants.h in Headers */,

View File

@ -84,7 +84,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
}
// No point continuing if we are running tests
guard !CurrentAppContext().isRunningTests else { return true }
guard !SNUtilitiesKit.isRunningTests else { return true }
self.window = mainWindow
CurrentAppContext().mainWindow = mainWindow
@ -156,7 +156,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
}
func applicationDidBecomeActive(_ application: UIApplication) {
guard !CurrentAppContext().isRunningTests else { return }
guard !SNUtilitiesKit.isRunningTests else { return }
UserDefaults.sharedLokiProject?[.isMainAppActive] = true

View File

@ -1,6 +1,7 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import SessionUtilitiesKit
import SignalUtilitiesKit
public class AppEnvironment {
@ -10,7 +11,7 @@ public class AppEnvironment {
public class var shared: AppEnvironment {
get { return _shared }
set {
guard CurrentAppContext().isRunningTests else {
guard SNUtilitiesKit.isRunningTests else {
owsFailDebug("Can only switch environments in tests.")
return
}

View File

@ -61,8 +61,6 @@ NSString *const ReportedApplicationStateDidChangeNotification = @"ReportedApplic
name:UIApplicationWillTerminateNotification
object:nil];
// We can't use OWSSingletonAssert() since it uses the app context.
self.appActiveBlocks = [NSMutableArray new];
return self;
@ -243,11 +241,6 @@ NSString *const ReportedApplicationStateDidChangeNotification = @"ReportedApplic
}];
}
- (BOOL)isRunningTests
{
return (NSProcessInfo.processInfo.environment[@"XCTestConfigurationFilePath"] != nil);
}
- (void)setNetworkActivityIndicatorVisible:(BOOL)value
{
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:value];

View File

@ -10,6 +10,5 @@
#import <SignalCoreKit/NSObject+OWS.h>
#import <SignalCoreKit/OWSAsserts.h>
#import <SignalUtilitiesKit/SSKAsserts.h>
#import <SessionUIKit/SessionUIKit.h>
#endif

View File

@ -13,29 +13,30 @@ public enum GroupLeavingJob: JobExecutor {
public static var requiresInteractionId: Bool = true
public static func run(
_ job: SessionUtilitiesKit.Job,
_ job: Job,
queue: DispatchQueue,
success: @escaping (SessionUtilitiesKit.Job, Bool) -> (),
failure: @escaping (SessionUtilitiesKit.Job, Error?, Bool) -> (),
deferred: @escaping (SessionUtilitiesKit.Job) -> ())
{
success: @escaping (Job, Bool, Dependencies) -> (),
failure: @escaping (Job, Error?, Bool, Dependencies) -> (),
deferred: @escaping (Job, Dependencies) -> (),
dependencies: Dependencies = Dependencies()
) {
guard
let detailsData: Data = job.details,
let details: Details = try? JSONDecoder().decode(Details.self, from: detailsData),
let interactionId: Int64 = job.interactionId
else {
failure(job, JobRunnerError.missingRequiredDetails, true)
failure(job, JobRunnerError.missingRequiredDetails, true, dependencies)
return
}
guard let thread: SessionThread = Storage.shared.read({ db in try? SessionThread.fetchOne(db, id: details.groupPublicKey)}) else {
SNLog("Can't leave nonexistent closed group.")
failure(job, MessageSenderError.noThread, true)
failure(job, MessageSenderError.noThread, true, dependencies)
return
}
guard let closedGroup: ClosedGroup = Storage.shared.read({ db in try? thread.closedGroup.fetchOne(db)}) else {
failure(job, MessageSenderError.invalidClosedGroupUpdate, true)
failure(job, MessageSenderError.invalidClosedGroupUpdate, true, dependencies)
return
}
@ -101,7 +102,7 @@ public enum GroupLeavingJob: JobExecutor {
.deleteAll(db)
}
}
success(job, false)
success(job, false, dependencies)
}
.catch(on: queue) { error in
Storage.shared.writeAsync { db in
@ -115,7 +116,7 @@ public enum GroupLeavingJob: JobExecutor {
]
)
}
success(job, false)
success(job, false, dependencies)
}
.retainUntilComplete()

View File

@ -6,6 +6,7 @@
#import "AppContext.h"
#import <SignalCoreKit/SignalCoreKit.h>
#import <SignalCoreKit/Threading.h>
#import <SessionUtilitiesKit/SessionUtilitiesKit.h>
NS_ASSUME_NONNULL_BEGIN
@ -60,7 +61,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)runNowOrWhenAppWillBecomeReady:(AppReadyBlock)block
{
if (CurrentAppContext().isRunningTests) {
if ([SNUtilitiesKitConfiguration isRunningTests]) {
// We don't need to do any "on app ready" work in the tests.
return;
}
@ -82,7 +83,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)runNowOrWhenAppDidBecomeReady:(AppReadyBlock)block
{
if (CurrentAppContext().isRunningTests) {
if ([SNUtilitiesKitConfiguration isRunningTests]) {
// We don't need to do any "on app ready" work in the tests.
return;
}

View File

@ -61,7 +61,6 @@ final class NotificationServiceExtensionContext : NSObject, AppContext {
let frame = CGRect.zero
let interfaceOrientation = UIInterfaceOrientation.unknown
let isRTL = false
let isRunningTests = false
let reportedApplicationState = UIApplication.State.background
let statusBarHeight = CGFloat.zero

View File

@ -30,7 +30,6 @@ final class ShareAppExtensionContext: NSObject, AppContext {
}()
var isRTL: Bool { return ShareAppExtensionContext._isRTL }
var isRunningTests: Bool { return false } // We don't need to distinguish this in the SAE
var statusBarHeight: CGFloat { return 20 }
var openSystemSettingsAction: UIAlertAction?

View File

@ -5,6 +5,7 @@ import CoreServices
import PromiseKit
import SignalUtilitiesKit
import SessionUIKit
import SessionUtilitiesKit
final class ShareVC: UINavigationController, ShareViewDelegate {
private var areVersionMigrationsComplete = false
@ -46,7 +47,7 @@ final class ShareVC: UINavigationController, ShareViewDelegate {
// We don't need to use applySignalAppearence in the SAE.
if CurrentAppContext().isRunningTests {
if SNUtilitiesKit.isRunningTests {
// TODO: Do we need to implement isRunningTests in the SAE context?
return
}

View File

@ -228,7 +228,7 @@ class ThreadSettingsViewModelSpec: QuickSpec {
ParentType.NavItem(
id: .cancel,
systemItem: .cancel,
accessibilityIdentifier: "Cancel"
accessibilityIdentifier: "Cancel button"
)
]))
expect(viewModel.rightNavItems.firstValue())

View File

@ -3,6 +3,10 @@
import Foundation
public enum SNUtilitiesKit { // Just to make the external API nice
public static var isRunningTests: Bool {
ProcessInfo.processInfo.environment["XCTestConfigurationFilePath"] != nil
}
public static func migrations() -> TargetMigrations {
return TargetMigrations(
identifier: .utilitiesKit,
@ -29,4 +33,5 @@ public enum SNUtilitiesKit { // Just to make the external API nice
@objc public final class SNUtilitiesKitConfiguration: NSObject {
@objc public static var maxFileSize: UInt = 0
@objc public static var isRunningTests: Bool { return SNUtilitiesKit.isRunningTests }
}

View File

@ -212,11 +212,8 @@ open class Storage {
for migration: Migration.Type,
in target: TargetMigrations.Identifier
) {
// In test builds ignore any migration progress updates (we run in a custom database writer anyway),
// this code should be the same as 'CurrentAppContext().isRunningTests' but since the tests can run
// without being attached to a host application the `CurrentAppContext` might not have been set and
// would crash as it gets force-unwrapped - better to just do the check explicitly instead
guard ProcessInfo.processInfo.environment["XCTestConfigurationFilePath"] == nil else { return }
// In test builds ignore any migration progress updates (we run in a custom database writer anyway)
guard !SNUtilitiesKit.isRunningTests else { return }
Storage.shared.migrationProgressUpdater?.wrappedValue(target.key(with: migration), progress)
}
@ -242,7 +239,7 @@ open class Storage {
// For these cases it means either the keySpec or the keychain has become corrupt so in order to
// get back to a "known good state" and behave like a new install we need to reset the storage
// and regenerate the key
if !CurrentAppContext().isRunningTests {
if !SNUtilitiesKit.isRunningTests {
// Try to reset app by deleting database.
resetAllStorage()
}

View File

@ -42,8 +42,6 @@ NSString *NSStringForUIApplicationState(UIApplicationState value);
// Whether the user is using a right-to-left language like Arabic.
@property (nonatomic, readonly) BOOL isRTL;
@property (nonatomic, readonly) BOOL isRunningTests;
@property (atomic, nullable) UIWindow *mainWindow;
// Unlike UIApplication.applicationState, this is thread-safe.

View File

@ -138,7 +138,7 @@ public final class JobRunner: JobRunnerType {
isTestingJobRunner || (
HasAppContext() &&
CurrentAppContext().isMainApp &&
!CurrentAppContext().isRunningTests
!SNUtilitiesKit.isRunningTests
)
)
self.blockingQueue = Atomic(
@ -609,6 +609,19 @@ public final class JobQueue {
timestamp: TimeInterval,
dependencies: Dependencies
) -> Trigger? {
guard !SNUtilitiesKit.isRunningTests else {
/// When running unit tests don't schedule a proper Timer, use a while loop instead and base it on the `fixedTime`
/// value instead of `dependencies.date` to simplify things
DispatchQueue.global(qos: .default).async { [weak queue] in
while dependencies.fixedTime < Int(timestamp) {
Thread.sleep(forTimeInterval: 0.01) // Wait for 10ms
}
queue?.start(dependencies: dependencies)
}
return nil
}
/// Setup the trigger (wait at least 1 second before triggering)
///
/// **Note:** We use the `Timer.scheduledTimerOnMainThread` method because running a timer
@ -616,28 +629,13 @@ public final class JobQueue {
/// the correct thread
let trigger: Trigger = Trigger()
trigger.fireTimestamp = max(1, (timestamp - dependencies.date.timeIntervalSince1970))
switch HasAppContext() && CurrentAppContext().isRunningTests {
case true:
// When running unit tests don't schedule a proper Timer, use a while loop instead
DispatchQueue.global(qos: .default).async { [weak queue] in
while timestamp < dependencies.date.timeIntervalSince1970 {
Thread.sleep(forTimeInterval: 0.01) // Wait for 10ms
}
queue?.start(dependencies: dependencies)
}
case false:
trigger.timer = Timer.scheduledTimerOnMainThread(
withTimeInterval: trigger.fireTimestamp,
repeats: false,
block: { [weak queue] _ in
queue?.start(dependencies: dependencies)
}
)
}
trigger.timer = Timer.scheduledTimerOnMainThread(
withTimeInterval: trigger.fireTimestamp,
repeats: false,
block: { [weak queue] _ in
queue?.start(dependencies: dependencies)
}
)
return trigger
}
@ -1129,7 +1127,11 @@ public final class JobQueue {
}
// If the next job isn't scheduled in the future then just restart the JobRunner immediately
let secondsUntilNextJob: TimeInterval = (nextJobTimestamp - dependencies.date.timeIntervalSince1970)
let secondsUntilNextJob: TimeInterval = {
guard !SNUtilitiesKit.isRunningTests else { return (nextJobTimestamp - TimeInterval(dependencies.fixedTime)) }
return (nextJobTimestamp - dependencies.date.timeIntervalSince1970)
}()
guard secondsUntilNextJob > 0 else {
// Only log that the queue is getting restarted if this queue had actually been about to stop

View File

@ -58,14 +58,14 @@ class JobRunnerSpec: QuickSpec {
else { return success(job, true, dependencies) }
let completeJob: () -> () = {
// Need to auto-increment the 'completeTime' and 'nextRunTimestamp' to prevent the job
// from immediately being run again
// Need to increase the 'completeTime' and 'nextRunTimestamp' to prevent the job
// from immediately being run again or immediately completing afterwards
let updatedJob: Job = job
.with(nextRunTimestamp: (max(1234567890, job.nextRunTimestamp) + 0.5))
.with(nextRunTimestamp: TimeInterval(details.completeTime + 1))
.with(
details: TestDetails(
result: details.result,
completeTime: (details.completeTime + 1),
completeTime: (details.completeTime + 2),
intValue: details.intValue,
stringValue: details.stringValue
)
@ -1366,12 +1366,13 @@ class JobRunnerSpec: QuickSpec {
// Make sure there are no running jobs
dependencies.fixedTime = 1
dependencies.date = Date(timeIntervalSince1970: 1234567890 + 1)
expect(jobRunner.detailsFor(state: .running))
.toEventually(
equal([100: try! JSONEncoder().encode(TestDetails(result: .deferred, completeTime: 2))]),
beEmpty(),
timeout: .milliseconds(50)
)
expect(mockStorage.read { db in try Job.select(.details).asRequest(of: Data.self).fetchOne(db) })
.to(equal(try! JSONEncoder().encode(TestDetails(result: .deferred, completeTime: 3))))
}
it("does not delete the job") {
@ -1392,10 +1393,9 @@ class JobRunnerSpec: QuickSpec {
// Make sure there are no running jobs
dependencies.fixedTime = 1
dependencies.date = Date(timeIntervalSince1970: 1234567890 + 1)
expect(jobRunner.detailsFor(state: .running))
.toEventually(
equal([100: try! JSONEncoder().encode(TestDetails(result: .deferred, completeTime: 2))]),
beEmpty(),
timeout: .milliseconds(50)
)
@ -1425,28 +1425,10 @@ class JobRunnerSpec: QuickSpec {
timeout: .milliseconds(50)
)
// Restart the JobRunner
dependencies.date = Date(timeIntervalSince1970: 1234567890 + 0.5)
jobRunner.startNonBlockingQueues(dependencies: dependencies)
// Progress the time
dependencies.fixedTime = 2
// Make sure it finishes once
expect(jobRunner.detailsFor(state: .running))
.toEventually(
equal([100: try! JSONEncoder().encode(TestDetails(result: .deferred, completeTime: 2))]),
timeout: .milliseconds(50)
)
dependencies.fixedTime = 2
expect(Array(jobRunner.detailsFor(state: .running).keys))
.toEventually(
beEmpty(),
timeout: .milliseconds(50)
)
// Restart the JobRunner
dependencies.date = Date(timeIntervalSince1970: 1234567890 + 1)
jobRunner.startNonBlockingQueues(dependencies: dependencies)
// Make sure it finishes twice
expect(jobRunner.detailsFor(state: .running))
.toEventually(
equal([100: try! JSONEncoder().encode(TestDetails(result: .deferred, completeTime: 3))]),
@ -1459,17 +1441,32 @@ class JobRunnerSpec: QuickSpec {
timeout: .milliseconds(50)
)
// Restart the JobRunner
dependencies.date = Date(timeIntervalSince1970: 1234567890 + 1.5)
jobRunner.startNonBlockingQueues(dependencies: dependencies)
// Progress the time
dependencies.fixedTime = 4
// Make sure it finishes twice
expect(jobRunner.detailsFor(state: .running))
.toEventually(
equal([100: try! JSONEncoder().encode(TestDetails(result: .deferred, completeTime: 5))]),
timeout: .milliseconds(50)
)
dependencies.fixedTime = 5
expect(Array(jobRunner.detailsFor(state: .running).keys))
.toEventually(
beEmpty(),
timeout: .milliseconds(50)
)
// Progress the time
dependencies.fixedTime = 6
// Make sure it's finishes the last time
expect(jobRunner.detailsFor(state: .running))
.toEventually(
equal([100: try! JSONEncoder().encode(TestDetails(result: .deferred, completeTime: 4))]),
equal([100: try! JSONEncoder().encode(TestDetails(result: .deferred, completeTime: 7))]),
timeout: .milliseconds(50)
)
dependencies.fixedTime = 4
dependencies.fixedTime = 7
expect(Array(jobRunner.detailsFor(state: .running).keys))
.toEventually(
beEmpty(),
@ -1502,7 +1499,6 @@ class JobRunnerSpec: QuickSpec {
// Make sure there are no running jobs
dependencies.fixedTime = 1
dependencies.date = Date(timeIntervalSince1970: 1234567890 + 1)
expect(Array(jobRunner.detailsFor(state: .running).keys))
.toEventually(
beEmpty(),
@ -1528,7 +1524,6 @@ class JobRunnerSpec: QuickSpec {
// Make sure there are no running jobs
dependencies.fixedTime = 1
dependencies.date = Date(timeIntervalSince1970: 1234567890 + 1)
expect(Array(jobRunner.detailsFor(state: .running).keys))
.toEventually(
beEmpty(),
@ -1561,7 +1556,6 @@ class JobRunnerSpec: QuickSpec {
// Make sure there are no running jobs
dependencies.fixedTime = 1
dependencies.date = Date(timeIntervalSince1970: 1234567890 + 1)
expect(Array(jobRunner.detailsFor(state: .running).keys))
.toEventually(
beEmpty(),
@ -1587,7 +1581,6 @@ class JobRunnerSpec: QuickSpec {
// Make sure there are no running jobs
dependencies.fixedTime = 1
dependencies.date = Date(timeIntervalSince1970: 1234567890 + 1)
expect(Array(jobRunner.detailsFor(state: .running).keys))
.toEventually(
beEmpty(),

View File

@ -17,6 +17,6 @@ FOUNDATION_EXPORT const unsigned char SignalUtilitiesKitVersionString[];
#import <SignalUtilitiesKit/OWSFormat.h>
#import <SignalUtilitiesKit/OWSOperation.h>
#import <SignalUtilitiesKit/OWSViewController.h>
#import <SignalUtilitiesKit/SSKAsserts.h>
#import <SignalUtilitiesKit/TSConstants.h>
#import <SignalUtilitiesKit/UIFont+OWS.h>
#import <SignalCoreKit/OWSAsserts.h>

View File

@ -1,68 +0,0 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import <SessionUtilitiesKit/AppContext.h>
#import <SignalCoreKit/NSObject+OWS.h>
#import <SignalCoreKit/OWSAsserts.h>
NS_ASSUME_NONNULL_BEGIN
#pragma mark - Singleton Asserts
// The "singleton asserts" can be used to ensure
// that we only create a singleton once.
//
// The simplest way to use them is the OWSSingletonAssert() macro.
// It is intended to be used inside the singleton's initializer.
//
// If, however, a singleton has multiple possible initializers,
// you need to:
//
// 1. Use OWSSingletonAssertFlag() outside the class definition.
// 2. Use OWSSingletonAssertInit() in each initializer.
#ifdef DEBUG
#define ENFORCE_SINGLETONS
#endif
#ifdef ENFORCE_SINGLETONS
#define OWSSingletonAssertFlag() static BOOL _isSingletonCreated = NO;
#define OWSSingletonAssertInit() \
@synchronized([self class]) { \
if (!CurrentAppContext().isRunningTests) { \
OWSAssertDebug(!_isSingletonCreated); \
_isSingletonCreated = YES; \
} \
}
#define OWSSingletonAssert() OWSSingletonAssertFlag() OWSSingletonAssertInit()
#else
#define OWSSingletonAssertFlag()
#define OWSSingletonAssertInit()
#define OWSSingletonAssert()
#endif
#define OWSFailDebugUnlessRunningTests(_messageFormat, ...) \
do { \
if (!CurrentAppContext().isRunningTests) { \
OWSFailDebug(_messageFormat, ##__VA_ARGS__); \
} \
} while (0)
#define OWSCFailDebugUnlessRunningTests(_messageFormat, ...) \
do { \
if (!CurrentAppContext().isRunningTests) { \
OWSCFailDebug(_messageFormat, ##__VA_ARGS__); \
} \
} while (NO)
NS_ASSUME_NONNULL_END

View File

@ -14,12 +14,8 @@ public class SwiftSingletons: NSObject {
}
public func register(_ singleton: AnyObject) {
guard !CurrentAppContext().isRunningTests else {
return
}
guard _isDebugAssertConfiguration() else {
return
}
guard !SNUtilitiesKit.isRunningTests else { return }
guard _isDebugAssertConfiguration() else { return }
let singletonClassName = String(describing: type(of: singleton))
guard !classSet.contains(singletonClassName) else {
owsFailDebug("Duplicate singleton: \(singletonClassName).")