| // 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()); |
| } |