From 30fc8cb6dedb3dabb241471e501933001518bc50 Mon Sep 17 00:00:00 2001 From: Simon Krueger Date: Fri, 6 Dec 2024 15:44:53 -0800 Subject: [PATCH] Add basic tests for fileops functions Summary: Add basic tests for `folly::fileops::{open,read,write,close,pipe}`. These are implemented for windows to handle sockets and /dev/null. They are simple aliases on non-windows. Reviewed By: Orvid Differential Revision: D66838378 fbshipit-source-id: feee6f1f14deebab58d928dc8b31d0012b7d834a --- folly/portability/Unistd.h | 8 +++++ folly/portability/test/BUCK | 24 ++++++++++++++ folly/portability/test/FcntlTest.cpp | 45 +++++++++++++++++++++++++ folly/portability/test/UnistdTest.cpp | 47 +++++++++++++++++++++++++++ 4 files changed, 124 insertions(+) create mode 100644 folly/portability/test/FcntlTest.cpp create mode 100644 folly/portability/test/UnistdTest.cpp diff --git a/folly/portability/Unistd.h b/folly/portability/Unistd.h index f52712c3cae..458683f8fd9 100644 --- a/folly/portability/Unistd.h +++ b/folly/portability/Unistd.h @@ -103,6 +103,14 @@ namespace fileops { #ifdef _WIN32 int close(int fh); ssize_t read(int fh, void* buf, size_t mcc); + +/// Create a pipe, returning the file descriptors in `pth`. +/// +/// On windows this has different behavior than the traditional posix pipe. +/// The returned file descriptors are unix sockets for compatibility with +/// libevent. Also, they allow bidirectional reads and writes, +/// unlike posix which only supports a single direction. +/// @file int pipe(int pth[2]); ssize_t write(int fh, void const* buf, size_t count); #else diff --git a/folly/portability/test/BUCK b/folly/portability/test/BUCK index d53bcae6267..ae73b480652 100644 --- a/folly/portability/test/BUCK +++ b/folly/portability/test/BUCK @@ -1,3 +1,4 @@ +load("@fbcode//target_determinator/macros:ci.bzl", "ci") load("@fbcode_macros//build_defs:cpp_unittest.bzl", "cpp_unittest") oncall("fbcode_entropy_wardens_folly") @@ -11,6 +12,18 @@ cpp_unittest( ], ) +cpp_unittest( + name = "fcntl_test", + srcs = ["FcntlTest.cpp"], + labels = ci.labels( + ci.windows(ci.mode("fbcode//mode/win")), + ), + deps = [ + "//folly/portability:fcntl", + "//folly/portability:unistd", + ], +) + cpp_unittest( name = "filesystem_test", srcs = ["FilesystemTest.cpp"], @@ -57,3 +70,14 @@ cpp_unittest( "//folly/test:test_utils", ], ) + +cpp_unittest( + name = "unistd_test", + srcs = ["UnistdTest.cpp"], + labels = ci.labels( + ci.windows(ci.mode("fbcode//mode/win")), + ), + deps = [ + "//folly/portability:unistd", + ], +) diff --git a/folly/portability/test/FcntlTest.cpp b/folly/portability/test/FcntlTest.cpp new file mode 100644 index 00000000000..b05bf4ff276 --- /dev/null +++ b/folly/portability/test/FcntlTest.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include + +using namespace ::testing; + +/// Test that open supports "/dev/null" on Windows. +/// +/// Windows doesn't have a /dev/null, but it does have +/// NUL, which achieves the same result. +TEST(FcntlTest, OpenDevNull) { + int fd = folly::fileops::open("/dev/null", O_RDWR); + ASSERT_GE(fd, 0); + + ASSERT_EQ(3, folly::fileops::write(fd, "abc", 3)); + + { + char buf[4] = {1, 2, 3, 4}; + // Reads from /dev/null always return 0 for end-of-file (EOF). + ASSERT_EQ(0, folly::fileops::read(fd, buf, 3)); + ASSERT_EQ(buf[0], 1); + ASSERT_EQ(buf[1], 2); + ASSERT_EQ(buf[2], 3); + ASSERT_EQ(buf[3], 4); + } + + ASSERT_EQ(0, folly::fileops::close(fd)); +} diff --git a/folly/portability/test/UnistdTest.cpp b/folly/portability/test/UnistdTest.cpp new file mode 100644 index 00000000000..7df0de87224 --- /dev/null +++ b/folly/portability/test/UnistdTest.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include + +using namespace ::testing; + +/// Simple smoke test of `folly::fileops::{pipe, read, write, close}` functions. +/// +/// On windows, the file descriptors created will be unix sockets, which is +/// normally unsupported by the windows UCRT version of these functions. +/// +/// This tests pipe's ability to perform a write, read, and close. +TEST(UnistdTest, FileOpsSmokeTest) { + int fds[2] = {-1}; + ASSERT_EQ(0, folly::fileops::pipe(fds)); + int readEnd = fds[0]; + int writeEnd = fds[1]; + ASSERT_GE(readEnd, 0); + ASSERT_GE(writeEnd, 0); + + ASSERT_EQ(4, folly::fileops::write(writeEnd, "pika", 4)); + + { + char actual[5] = {0}; + ASSERT_EQ(4, folly::fileops::read(readEnd, actual, 4)); + ASSERT_STREQ("pika", actual); + } + + ASSERT_EQ(0, folly::fileops::close(readEnd)); + ASSERT_EQ(0, folly::fileops::close(writeEnd)); +}