Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / net / base / test_completion_callback_unittest.cc
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
5 // Illustrates how to use worker threads that issue completion callbacks
6
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/threading/worker_pool.h"
11 #include "net/base/completion_callback.h"
12 #include "net/base/test_completion_callback.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "testing/platform_test.h"
15
16 namespace {
17
18 const int kMagicResult = 8888;
19
20 void CallClosureAfterCheckingResult(const base::Closure& closure,
21                                     bool* did_check_result,
22                                     int result) {
23   DCHECK_EQ(result, kMagicResult);
24   *did_check_result = true;
25   closure.Run();
26 }
27
28 // ExampleEmployer is a toy version of HostResolver
29 // TODO: restore damage done in extracting example from real code
30 // (e.g. bring back real destructor, bring back comments)
31 class ExampleEmployer {
32  public:
33   ExampleEmployer();
34   ~ExampleEmployer();
35
36   // Do some imaginary work on a worker thread;
37   // when done, worker posts callback on the original thread.
38   // Returns true on success
39   bool DoSomething(const net::CompletionCallback& callback);
40
41  private:
42   class ExampleWorker;
43   friend class ExampleWorker;
44   scoped_refptr<ExampleWorker> request_;
45   DISALLOW_COPY_AND_ASSIGN(ExampleEmployer);
46 };
47
48 // Helper class; this is how ExampleEmployer puts work on a different thread
49 class ExampleEmployer::ExampleWorker
50     : public base::RefCountedThreadSafe<ExampleWorker> {
51  public:
52   ExampleWorker(ExampleEmployer* employer,
53                 const net::CompletionCallback& callback)
54       : employer_(employer),
55         callback_(callback),
56         origin_loop_(base::MessageLoop::current()) {}
57   void DoWork();
58   void DoCallback();
59  private:
60   friend class base::RefCountedThreadSafe<ExampleWorker>;
61
62   ~ExampleWorker() {}
63
64   // Only used on the origin thread (where DoSomething was called).
65   ExampleEmployer* employer_;
66   net::CompletionCallback callback_;
67   // Used to post ourselves onto the origin thread.
68   base::Lock origin_loop_lock_;
69   base::MessageLoop* origin_loop_;
70 };
71
72 void ExampleEmployer::ExampleWorker::DoWork() {
73   // Running on the worker thread
74   // In a real worker thread, some work would be done here.
75   // Pretend it is, and send the completion callback.
76
77   // The origin loop could go away while we are trying to post to it, so we
78   // need to call its PostTask method inside a lock.  See ~ExampleEmployer.
79   {
80     base::AutoLock locked(origin_loop_lock_);
81     if (origin_loop_)
82       origin_loop_->PostTask(FROM_HERE,
83                              base::Bind(&ExampleWorker::DoCallback, this));
84   }
85 }
86
87 void ExampleEmployer::ExampleWorker::DoCallback() {
88   // Running on the origin thread.
89
90   // Drop the employer_'s reference to us.  Do this before running the
91   // callback since the callback might result in the employer being
92   // destroyed.
93   employer_->request_ = NULL;
94
95   callback_.Run(kMagicResult);
96 }
97
98 ExampleEmployer::ExampleEmployer() {
99 }
100
101 ExampleEmployer::~ExampleEmployer() {
102 }
103
104 bool ExampleEmployer::DoSomething(const net::CompletionCallback& callback) {
105   DCHECK(!request_.get()) << "already in use";
106
107   request_ = new ExampleWorker(this, callback);
108
109   // Dispatch to worker thread...
110   if (!base::WorkerPool::PostTask(
111           FROM_HERE,
112           base::Bind(&ExampleWorker::DoWork, request_.get()),
113           true)) {
114     NOTREACHED();
115     request_ = NULL;
116     return false;
117   }
118
119   return true;
120 }
121
122 }  // namespace
123
124 typedef PlatformTest TestCompletionCallbackTest;
125
126 TEST_F(TestCompletionCallbackTest, Simple) {
127   ExampleEmployer boss;
128   net::TestCompletionCallback callback;
129   bool queued = boss.DoSomething(callback.callback());
130   EXPECT_TRUE(queued);
131   int result = callback.WaitForResult();
132   EXPECT_EQ(result, kMagicResult);
133 }
134
135 TEST_F(TestCompletionCallbackTest, Closure) {
136   ExampleEmployer boss;
137   net::TestClosure closure;
138   bool did_check_result = false;
139   net::CompletionCallback completion_callback =
140       base::Bind(&CallClosureAfterCheckingResult,
141                  closure.closure(), base::Unretained(&did_check_result));
142   bool queued = boss.DoSomething(completion_callback);
143   EXPECT_TRUE(queued);
144
145   EXPECT_FALSE(did_check_result);
146   closure.WaitForResult();
147   EXPECT_TRUE(did_check_result);
148 }
149
150 // TODO: test deleting ExampleEmployer while work outstanding