From c7667229e2ab35d14fa7855789ee0584a2f8e817 Mon Sep 17 00:00:00 2001 From: Konstantin Varlamov Date: Thu, 10 May 2018 15:48:52 -0400 Subject: Firestore C++: add missing tests for Executor (#1247) --- .../test/firebase/firestore/util/executor_test.cc | 104 +++++++++++++++++++++ 1 file changed, 104 insertions(+) (limited to 'Firestore/core/test') diff --git a/Firestore/core/test/firebase/firestore/util/executor_test.cc b/Firestore/core/test/firebase/firestore/util/executor_test.cc index 5cf389b..e277786 100644 --- a/Firestore/core/test/firebase/firestore/util/executor_test.cc +++ b/Firestore/core/test/firebase/firestore/util/executor_test.cc @@ -49,6 +49,12 @@ TEST_P(ExecutorTest, Execute) { EXPECT_TRUE(WaitForTestToFinish()); } +TEST_P(ExecutorTest, ExecuteBlocking) { + bool finished = false; + executor->ExecuteBlocking([&] { finished = true; }); + EXPECT_TRUE(finished); +} + TEST_P(ExecutorTest, DestructorDoesNotBlockIfThereArePendingTasks) { const auto future = std::async(std::launch::async, [&] { auto another_executor = GetParam()(); @@ -105,6 +111,104 @@ TEST_P(ExecutorTest, DelayedOperationIsValidAfterTheOperationHasRun) { EXPECT_NO_THROW(delayed_operation.Cancel()); } +TEST_P(ExecutorTest, IsCurrentExecutor) { + EXPECT_FALSE(executor->IsCurrentExecutor()); + EXPECT_NE(executor->Name(), executor->CurrentExecutorName()); + + executor->ExecuteBlocking([&] { + EXPECT_TRUE(executor->IsCurrentExecutor()); + EXPECT_EQ(executor->Name(), executor->CurrentExecutorName()); + }); + + executor->Execute([&] { + EXPECT_TRUE(executor->IsCurrentExecutor()); + EXPECT_EQ(executor->Name(), executor->CurrentExecutorName()); + }); + + Schedule(executor.get(), Executor::Milliseconds(1), [&] { + EXPECT_TRUE(executor->IsCurrentExecutor()); + EXPECT_EQ(executor->Name(), executor->CurrentExecutorName()); + signal_finished(); + }); + + EXPECT_TRUE(WaitForTestToFinish()); +} + +TEST_P(ExecutorTest, OperationsCanBeRemovedFromScheduleBeforeTheyRun) { + const Executor::Tag tag_foo = 1; + const Executor::Tag tag_bar = 2; + + // Make sure the schedule is empty. + EXPECT_FALSE(executor->IsScheduled(tag_foo)); + EXPECT_FALSE(executor->IsScheduled(tag_bar)); + EXPECT_FALSE(executor->PopFromSchedule().has_value()); + + // Add two operations to the schedule with different tags. + + // The exact delay doesn't matter as long as it's too far away to be executed + // during the test. + const auto far_away = chr::seconds(1); + executor->Schedule(far_away, {tag_foo, [] {}}); + // Scheduled operations can be distinguished by their tag. + EXPECT_TRUE(executor->IsScheduled(tag_foo)); + EXPECT_FALSE(executor->IsScheduled(tag_bar)); + + // This operation will be scheduled after the previous one (operations + // scheduled with the same delay are FIFO ordered). + executor->Schedule(far_away, {tag_bar, [] {}}); + EXPECT_TRUE(executor->IsScheduled(tag_foo)); + EXPECT_TRUE(executor->IsScheduled(tag_bar)); + + // Now pop the operations one by one without waiting for them to be executed, + // check that operations are popped in the order they are scheduled and + // preserve tags. Schedule should become empty as a result. + + auto maybe_operation = executor->PopFromSchedule(); + ASSERT_TRUE(maybe_operation.has_value()); + EXPECT_EQ(maybe_operation->tag, tag_foo); + EXPECT_FALSE(executor->IsScheduled(tag_foo)); + EXPECT_TRUE(executor->IsScheduled(tag_bar)); + + maybe_operation = executor->PopFromSchedule(); + ASSERT_TRUE(maybe_operation.has_value()); + EXPECT_EQ(maybe_operation->tag, tag_bar); + EXPECT_FALSE(executor->IsScheduled(tag_bar)); + + // Schedule should now be empty. + EXPECT_FALSE(executor->PopFromSchedule().has_value()); +} + +TEST_P(ExecutorTest, DuplicateTagsOnOperationsAreAllowed) { + const Executor::Tag tag_foo = 1; + std::string steps; + + // Add two operations with the same tag to the schedule to verify that + // duplicate tags are allowed. + + const auto far_away = chr::seconds(1); + executor->Schedule(far_away, {tag_foo, [&steps] { steps += '1'; }}); + executor->Schedule(far_away, {tag_foo, [&steps] { steps += '2'; }}); + EXPECT_TRUE(executor->IsScheduled(tag_foo)); + + auto maybe_operation = executor->PopFromSchedule(); + ASSERT_TRUE(maybe_operation.has_value()); + EXPECT_EQ(maybe_operation->tag, tag_foo); + // There's still another operation with the same tag in the schedule. + EXPECT_TRUE(executor->IsScheduled(tag_foo)); + + maybe_operation->operation(); + + maybe_operation = executor->PopFromSchedule(); + ASSERT_TRUE(maybe_operation.has_value()); + EXPECT_EQ(maybe_operation->tag, tag_foo); + EXPECT_FALSE(executor->IsScheduled(tag_foo)); + + maybe_operation->operation(); + // Despite having the same tag, the operations should have been ordered + // according to their scheduled time and preserved their identity. + EXPECT_EQ(steps, "12"); +} + } // namespace util } // namespace firestore } // namespace firebase -- cgit v1.2.3