1// Copyright 2018 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <fcntl.h>
6#include <unistd.h>
7
8#include <fbl/unique_fd.h>
9#include <fuchsia/io/c/fidl.h>
10#include <lib/async-loop/cpp/loop.h>
11#include <lib/memfs/memfs.h>
12#include <lib/fzl/fdio.h>
13#include <unittest/unittest.h>
14
15namespace {
16
17bool fdio_call_io() {
18    BEGIN_TEST;
19
20    // Create a Memfs filesystem.
21    async::Loop loop(&kAsyncLoopConfigNoAttachToThread);
22    ASSERT_EQ(loop.StartThread(), ZX_OK);
23    ASSERT_EQ(memfs_install_at(loop.dispatcher(), "/my-tmp"), ZX_OK);
24    fbl::unique_fd dir(open("/my-tmp", O_DIRECTORY | O_RDONLY));
25    ASSERT_TRUE(dir);
26
27    // Open a file within the filesystem.
28    fbl::unique_fd fd(openat(dir.get(), "my-file", O_CREAT | O_RDWR));
29    ASSERT_TRUE(fd);
30
31    // Try some filesystem operations natively:
32    fzl::FdioCaller caller(fbl::move(fd));
33    ASSERT_TRUE(caller);
34
35    const char* golden = "foobar";
36    zx_status_t status;
37    uint64_t actual;
38    ASSERT_EQ(fuchsia_io_FileWrite(caller.borrow_channel(),
39                                   reinterpret_cast<const uint8_t*>(golden),
40                                   strlen(golden), &status, &actual),
41              ZX_OK);
42    ASSERT_EQ(status, ZX_OK);
43    ASSERT_EQ(actual, strlen(golden));
44
45    ASSERT_EQ(fuchsia_io_FileSeek(caller.borrow_channel(), 0L, fuchsia_io_SeekOrigin_START,
46                                  &status, &actual),
47              ZX_OK);
48    ASSERT_EQ(status, ZX_OK);
49    ASSERT_EQ(actual, 0);
50
51    char buf[256];
52    ASSERT_EQ(fuchsia_io_FileRead(caller.borrow_channel(), static_cast<uint64_t>(sizeof(buf)),
53                                  &status, reinterpret_cast<uint8_t*>(buf), sizeof(buf), &actual),
54              ZX_OK);
55    ASSERT_EQ(status, ZX_OK);
56    ASSERT_EQ(actual, strlen(golden));
57    ASSERT_EQ(memcmp(buf, golden, strlen(golden)), 0);
58
59    // Re-acquire the underlying fd.
60    fd = caller.release();
61    ASSERT_EQ(close(fd.release()), 0);
62
63    END_TEST;
64}
65
66}  // namespace
67
68BEGIN_TEST_CASE(fdio_call_tests)
69RUN_TEST(fdio_call_io)
70END_TEST_CASE(fdio_call_tests)
71
72