diff options
author | dkegel@google.com <dkegel@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-09-15 23:54:22 +0000 |
---|---|---|
committer | dkegel@google.com <dkegel@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-09-15 23:54:22 +0000 |
commit | 6d5a5e92652f07e86ad7a397d198437853a5f210 (patch) | |
tree | 513a63a21c3461d8b04861c25a98a80249c1a459 | |
parent | 2ed62e2e06281783050df600a7f933557be055a5 (diff) | |
download | chromium_src-6d5a5e92652f07e86ad7a397d198437853a5f210.zip chromium_src-6d5a5e92652f07e86ad7a397d198437853a5f210.tar.gz chromium_src-6d5a5e92652f07e86ad7a397d198437853a5f210.tar.bz2 |
Simple unit test, written mostly just to become familiar with the code.
I've addressed the comments and added the test to the visual studio project. I'll commit when the tree opens.
Review URL: http://codereview.chromium.org/3049
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@2249 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | net/SConscript | 1 | ||||
-rw-r--r-- | net/base/test_completion_callback_unittest.cc | 118 | ||||
-rw-r--r-- | net/build/net_unittests.vcproj | 4 |
3 files changed, 123 insertions, 0 deletions
diff --git a/net/SConscript b/net/SConscript index 0b3fd50..075a032 100644 --- a/net/SConscript +++ b/net/SConscript @@ -222,6 +222,7 @@ unittest_files = [ 'base/net_util_unittest.cc', 'base/registry_controlled_domain_unittest.cc', 'base/run_all_unittests.cc', + 'base/test_completion_callback_unittest.cc', 'disk_cache/addr_unittest.cc', 'disk_cache/block_files_unittest.cc', 'disk_cache/disk_cache_test_base.cc', diff --git a/net/base/test_completion_callback_unittest.cc b/net/base/test_completion_callback_unittest.cc new file mode 100644 index 0000000..23a2448 --- /dev/null +++ b/net/base/test_completion_callback_unittest.cc @@ -0,0 +1,118 @@ +// Copyright (c) 2006-2008 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 worker threads that issue completion callbacks + +#include "testing/gtest/include/gtest/gtest.h" +#include "net/base/completion_callback.h" +#include "net/base/test_completion_callback.h" +#include "base/worker_pool.h" + +using net::CompletionCallback; + +const int kMagicResult = 8888; + +// 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(); + + // Do some imaginary work on a worker thread; + // when done, worker posts callback on the original thread. + // Returns true on success + bool DoSomething(CompletionCallback* callback); + + private: + class ExampleWorker; + friend class ExampleWorker; + scoped_refptr<ExampleWorker> request_; + DISALLOW_COPY_AND_ASSIGN(ExampleEmployer); +}; + +// Helper class; this is how ExampleEmployer puts work on a different thread +class ExampleEmployer::ExampleWorker + : public base::RefCountedThreadSafe<ExampleWorker> { + public: + ExampleWorker(ExampleEmployer* employer, CompletionCallback* callback) + : callback_(callback), + employer_(employer), + origin_loop_(MessageLoop::current()) { + } + void DoWork(); + void DoCallback(); + private: + // Only used on the origin thread (where DoSomething was called). + ExampleEmployer* employer_; + CompletionCallback* callback_; + // Used to post ourselves onto the origin thread. + Lock origin_loop_lock_; + MessageLoop* origin_loop_; +}; + +void ExampleEmployer::ExampleWorker::DoWork() { + // Running on the worker thread + // In a real worker thread, some work would be done here. + // Pretend it is, and send the completion callback. + Task* reply = NewRunnableMethod(this, &ExampleWorker::DoCallback); + + // The origin loop could go away while we are trying to post to it, so we + // need to call its PostTask method inside a lock. See ~ExampleEmployer. + { + AutoLock locked(origin_loop_lock_); + if (origin_loop_) { + origin_loop_->PostTask(FROM_HERE, reply); + reply = NULL; + } + } + + // Does nothing if it got posted. + delete reply; +} + +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_ = NULL; + + callback_->Run(kMagicResult); +} + +ExampleEmployer::ExampleEmployer() { +} + +ExampleEmployer::~ExampleEmployer() { +} + +bool ExampleEmployer::DoSomething(CompletionCallback* callback) { + DCHECK(!request_) << "already in use"; + + request_ = new ExampleWorker(this, callback); + + // Dispatch to worker thread... + if (!WorkerPool::PostTask(FROM_HERE, + NewRunnableMethod(request_.get(), &ExampleWorker::DoWork), true)) { + NOTREACHED(); + request_ = NULL; + return false; + } + + return true; +} + +TEST(TestCompletionCallbackTest, Simple) { + ExampleEmployer boss; + TestCompletionCallback callback; + bool queued = boss.DoSomething(&callback); + EXPECT_EQ(queued, true); + int result = callback.WaitForResult(); + EXPECT_EQ(result, kMagicResult); +} + +// TODO: test deleting ExampleEmployer while work outstanding diff --git a/net/build/net_unittests.vcproj b/net/build/net_unittests.vcproj index d2a0a90..617ef20 100644 --- a/net/build/net_unittests.vcproj +++ b/net/build/net_unittests.vcproj @@ -359,6 +359,10 @@ > </File> <File + RelativePath="..\base\test_completion_callback_unittest.cc" + > + </File> + <File RelativePath="..\base\wininet_util_unittest.cc" > </File> |