blob: 94cb73f5812c1778a19e3608964f61e7b09c9f0b [file] [log] [blame]
// Copyright 2019 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 "delayed-outdir.h"
#include <lib/fdio/directory.h>
#include <lib/fit/bridge.h>
#include <lib/fit/result.h>
#include <lib/fit/single_threaded_executor.h>
#include <zircon/assert.h>
#include <zircon/types.h>
#include <fs/managed_vfs.h>
#include <zxtest/zxtest.h>
// TODO(fxbug.dev/39588): delete this
TEST(DelayedOutdirTest, MessagesWaitForStart) {
// Create a new DelayedOutdir, and initialize it with a new channel
auto delayed_outdir = devmgr::DelayedOutdir();
auto delayed = fidl::CreateEndpoints<::llcpp::fuchsia::io::Directory>();
ASSERT_OK(delayed.status_value());
auto remote_dir = delayed_outdir.Initialize(std::move(delayed->client));
// Put the remote_dir we received from DelayedOutDir in a vfs and run it
auto root = fidl::CreateEndpoints<::llcpp::fuchsia::io::Directory>();
ASSERT_OK(root.status_value());
auto loop = async::Loop(&kAsyncLoopConfigNoAttachToCurrentThread);
auto vfs = fs::ManagedVfs(loop.dispatcher());
vfs.ServeDirectory(remote_dir, std::move(root->server));
loop.StartThread("delayed_outgoing_dir_test");
// Attempt to open "fs/foo" in our vfs, which will forward an open request for
// "foo" into the channel we provided above.
auto foo = fidl::CreateEndpoints<::llcpp::fuchsia::io::Directory>();
ASSERT_OK(foo.status_value());
zx_status_t status = fdio_open_at(root->client.channel().get(), "fs/foo", ZX_FS_RIGHT_READABLE,
foo->server.channel().release());
ASSERT_OK(status);
// If we attempt to read from the channel behind DelayedOutdir, we should see
// ZX_ERR_SHOULD_WAIT because the DelayedOutdir isn't running yet, and thus
// the open we just made hasn't been handled yet.
uint8_t read_buffer[1024];
zx_handle_t handle_buffer[16];
uint32_t actual_bytes = 0;
uint32_t actual_handles = 0;
status = delayed->server.channel().read(0, read_buffer, handle_buffer, sizeof(read_buffer),
sizeof(handle_buffer), &actual_bytes, &actual_handles);
ASSERT_EQ(ZX_ERR_SHOULD_WAIT, status);
// Now let's start the DelayedOutdir, and wait for the channel to become
// readable. Once it's readable, that means our open request from above made
// it through.
delayed_outdir.Start();
zx_signals_t observed;
status = delayed->server.channel().wait_one(ZX_CHANNEL_READABLE, zx::deadline_after(zx::sec(10)),
&observed);
ASSERT_OK(status);
ASSERT_TRUE(observed & ZX_CHANNEL_READABLE);
// Shut down the managed VFS to get it to close active connections, otherwise
// the deconstructor will crash.
fit::bridge<zx_status_t> bridge;
vfs.Shutdown(bridge.completer.bind());
auto promise_shutdown = bridge.consumer.promise_or(::fit::error());
fit::result<zx_status_t, void> result = fit::run_single_threaded(std::move(promise_shutdown));
ASSERT_TRUE(result.is_ok());
ASSERT_OK(result.value());
}