blob: 2f7e722971f19f058f1a90403aeac3f894326abd [file] [log] [blame]
// Copyright 2020 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 "src/lib/fuchsia-async/cpp/executor.h"
#include <lib/async/receiver.h>
#include <lib/async/task.h>
#include <lib/async/time.h>
#include <lib/async/trap.h>
#include <lib/async/wait.h>
#include <gtest/gtest.h>
#ifdef __Fuchsia__
#include <zircon/syscalls.h>
#endif
namespace fuchsia_async {
namespace testing {
TEST(FuchsiaAsync, CanCreateAndExitLoop) { Executor executor; }
TEST(FuchsiaAsync, SomeOperationsAreUnsupported) {
Executor executor;
auto* dispatcher = executor.dispatcher();
EXPECT_EQ(ZX_ERR_NOT_SUPPORTED, async_queue_packet(dispatcher, nullptr, nullptr));
EXPECT_EQ(ZX_ERR_NOT_SUPPORTED, async_set_guest_bell_trap(dispatcher, nullptr, 0, 0, 0));
}
template <class F>
void PostTask(Executor* executor, F impl) {
struct Task {
async_task_t task;
F impl;
static void Handler(async_dispatcher_t* dispatcher, async_task_t* task, zx_status_t status) {
auto* t = reinterpret_cast<Task*>(task);
t->impl();
delete t;
}
};
Task* task = new Task{{
ASYNC_STATE_INIT,
Task::Handler,
async_now(executor->dispatcher()),
},
std::move(impl)};
EXPECT_EQ(ZX_OK, async_post_task(executor->dispatcher(), &task->task));
}
TEST(FuchsiaAsync, CanPostTask) {
Executor executor;
PostTask(&executor, [&executor]() { executor.Quit(); });
executor.RunSinglethreaded();
}
template <class F>
void PostWait(Executor* executor, zx_handle_t handle, zx_signals_t trigger, F impl) {
struct Wait {
async_wait_t wait;
F impl;
static void Handler(async_dispatcher_t* dispatcher, async_wait_t* wait, zx_status_t status,
const zx_packet_signal_t* signal) {
auto* w = reinterpret_cast<Wait*>(wait);
w->impl(status, signal);
delete w;
}
};
Wait* wait = new Wait{{ASYNC_STATE_INIT, Wait::Handler, handle, trigger, 0}, std::move(impl)};
EXPECT_EQ(ZX_OK, async_begin_wait(executor->dispatcher(), &wait->wait));
}
// TODO: make this available for host also
#ifdef __Fuchsia__
TEST(FuchsiaAsync, CanWaitForRead) {
Executor executor;
zx_handle_t a, b;
ASSERT_EQ(ZX_OK, zx_channel_create(0, &a, &b));
fprintf(stderr, "made channels %u %u\n", a, b);
bool write_queued = false;
PostWait(&executor, b, ZX_CHANNEL_READABLE,
[&executor, &write_queued](zx_status_t status, const zx_packet_signal_t* signal) {
EXPECT_EQ(true, write_queued);
EXPECT_EQ(ZX_OK, status);
EXPECT_TRUE((signal->observed & ZX_CHANNEL_READABLE) != 0);
executor.Quit();
});
PostTask(&executor, [a, &write_queued]() {
EXPECT_EQ(false, write_queued);
fprintf(stderr, "write to channel %u\n", a);
ASSERT_EQ(ZX_OK, zx_channel_write(a, 0, nullptr, 0, nullptr, 0));
write_queued = true;
});
executor.RunSinglethreaded();
zx_handle_close(a);
zx_handle_close(b);
}
#endif
} // namespace testing
} // namespace fuchsia_async