chromium/chrome/services/sharing/nearby/platform/single_thread_executor_unittest.cc

// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/services/sharing/nearby/platform/submittable_executor.h"

#include <map>
#include <memory>
#include <set>
#include <utility>

#include "base/synchronization/lock.h"
#include "base/task/thread_pool.h"
#include "base/test/task_environment.h"
#include "base/unguessable_token.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace nearby {
namespace chrome {

// To test Execute(), which has no return value, each task is assigned a unique
// ID. This ID is added to |executed_tasks_| when the task is Run(). Thus, the
// presence of an ID within |executed_tasks_| means the associated task has
// completed execution.
class SingleThreadExecutorTest : public testing::Test {
 protected:
  Runnable CreateTrackedRunnable(base::RunLoop& run_loop,
                                 const base::UnguessableToken& task_id) {
    return [&] {
      base::AutoLock al(executed_tasks_lock_);
      executed_tasks_.insert(task_id);
      run_loop.Quit();
    };
  }

  bool HasTaskExecuted(const base::UnguessableToken& task_id) {
    base::AutoLock al(executed_tasks_lock_);
    return executed_tasks_.find(task_id) != executed_tasks_.end();
  }

  base::test::TaskEnvironment task_environment_;
  std::unique_ptr<SubmittableExecutor> single_thread_executor_ =
      std::make_unique<SubmittableExecutor>(
          base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()}));

 private:
  base::Lock executed_tasks_lock_;
  std::set<base::UnguessableToken> executed_tasks_;
};

TEST_F(SingleThreadExecutorTest, Submit) {
  base::RunLoop run_loop;
  base::UnguessableToken task_id = base::UnguessableToken::Create();
  EXPECT_TRUE(single_thread_executor_->DoSubmit(
      CreateTrackedRunnable(run_loop, task_id)));

  run_loop.Run();
  EXPECT_TRUE(HasTaskExecuted(task_id));
}

TEST_F(SingleThreadExecutorTest, Execute) {
  base::RunLoop run_loop;
  base::UnguessableToken task_id = base::UnguessableToken::Create();
  single_thread_executor_->Execute(CreateTrackedRunnable(run_loop, task_id));

  run_loop.Run();
  EXPECT_TRUE(HasTaskExecuted(task_id));
}

TEST_F(SingleThreadExecutorTest, ShutdownPreventsFurtherTasks) {
  single_thread_executor_->Shutdown();
  base::RunLoop run_loop;
  base::UnguessableToken task_id = base::UnguessableToken::Create();
  EXPECT_FALSE(single_thread_executor_->DoSubmit(
      CreateTrackedRunnable(run_loop, task_id)));

  EXPECT_FALSE(HasTaskExecuted(task_id));
}

TEST_F(SingleThreadExecutorTest, DestroyAllowExistingTaskToComplete) {
  base::RunLoop run_loop;
  base::UnguessableToken task_id = base::UnguessableToken::Create();
  EXPECT_TRUE(single_thread_executor_->DoSubmit(
      CreateTrackedRunnable(run_loop, task_id)));
  EXPECT_FALSE(HasTaskExecuted(task_id));
  single_thread_executor_.reset();

  run_loop.Run();
  EXPECT_TRUE(HasTaskExecuted(task_id));
}

}  // namespace chrome
}  // namespace nearby