blob: e7716f0759bad55c9b58cf1b305a15c53d1f0aa0 [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <async/auto_task.h>
#include <async/task.h>
#include <unittest/unittest.h>
#include "async_stub.h"
namespace {
class MockAsync : public AsyncStub {
public:
enum class Op {
NONE,
POST_TASK,
CANCEL_TASK,
};
Op last_op = Op::NONE;
async_task_t* last_task = nullptr;
zx_status_t PostTask(async_task_t* task) override {
last_op = Op::POST_TASK;
last_task = task;
return ZX_OK;
}
zx_status_t CancelTask(async_task_t* task) override {
last_op = Op::CANCEL_TASK;
last_task = task;
return ZX_OK;
}
};
template <typename TTask>
struct Handler {
Handler(TTask* task, async_task_result_t result = ASYNC_TASK_REPEAT)
: result(result) {
task->set_handler([this](async_t* async, zx_status_t status) {
handler_ran = true;
last_status = status;
return this->result;
});
}
async_task_result_t result;
bool handler_ran = false;
zx_status_t last_status = ZX_ERR_INTERNAL;
};
bool task_test() {
const zx_time_t dummy_deadline = 1;
const uint32_t dummy_flags = ASYNC_FLAG_HANDLE_SHUTDOWN;
BEGIN_TEST;
{
async::Task default_task;
EXPECT_EQ(ZX_TIME_INFINITE, default_task.deadline(), "default deadline");
EXPECT_EQ(0u, default_task.flags(), "default flags");
default_task.set_deadline(dummy_deadline);
EXPECT_EQ(dummy_deadline, default_task.deadline(), "set deadline");
default_task.set_flags(dummy_flags);
EXPECT_EQ(dummy_flags, default_task.flags(), "set flags");
EXPECT_FALSE(!!default_task.handler(), "handler");
}
{
async::Task explicit_task(dummy_deadline, dummy_flags);
EXPECT_EQ(dummy_deadline, explicit_task.deadline(), "explicit deadline");
EXPECT_EQ(dummy_flags, explicit_task.flags(), "explicit flags");
// begin a repeating task
EXPECT_FALSE(!!explicit_task.handler(), "handler");
Handler<async::Task> handler(&explicit_task, ASYNC_TASK_REPEAT);
EXPECT_TRUE(!!explicit_task.handler(), "handler");
MockAsync async;
EXPECT_EQ(ZX_OK, explicit_task.Post(&async), "post, valid args");
EXPECT_EQ(MockAsync::Op::POST_TASK, async.last_op, "op");
EXPECT_EQ(dummy_deadline, async.last_task->deadline, "deadline");
EXPECT_EQ(dummy_flags, async.last_task->flags, "flags");
EXPECT_EQ(ASYNC_TASK_REPEAT,
async.last_task->handler(&async, async.last_task, ZX_OK),
"invoke handler");
EXPECT_TRUE(handler.handler_ran, "handler ran");
EXPECT_EQ(ZX_OK, handler.last_status, "status");
// cancel the task
EXPECT_EQ(ZX_OK, explicit_task.Cancel(&async), "cancel, valid args");
EXPECT_EQ(MockAsync::Op::CANCEL_TASK, async.last_op, "op");
}
END_TEST;
}
bool auto_task_test() {
const zx_time_t dummy_deadline = 1;
const uint32_t dummy_flags = ASYNC_FLAG_HANDLE_SHUTDOWN;
BEGIN_TEST;
MockAsync async;
{
async::AutoTask default_task(&async);
EXPECT_EQ(&async, default_task.async());
EXPECT_FALSE(default_task.is_pending());
EXPECT_EQ(ZX_TIME_INFINITE, default_task.deadline(), "default deadline");
EXPECT_EQ(0u, default_task.flags(), "default flags");
default_task.set_deadline(dummy_deadline);
EXPECT_EQ(dummy_deadline, default_task.deadline(), "set deadline");
default_task.set_flags(dummy_flags);
EXPECT_EQ(dummy_flags, default_task.flags(), "set flags");
EXPECT_FALSE(!!default_task.handler(), "handler");
}
EXPECT_EQ(MockAsync::Op::NONE, async.last_op, "op");
{
async::AutoTask explicit_task(&async, dummy_deadline, dummy_flags);
EXPECT_EQ(&async, explicit_task.async());
EXPECT_FALSE(explicit_task.is_pending());
EXPECT_EQ(dummy_deadline, explicit_task.deadline(), "explicit deadline");
EXPECT_EQ(dummy_flags, explicit_task.flags(), "explicit flags");
// post a non-repeating task
EXPECT_FALSE(!!explicit_task.handler(), "handler");
Handler<async::AutoTask> handler(&explicit_task, ASYNC_TASK_FINISHED);
EXPECT_TRUE(!!explicit_task.handler(), "handler");
EXPECT_EQ(ZX_OK, explicit_task.Post(), "post, valid args");
EXPECT_TRUE(explicit_task.is_pending());
EXPECT_EQ(MockAsync::Op::POST_TASK, async.last_op, "op");
EXPECT_EQ(dummy_deadline, async.last_task->deadline, "deadline");
EXPECT_EQ(dummy_flags, async.last_task->flags, "flags");
EXPECT_EQ(ASYNC_TASK_FINISHED,
async.last_task->handler(&async, async.last_task, ZX_OK),
"invoke handler");
EXPECT_TRUE(handler.handler_ran, "handler ran");
EXPECT_EQ(ZX_OK, handler.last_status, "status");
// post a repeating task
handler.result = ASYNC_TASK_REPEAT;
EXPECT_EQ(ZX_OK, explicit_task.Post(), "post, valid args");
EXPECT_TRUE(explicit_task.is_pending());
EXPECT_EQ(MockAsync::Op::POST_TASK, async.last_op, "op");
EXPECT_EQ(dummy_deadline, async.last_task->deadline, "deadline");
EXPECT_EQ(dummy_flags, async.last_task->flags, "flags");
EXPECT_EQ(ASYNC_TASK_REPEAT,
async.last_task->handler(&async, async.last_task, ZX_OK),
"invoke handler");
EXPECT_TRUE(handler.handler_ran, "handler ran");
EXPECT_EQ(ZX_OK, handler.last_status, "status");
// cancel the task
explicit_task.Cancel();
EXPECT_EQ(MockAsync::Op::CANCEL_TASK, async.last_op, "op");
EXPECT_FALSE(explicit_task.is_pending());
// post the task again then let it go out of scope
EXPECT_EQ(ZX_OK, explicit_task.Post(), "post, valid args");
EXPECT_TRUE(explicit_task.is_pending());
EXPECT_EQ(MockAsync::Op::POST_TASK, async.last_op, "op");
}
EXPECT_EQ(MockAsync::Op::CANCEL_TASK, async.last_op, "op");
END_TEST;
}
bool unsupported_post_task_test() {
BEGIN_TEST;
AsyncStub async;
async_task_t task{};
EXPECT_EQ(ZX_ERR_NOT_SUPPORTED, async_post_task(&async, &task), "valid args");
END_TEST;
}
bool unsupported_cancel_task_test() {
BEGIN_TEST;
AsyncStub async;
async_task_t task{};
EXPECT_EQ(ZX_ERR_NOT_SUPPORTED, async_cancel_task(&async, &task), "valid args");
END_TEST;
}
} // namespace
BEGIN_TEST_CASE(task_tests)
RUN_TEST(task_test)
RUN_TEST(auto_task_test)
RUN_TEST(unsupported_post_task_test)
RUN_TEST(unsupported_cancel_task_test)
END_TEST_CASE(task_tests)