test_completion_callback_unittest.cc 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. // Copyright (c) 2011 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. // Illustrates how to use net::TestCompletionCallback.
  5. #include "net/base/test_completion_callback.h"
  6. #include "base/bind.h"
  7. #include "base/check_op.h"
  8. #include "base/location.h"
  9. #include "base/memory/raw_ptr.h"
  10. #include "base/notreached.h"
  11. #include "base/task/single_thread_task_runner.h"
  12. #include "base/threading/thread_task_runner_handle.h"
  13. #include "net/base/completion_once_callback.h"
  14. #include "net/test/test_with_task_environment.h"
  15. #include "testing/gtest/include/gtest/gtest.h"
  16. #include "testing/platform_test.h"
  17. namespace net {
  18. namespace {
  19. const int kMagicResult = 8888;
  20. void CallClosureAfterCheckingResult(base::OnceClosure closure,
  21. bool* did_check_result,
  22. int result) {
  23. DCHECK_EQ(result, kMagicResult);
  24. *did_check_result = true;
  25. std::move(closure).Run();
  26. }
  27. // ExampleEmployer is a toy version of HostResolver
  28. // TODO: restore damage done in extracting example from real code
  29. // (e.g. bring back real destructor, bring back comments)
  30. class ExampleEmployer {
  31. public:
  32. ExampleEmployer();
  33. ExampleEmployer(const ExampleEmployer&) = delete;
  34. ExampleEmployer& operator=(const ExampleEmployer&) = delete;
  35. ~ExampleEmployer();
  36. // Posts to the current thread a task which itself posts |callback| to the
  37. // current thread. Returns true on success
  38. bool DoSomething(CompletionOnceCallback callback);
  39. private:
  40. class ExampleWorker;
  41. friend class ExampleWorker;
  42. scoped_refptr<ExampleWorker> request_;
  43. };
  44. // Helper class; this is how ExampleEmployer schedules work.
  45. class ExampleEmployer::ExampleWorker
  46. : public base::RefCountedThreadSafe<ExampleWorker> {
  47. public:
  48. ExampleWorker(ExampleEmployer* employer, CompletionOnceCallback callback)
  49. : employer_(employer), callback_(std::move(callback)) {}
  50. void DoWork();
  51. void DoCallback();
  52. private:
  53. friend class base::RefCountedThreadSafe<ExampleWorker>;
  54. ~ExampleWorker() = default;
  55. // Only used on the origin thread (where DoSomething was called).
  56. raw_ptr<ExampleEmployer> employer_;
  57. CompletionOnceCallback callback_;
  58. // Used to post ourselves onto the origin thread.
  59. const scoped_refptr<base::SingleThreadTaskRunner> origin_task_runner_ =
  60. base::ThreadTaskRunnerHandle::Get();
  61. };
  62. void ExampleEmployer::ExampleWorker::DoWork() {
  63. // In a real worker thread, some work would be done here.
  64. // Pretend it is, and send the completion callback.
  65. origin_task_runner_->PostTask(
  66. FROM_HERE, base::BindOnce(&ExampleWorker::DoCallback, this));
  67. }
  68. void ExampleEmployer::ExampleWorker::DoCallback() {
  69. // Running on the origin thread.
  70. // Drop the employer_'s reference to us. Do this before running the
  71. // callback since the callback might result in the employer being
  72. // destroyed.
  73. employer_->request_ = nullptr;
  74. std::move(callback_).Run(kMagicResult);
  75. }
  76. ExampleEmployer::ExampleEmployer() = default;
  77. ExampleEmployer::~ExampleEmployer() = default;
  78. bool ExampleEmployer::DoSomething(CompletionOnceCallback callback) {
  79. DCHECK(!request_.get()) << "already in use";
  80. request_ = base::MakeRefCounted<ExampleWorker>(this, std::move(callback));
  81. if (!base::ThreadTaskRunnerHandle::Get()->PostTask(
  82. FROM_HERE, base::BindOnce(&ExampleWorker::DoWork, request_))) {
  83. NOTREACHED();
  84. request_ = nullptr;
  85. return false;
  86. }
  87. return true;
  88. }
  89. } // namespace
  90. class TestCompletionCallbackTest : public PlatformTest,
  91. public WithTaskEnvironment {};
  92. TEST_F(TestCompletionCallbackTest, Simple) {
  93. ExampleEmployer boss;
  94. TestCompletionCallback callback;
  95. bool queued = boss.DoSomething(callback.callback());
  96. EXPECT_TRUE(queued);
  97. int result = callback.WaitForResult();
  98. EXPECT_EQ(result, kMagicResult);
  99. }
  100. TEST_F(TestCompletionCallbackTest, Closure) {
  101. ExampleEmployer boss;
  102. TestClosure closure;
  103. bool did_check_result = false;
  104. CompletionOnceCallback completion_callback =
  105. base::BindOnce(&CallClosureAfterCheckingResult, closure.closure(),
  106. base::Unretained(&did_check_result));
  107. bool queued = boss.DoSomething(std::move(completion_callback));
  108. EXPECT_TRUE(queued);
  109. EXPECT_FALSE(did_check_result);
  110. closure.WaitForResult();
  111. EXPECT_TRUE(did_check_result);
  112. }
  113. // TODO: test deleting ExampleEmployer while work outstanding
  114. } // namespace net