#include "base/task/sequence_manager/work_tracker.h"
#include <optional>
#include "base/test/bind.h"
#include "base/test/test_timeouts.h"
#include "base/threading/platform_thread.h"
#include "base/threading/thread.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace base::sequence_manager::internal {
TEST(SequenceManagerWorkTrackerTest, SetRunTaskSynchronouslyAllowed) {
WorkTracker tracker;
EXPECT_FALSE(tracker.TryAcquireSyncWorkAuthorization().IsValid());
tracker.OnBeginWork();
tracker.OnIdle();
EXPECT_FALSE(tracker.TryAcquireSyncWorkAuthorization().IsValid());
tracker.WillRequestReloadImmediateWorkQueue();
tracker.WillReloadImmediateWorkQueues();
tracker.OnIdle();
EXPECT_FALSE(tracker.TryAcquireSyncWorkAuthorization().IsValid());
tracker.SetRunTaskSynchronouslyAllowed(true);
EXPECT_TRUE(tracker.TryAcquireSyncWorkAuthorization().IsValid());
tracker.SetRunTaskSynchronouslyAllowed(false);
EXPECT_FALSE(tracker.TryAcquireSyncWorkAuthorization().IsValid());
}
TEST(SequenceManagerWorkTrackerTest, SetRunTaskSynchronouslyAllowedBlocks) {
WorkTracker tracker;
tracker.SetRunTaskSynchronouslyAllowed(true);
WaitableEvent did_acquire_sync_work_auth;
bool will_release_sync_work_auth = false;
Thread other_thread("OtherThread");
other_thread.Start();
other_thread.task_runner()->PostTask(
FROM_HERE, BindLambdaForTesting([&] {
std::optional<SyncWorkAuthorization> auth =
tracker.TryAcquireSyncWorkAuthorization();
EXPECT_TRUE(auth->IsValid());
did_acquire_sync_work_auth.Signal();
PlatformThread::Sleep(TestTimeouts::tiny_timeout());
will_release_sync_work_auth = true;
auth.reset();
}));
did_acquire_sync_work_auth.Wait();
tracker.SetRunTaskSynchronouslyAllowed(false);
EXPECT_TRUE(will_release_sync_work_auth);
other_thread.FlushForTesting();
}
TEST(SequenceManagerWorkTrackerTest, WillRequestReloadImmediateWorkQueue) {
WorkTracker tracker;
tracker.SetRunTaskSynchronouslyAllowed(true);
EXPECT_TRUE(tracker.TryAcquireSyncWorkAuthorization().IsValid());
tracker.WillRequestReloadImmediateWorkQueue();
EXPECT_FALSE(tracker.TryAcquireSyncWorkAuthorization().IsValid());
tracker.WillReloadImmediateWorkQueues();
EXPECT_FALSE(tracker.TryAcquireSyncWorkAuthorization().IsValid());
tracker.OnIdle();
EXPECT_TRUE(tracker.TryAcquireSyncWorkAuthorization().IsValid());
tracker.WillRequestReloadImmediateWorkQueue();
EXPECT_FALSE(tracker.TryAcquireSyncWorkAuthorization().IsValid());
tracker.OnIdle();
EXPECT_FALSE(tracker.TryAcquireSyncWorkAuthorization().IsValid());
}
TEST(SequenceManagerWorkTrackerTest, OnBeginWork) {
WorkTracker tracker;
tracker.SetRunTaskSynchronouslyAllowed(true);
EXPECT_TRUE(tracker.TryAcquireSyncWorkAuthorization().IsValid());
tracker.OnBeginWork();
EXPECT_FALSE(tracker.TryAcquireSyncWorkAuthorization().IsValid());
tracker.OnIdle();
EXPECT_TRUE(tracker.TryAcquireSyncWorkAuthorization().IsValid());
}
TEST(SequenceManagerWorkTrackerTest, TwoSyncWorkAuthorizations) {
WorkTracker tracker;
tracker.SetRunTaskSynchronouslyAllowed(true);
std::optional<SyncWorkAuthorization> first =
tracker.TryAcquireSyncWorkAuthorization();
EXPECT_TRUE(first->IsValid());
SyncWorkAuthorization second = tracker.TryAcquireSyncWorkAuthorization();
EXPECT_FALSE(second.IsValid());
first.reset();
EXPECT_TRUE(tracker.TryAcquireSyncWorkAuthorization().IsValid());
}
TEST(SequenceManagerWorkTrackerTest, OnBeginWorkBlocks) {
WorkTracker tracker;
tracker.SetRunTaskSynchronouslyAllowed(true);
WaitableEvent did_acquire_sync_work_auth;
bool will_release_sync_work_auth = false;
Thread other_thread("OtherThread");
other_thread.Start();
other_thread.task_runner()->PostTask(
FROM_HERE, BindLambdaForTesting([&] {
std::optional<SyncWorkAuthorization> auth =
tracker.TryAcquireSyncWorkAuthorization();
EXPECT_TRUE(auth->IsValid());
did_acquire_sync_work_auth.Signal();
PlatformThread::Sleep(TestTimeouts::tiny_timeout());
will_release_sync_work_auth = true;
auth.reset();
}));
did_acquire_sync_work_auth.Wait();
tracker.OnBeginWork();
EXPECT_TRUE(will_release_sync_work_auth);
other_thread.FlushForTesting();
}
}