Index: ios/chrome/app/deferred_initialization_runner_unittest.mm |
diff --git a/ios/chrome/app/deferred_initialization_runner_unittest.mm b/ios/chrome/app/deferred_initialization_runner_unittest.mm |
new file mode 100644 |
index 0000000000000000000000000000000000000000..dd242beade1f29fa4602c4c8292baaf2579863dd |
--- /dev/null |
+++ b/ios/chrome/app/deferred_initialization_runner_unittest.mm |
@@ -0,0 +1,164 @@ |
+// Copyright 2016 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#import "ios/chrome/app/deferred_initialization_runner.h" |
+ |
+#import "base/test/ios/wait_util.h" |
+#include "base/time/time.h" |
+#include "testing/platform_test.h" |
+ |
+TEST(DeferredInitializationRunnerTest, TestSharedInstance) { |
+ EXPECT_TRUE([DeferredInitializationRunner sharedInstance]); |
+ // Cancelling a non-existing block does nothing. |
+ [[DeferredInitializationRunner sharedInstance] |
+ cancelBlockNamed:@"Invalid Name"]; |
+} |
+ |
+// Tests that all blocks added on the queue are executed after a delay. |
+TEST(DeferredInitializationRunnerTest, TestRunBlockSequentially) { |
+ // Setup. |
+ __block bool firstFlag = NO; |
+ __block bool secondFlag = NO; |
+ DeferredInitializationRunner* runner = |
+ [DeferredInitializationRunner sharedInstance]; |
+ ProceduralBlock firstBlock = ^() { |
+ EXPECT_FALSE(firstFlag); |
+ firstFlag = YES; |
+ }; |
+ ProceduralBlock secondBlock = ^() { |
+ EXPECT_FALSE(secondFlag); |
+ secondFlag = YES; |
+ }; |
+ ConditionBlock secondBlockRun = ^bool { |
+ return secondFlag; |
+ }; |
+ runner.delayBetweenBlocks = 0.01; |
+ runner.delayBeforeFirstBlock = 0.01; |
+ |
+ [runner enqueueBlockNamed:@"first block" block:firstBlock]; |
+ [runner enqueueBlockNamed:@"second block" block:secondBlock]; |
+ |
+ ASSERT_FALSE(firstFlag); |
+ ASSERT_FALSE(secondFlag); |
+ EXPECT_EQ(2U, [runner numberOfBlocksRemaining]); |
+ |
+ // Action. |
+ base::test::ios::WaitUntilCondition(secondBlockRun); |
+ |
+ // Test. |
+ EXPECT_TRUE(firstFlag); |
+ EXPECT_TRUE(secondFlag); |
+ EXPECT_EQ(0U, [runner numberOfBlocksRemaining]); |
+} |
+ |
+// Tests that runBlockIfNecessary does not execute the block if it has already |
+// been executed and runs synchronously the one not executed. |
+TEST(DeferredInitializationRunnerTest, TestRunBlock) { |
+ // Setup. |
+ __block bool quickFlag = NO; |
+ __block bool slowFlag = NO; |
+ DeferredInitializationRunner* runner = |
+ [DeferredInitializationRunner sharedInstance]; |
+ ProceduralBlock quickBlock = ^() { |
+ EXPECT_FALSE(quickFlag); |
+ quickFlag = YES; |
+ // Make sure we have time to go back to this test before running the second |
+ // task. |
+ runner.delayBetweenBlocks = 1; |
+ }; |
+ ConditionBlock quickBlockRun = ^bool { |
+ return quickFlag; |
+ }; |
+ ProceduralBlock slowBlock = ^() { |
+ EXPECT_FALSE(slowFlag); |
+ slowFlag = YES; |
+ }; |
+ runner.delayBeforeFirstBlock = 0.01; |
+ |
+ // Action. |
+ [runner enqueueBlockNamed:@"quick block" block:quickBlock]; |
+ [runner enqueueBlockNamed:@"slow block" block:slowBlock]; |
+ |
+ // Test. |
+ base::test::ios::WaitUntilCondition(quickBlockRun); |
+ EXPECT_TRUE(quickFlag); |
+ EXPECT_FALSE(slowFlag); |
+ EXPECT_EQ(1U, [runner numberOfBlocksRemaining]); |
+ [runner runBlockIfNecessary:@"quick block"]; |
+ [runner runBlockIfNecessary:@"slow block"]; |
+ EXPECT_TRUE(quickFlag); |
+ EXPECT_TRUE(slowFlag); |
+ EXPECT_EQ(0U, [runner numberOfBlocksRemaining]); |
+} |
+ |
+// Tests that a block is not executed when cancelled and it is removed from the |
+// remaining blocks list. |
+TEST(DeferredInitializationRunnerTest, TestCancelBlock) { |
+ // Setup. |
+ __block BOOL blockFinished = NO; |
+ DeferredInitializationRunner* runner = |
+ [DeferredInitializationRunner sharedInstance]; |
+ runner.delayBeforeFirstBlock = 0.01; |
+ runner.delayBetweenBlocks = 0.01; |
+ |
+ [runner enqueueBlockNamed:@"cancel me" |
+ block:^() { |
+ blockFinished = YES; |
+ }]; |
+ ASSERT_EQ(1U, [runner numberOfBlocksRemaining]); |
+ |
+ // Action. |
+ [runner cancelBlockNamed:@"cancel me"]; |
+ |
+ // Test. |
+ EXPECT_FALSE(blockFinished); |
+ EXPECT_EQ(0U, [runner numberOfBlocksRemaining]); |
+} |
+ |
+// Tests that a cancelled block will do nothing when run by name. |
+TEST(DeferredInitializationRunnerTest, TestCancelledBlockDoNothing) { |
+ // Setup. |
+ __block BOOL blockFinished = NO; |
+ DeferredInitializationRunner* runner = |
+ [DeferredInitializationRunner sharedInstance]; |
+ runner.delayBeforeFirstBlock = 0.01; |
+ runner.delayBetweenBlocks = 0.01; |
+ |
+ [runner enqueueBlockNamed:@"cancel me" |
+ block:^() { |
+ blockFinished = YES; |
+ }]; |
+ |
+ // Action. |
+ [runner cancelBlockNamed:@"cancel me"]; |
+ [runner runBlockIfNecessary:@"cancel me"]; |
+ |
+ // Test: expect false, the block should never be executed because it was |
+ // cancelled before it started running. |
+ EXPECT_FALSE(blockFinished); |
+} |
+ |
+// Tests that adding a block with the same name as an existing block will |
+// override the existing one. |
+TEST(DeferredInitializationRunnerTest, TestSecondBlockInvalidatesFirst) { |
+ // Setup. |
+ __block int blockRunCount = 0; |
+ ProceduralBlock runBlock = ^() { |
+ ++blockRunCount; |
+ }; |
+ DeferredInitializationRunner* runner = |
+ [DeferredInitializationRunner sharedInstance]; |
+ runner.delayBeforeFirstBlock = 0.01; |
+ runner.delayBetweenBlocks = 0.01; |
+ |
+ // Action. |
+ [runner enqueueBlockNamed:@"multiple" block:runBlock]; |
+ [runner enqueueBlockNamed:@"multiple" block:runBlock]; |
+ |
+ // Test: |runBlock| was executed only once. |
+ EXPECT_EQ(1U, [runner numberOfBlocksRemaining]); |
+ [runner runBlockIfNecessary:@"multiple"]; |
+ EXPECT_EQ(0U, [runner numberOfBlocksRemaining]); |
+ EXPECT_EQ(1, blockRunCount); |
+} |