| // 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) |