blob: c41860d39acd44a8b3533f8dbebc35c6f6e568d3 [file] [log] [blame]
/*
* 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 SlowWorker
#include "pagespeed/kernel/thread/slow_worker.h"
#include <unistd.h>
#include "base/logging.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 SlowWorkerTest: public WorkerTestBase {
public:
SlowWorkerTest()
: worker_(new SlowWorker("slow_worker_test", thread_runtime_.get())) {
}
protected:
scoped_ptr<SlowWorker> worker_;
private:
DISALLOW_COPY_AND_ASSIGN(SlowWorkerTest);
};
TEST_F(SlowWorkerTest, BasicOperation) {
// Add in a job that waits for our OK before finishing Run() and an another
// job that fails if Run. Since we don't let the first one proceed, the second
// one should be deleted immediately.
SyncPoint start_sync(thread_runtime_.get());
SyncPoint delete_sync(thread_runtime_.get());
worker_->Start();
worker_->RunIfNotBusy(new WaitRunFunction(&start_sync));
worker_->RunIfNotBusy(new DeleteNotifyFunction(&delete_sync));
delete_sync.Wait();
start_sync.Notify();
// Make sure we kill the thread now, so we don't get it accessing
// deleted start_sync after we exit if it's slow to start
worker_.reset(NULL);
}
class WaitCancelFunction : public Function {
public:
explicit WaitCancelFunction(WorkerTestBase::SyncPoint* sync) : sync_(sync) {}
virtual void Run() {
sync_->Notify();
while (!quit_requested()) {
usleep(10);
}
}
private:
WorkerTestBase::SyncPoint* sync_;
DISALLOW_COPY_AND_ASSIGN(WaitCancelFunction);
};
TEST_F(SlowWorkerTest, Cancellation) {
// Used to wait for thread to actually start, so we don't see it
// being deleted w/o being started as confirming that exit is working
SyncPoint start_sync(thread_runtime_.get());
worker_->Start();
worker_->RunIfNotBusy(new WaitCancelFunction(&start_sync));
// Wait for the thread to start...
start_sync.Wait();
// Ask for exit and block on that.
worker_.reset(NULL);
}
// Used to check that quit_requested is false by default normally.
class CheckDefaultCancelFunction : public WorkerTestBase::NotifyRunFunction {
public:
explicit CheckDefaultCancelFunction(WorkerTestBase::SyncPoint* sync)
: NotifyRunFunction(sync) {}
virtual void Run() {
CHECK(!quit_requested());
NotifyRunFunction::Run();
}
};
TEST_F(SlowWorkerTest, CancelDefaultFalse) {
SyncPoint start_sync(thread_runtime_.get());
worker_->Start();
worker_->RunIfNotBusy(new CheckDefaultCancelFunction(&start_sync));
start_sync.Wait();
}
} // namespace
} // namespace net_instaweb