123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- // Copyright (c) 2011 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.
- // Illustrates how to use net::TestCompletionCallback.
- #include "net/base/test_completion_callback.h"
- #include "base/bind.h"
- #include "base/check_op.h"
- #include "base/location.h"
- #include "base/memory/raw_ptr.h"
- #include "base/notreached.h"
- #include "base/task/single_thread_task_runner.h"
- #include "base/threading/thread_task_runner_handle.h"
- #include "net/base/completion_once_callback.h"
- #include "net/test/test_with_task_environment.h"
- #include "testing/gtest/include/gtest/gtest.h"
- #include "testing/platform_test.h"
- namespace net {
- namespace {
- const int kMagicResult = 8888;
- void CallClosureAfterCheckingResult(base::OnceClosure closure,
- bool* did_check_result,
- int result) {
- DCHECK_EQ(result, kMagicResult);
- *did_check_result = true;
- std::move(closure).Run();
- }
- // ExampleEmployer is a toy version of HostResolver
- // TODO: restore damage done in extracting example from real code
- // (e.g. bring back real destructor, bring back comments)
- class ExampleEmployer {
- public:
- ExampleEmployer();
- ExampleEmployer(const ExampleEmployer&) = delete;
- ExampleEmployer& operator=(const ExampleEmployer&) = delete;
- ~ExampleEmployer();
- // Posts to the current thread a task which itself posts |callback| to the
- // current thread. Returns true on success
- bool DoSomething(CompletionOnceCallback callback);
- private:
- class ExampleWorker;
- friend class ExampleWorker;
- scoped_refptr<ExampleWorker> request_;
- };
- // Helper class; this is how ExampleEmployer schedules work.
- class ExampleEmployer::ExampleWorker
- : public base::RefCountedThreadSafe<ExampleWorker> {
- public:
- ExampleWorker(ExampleEmployer* employer, CompletionOnceCallback callback)
- : employer_(employer), callback_(std::move(callback)) {}
- void DoWork();
- void DoCallback();
- private:
- friend class base::RefCountedThreadSafe<ExampleWorker>;
- ~ExampleWorker() = default;
- // Only used on the origin thread (where DoSomething was called).
- raw_ptr<ExampleEmployer> employer_;
- CompletionOnceCallback callback_;
- // Used to post ourselves onto the origin thread.
- const scoped_refptr<base::SingleThreadTaskRunner> origin_task_runner_ =
- base::ThreadTaskRunnerHandle::Get();
- };
- void ExampleEmployer::ExampleWorker::DoWork() {
- // In a real worker thread, some work would be done here.
- // Pretend it is, and send the completion callback.
- origin_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&ExampleWorker::DoCallback, this));
- }
- void ExampleEmployer::ExampleWorker::DoCallback() {
- // Running on the origin thread.
- // Drop the employer_'s reference to us. Do this before running the
- // callback since the callback might result in the employer being
- // destroyed.
- employer_->request_ = nullptr;
- std::move(callback_).Run(kMagicResult);
- }
- ExampleEmployer::ExampleEmployer() = default;
- ExampleEmployer::~ExampleEmployer() = default;
- bool ExampleEmployer::DoSomething(CompletionOnceCallback callback) {
- DCHECK(!request_.get()) << "already in use";
- request_ = base::MakeRefCounted<ExampleWorker>(this, std::move(callback));
- if (!base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&ExampleWorker::DoWork, request_))) {
- NOTREACHED();
- request_ = nullptr;
- return false;
- }
- return true;
- }
- } // namespace
- class TestCompletionCallbackTest : public PlatformTest,
- public WithTaskEnvironment {};
- TEST_F(TestCompletionCallbackTest, Simple) {
- ExampleEmployer boss;
- TestCompletionCallback callback;
- bool queued = boss.DoSomething(callback.callback());
- EXPECT_TRUE(queued);
- int result = callback.WaitForResult();
- EXPECT_EQ(result, kMagicResult);
- }
- TEST_F(TestCompletionCallbackTest, Closure) {
- ExampleEmployer boss;
- TestClosure closure;
- bool did_check_result = false;
- CompletionOnceCallback completion_callback =
- base::BindOnce(&CallClosureAfterCheckingResult, closure.closure(),
- base::Unretained(&did_check_result));
- bool queued = boss.DoSomething(std::move(completion_callback));
- EXPECT_TRUE(queued);
- EXPECT_FALSE(did_check_result);
- closure.WaitForResult();
- EXPECT_TRUE(did_check_result);
- }
- // TODO: test deleting ExampleEmployer while work outstanding
- } // namespace net
|