| /* |
| * Copyright 2011 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| // Author: morlovich@google.com (Maksim Orlovich) |
| |
| // Unit-test for QueuedWorker |
| |
| #include "pagespeed/kernel/thread/queued_worker.h" |
| |
| #include "pagespeed/kernel/base/basictypes.h" |
| #include "pagespeed/kernel/base/function.h" |
| #include "pagespeed/kernel/base/gtest.h" |
| #include "pagespeed/kernel/base/scoped_ptr.h" |
| #include "pagespeed/kernel/thread/worker_test_base.h" |
| |
| namespace net_instaweb { |
| namespace { |
| |
| class QueuedWorkerTest: public WorkerTestBase { |
| public: |
| QueuedWorkerTest() |
| : worker_(new QueuedWorker("queued_worker_test", thread_runtime_.get())) { |
| } |
| |
| protected: |
| scoped_ptr<QueuedWorker> worker_; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(QueuedWorkerTest); |
| }; |
| |
| // A closure that enqueues a new version of itself 'count' times, and |
| // finally schedules the running of the sync-point. |
| class ChainedTask : public Function { |
| public: |
| ChainedTask(int* count, QueuedWorker* worker, WorkerTestBase::SyncPoint* sync) |
| : count_(count), |
| worker_(worker), |
| sync_(sync) { |
| } |
| |
| virtual void Run() { |
| --*count_; |
| if (*count_ > 0) { |
| worker_->RunInWorkThread(new ChainedTask(count_, worker_, sync_)); |
| } else { |
| worker_->RunInWorkThread(new WorkerTestBase::NotifyRunFunction(sync_)); |
| } |
| } |
| |
| private: |
| int* count_; |
| QueuedWorker* worker_; |
| WorkerTestBase::SyncPoint* sync_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ChainedTask); |
| }; |
| |
| TEST_F(QueuedWorkerTest, BasicOperation) { |
| // All the jobs we queued should be run in order |
| const int kBound = 42; |
| int count = 0; |
| SyncPoint sync(thread_runtime_.get()); |
| |
| worker_->Start(); |
| for (int i = 0; i < kBound; ++i) { |
| worker_->RunInWorkThread(new CountFunction(&count)); |
| } |
| |
| worker_->RunInWorkThread(new NotifyRunFunction(&sync)); |
| sync.Wait(); |
| EXPECT_EQ(kBound, count); |
| } |
| |
| TEST_F(QueuedWorkerTest, ChainedTasks) { |
| // The ChainedTask closure ensures that there is always a task |
| // queued until we've executed all 11 tasks in the chain, at which |
| // point the 'notify' function fires and we can complete the test. |
| int count = 11; |
| SyncPoint sync(thread_runtime_.get()); |
| worker_->Start(); |
| worker_->RunInWorkThread(new ChainedTask(&count, worker_.get(), &sync)); |
| sync.Wait(); |
| EXPECT_EQ(0, count); |
| } |
| |
| TEST_F(QueuedWorkerTest, TestShutDown) { |
| // Make sure that shutdown cancels jobs put in after it --- that |
| // the job gets deleted (making clean.Wait() return), and doesn't |
| // run (which would LOG(FATAL)). |
| SyncPoint clean(thread_runtime_.get()); |
| worker_->Start(); |
| worker_->ShutDown(); |
| worker_->RunInWorkThread(new DeleteNotifyFunction(&clean)); |
| clean.Wait(); |
| } |
| |
| TEST_F(QueuedWorkerTest, TestIsBusy) { |
| worker_->Start(); |
| EXPECT_FALSE(worker_->IsBusy()); |
| |
| SyncPoint start_sync(thread_runtime_.get()); |
| worker_->RunInWorkThread(new WaitRunFunction(&start_sync)); |
| EXPECT_TRUE(worker_->IsBusy()); |
| start_sync.Notify(); |
| worker_->ShutDown(); |
| EXPECT_FALSE(worker_->IsBusy()); |
| } |
| |
| } // namespace |
| } // namespace net_instaweb |