aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/test/cpp
diff options
context:
space:
mode:
authorGravatar Laszlo Csomor <laszlocsomor@google.com>2016-12-16 10:25:14 +0000
committerGravatar John Cater <jcater@google.com>2016-12-16 15:36:57 +0000
commit1324e83e04757b45b78b01a1ab24bab4c6156231 (patch)
tree3188bfee0fe47a96c91dd465a371802c46cea046 /src/test/cpp
parent52b34308428cfd117470c966d8df329f686fb9ed (diff)
Bazel client, Windows: implement pipe handling
Create WindowsPipe which implements IPipe, and is a Windows-native implementation of pipe handling. It wraps the ::CreatePipe, ::WriteFile, and ::ReadFile API functions. Start using WindowsPipe on MSYS. Also move everything from file_test.cc into file_posix_test.cc, because these test methods heavily depend on POSIX and they test file_posix's functionality anyway. Also add tests for pipes: this will use the platform-specific implementation of IPipe. file_test.cc is now platform-independent, and we can test it with --cpu=x64_windows_msvc (and it passes!). See https://github.com/bazelbuild/bazel/issues/2107 Might also fix: https://github.com/bazelbuild/bazel/issues/2182 https://github.com/bazelbuild/bazel/issues/2248 -- PiperOrigin-RevId: 142240377 MOS_MIGRATED_REVID=142240377
Diffstat (limited to 'src/test/cpp')
-rw-r--r--src/test/cpp/util/BUILD11
-rw-r--r--src/test/cpp/util/file_posix_test.cc139
-rw-r--r--src/test/cpp/util/file_test.cc167
3 files changed, 171 insertions, 146 deletions
diff --git a/src/test/cpp/util/BUILD b/src/test/cpp/util/BUILD
index 033fca6268..e16f14f4ce 100644
--- a/src/test/cpp/util/BUILD
+++ b/src/test/cpp/util/BUILD
@@ -20,10 +20,13 @@ cc_test(
cc_test(
name = "file_test",
- srcs = [
- "file_posix_test.cc",
- "file_test.cc",
- ],
+ srcs = ["file_test.cc"] + select({
+ "//src:windows_msvc": [
+ ],
+ "//conditions:default": [
+ "file_posix_test.cc",
+ ],
+ }),
tags = ["manual"],
deps = [
"//src/main/cpp/util:file",
diff --git a/src/test/cpp/util/file_posix_test.cc b/src/test/cpp/util/file_posix_test.cc
index 446ada9790..bd91343672 100644
--- a/src/test/cpp/util/file_posix_test.cc
+++ b/src/test/cpp/util/file_posix_test.cc
@@ -16,6 +16,7 @@
#include <algorithm>
+#include "src/main/cpp/util/file.h"
#include "src/main/cpp/util/file_platform.h"
#include "gtest/gtest.h"
@@ -25,6 +26,144 @@ using std::pair;
using std::string;
using std::vector;
+static bool Symlink(const string& old_path, const string& new_path) {
+ return symlink(old_path.c_str(), new_path.c_str()) == 0;
+}
+
+static bool CreateEmptyFile(const string& path) {
+ // From the man page of open (man 2 open):
+ // int open(const char *pathname, int flags, mode_t mode);
+ //
+ // mode specifies the permissions to use in case a new file is created.
+ // This argument must be supplied when O_CREAT is specified in flags;
+ // if O_CREAT is not specified, then mode is ignored.
+ int fd = open(path.c_str(), O_CREAT | O_WRONLY, 0700);
+ if (fd == -1) {
+ return false;
+ }
+ return close(fd) == 0;
+}
+
+TEST(FileTest, JoinPath) {
+ std::string path = JoinPath("", "");
+ ASSERT_EQ("", path);
+
+ path = JoinPath("a", "b");
+ ASSERT_EQ("a/b", path);
+
+ path = JoinPath("a/", "b");
+ ASSERT_EQ("a/b", path);
+
+ path = JoinPath("a", "/b");
+ ASSERT_EQ("a/b", path);
+
+ path = JoinPath("a/", "/b");
+ ASSERT_EQ("a/b", path);
+
+ path = JoinPath("/", "/");
+ ASSERT_EQ("/", path);
+}
+
+void MockDirectoryListingFunction(const string& path,
+ DirectoryEntryConsumer* consume) {
+ if (path == "root") {
+ consume->Consume("root/file1", false);
+ consume->Consume("root/dir2", true);
+ consume->Consume("root/dir1", true);
+ } else if (path == "root/dir1") {
+ consume->Consume("root/dir1/dir3", true);
+ consume->Consume("root/dir1/file2", false);
+ } else if (path == "root/dir2") {
+ consume->Consume("root/dir2/file3", false);
+ } else if (path == "root/dir1/dir3") {
+ consume->Consume("root/dir1/dir3/file4", false);
+ consume->Consume("root/dir1/dir3/file5", false);
+ } else {
+ // Unexpected path
+ GTEST_FAIL();
+ }
+}
+
+TEST(FileTest, GetAllFilesUnder) {
+ vector<string> result;
+ _GetAllFilesUnder("root", &result, &MockDirectoryListingFunction);
+ std::sort(result.begin(), result.end());
+
+ vector<string> expected({"root/dir1/dir3/file4", "root/dir1/dir3/file5",
+ "root/dir1/file2", "root/dir2/file3", "root/file1"});
+ ASSERT_EQ(expected, result);
+}
+
+TEST(FileTest, MakeDirectories) {
+ const char* tmp_dir = getenv("TEST_TMPDIR");
+ ASSERT_STRNE(tmp_dir, NULL);
+ const char* test_src_dir = getenv("TEST_SRCDIR");
+ ASSERT_STRNE(NULL, test_src_dir);
+
+ string dir = JoinPath(tmp_dir, "x/y/z");
+ bool ok = MakeDirectories(dir, 0755);
+ ASSERT_TRUE(ok);
+
+ // Changing permissions on an existing dir should work.
+ ok = MakeDirectories(dir, 0750);
+ ASSERT_TRUE(ok);
+ struct stat filestat = {};
+ ASSERT_EQ(0, stat(dir.c_str(), &filestat));
+ ASSERT_EQ(0750, filestat.st_mode & 0777);
+
+ // srcdir shouldn't be writable.
+ // TODO(ulfjack): Fix this!
+ // string srcdir = JoinPath(test_src_dir, "x/y/z");
+ // ok = MakeDirectories(srcdir, 0755);
+ // ASSERT_FALSE(ok);
+ // ASSERT_EQ(EACCES, errno);
+
+ // Can't make a dir out of a file.
+ string non_dir = JoinPath(dir, "w");
+ ASSERT_TRUE(CreateEmptyFile(non_dir));
+ ok = MakeDirectories(non_dir, 0755);
+ ASSERT_FALSE(ok);
+ ASSERT_EQ(ENOTDIR, errno);
+
+ // Valid symlink should work.
+ string symlink = JoinPath(tmp_dir, "z");
+ ASSERT_TRUE(Symlink(dir, symlink));
+ ok = MakeDirectories(symlink, 0755);
+ ASSERT_TRUE(ok);
+
+ // Error: Symlink to a file.
+ symlink = JoinPath(tmp_dir, "w");
+ ASSERT_TRUE(Symlink(non_dir, symlink));
+ ok = MakeDirectories(symlink, 0755);
+ ASSERT_FALSE(ok);
+ ASSERT_EQ(ENOTDIR, errno);
+
+ // Error: Symlink to a dir with wrong perms.
+ symlink = JoinPath(tmp_dir, "s");
+ ASSERT_TRUE(Symlink("/", symlink));
+
+ // These perms will force a chmod()
+ // TODO(ulfjack): Fix this!
+ // ok = MakeDirectories(symlink, 0000);
+ // ASSERTFALSE(ok);
+ // ASSERT_EQ(EPERM, errno);
+
+ // Edge cases.
+ ASSERT_FALSE(MakeDirectories("", 0755));
+ ASSERT_EQ(EACCES, errno);
+ ASSERT_FALSE(MakeDirectories("/", 0755));
+ ASSERT_EQ(EACCES, errno);
+}
+
+TEST(FileTest, HammerMakeDirectories) {
+ const char* tmp_dir = getenv("TEST_TMPDIR");
+ ASSERT_STRNE(tmp_dir, NULL);
+
+ string path = JoinPath(tmp_dir, "x/y/z");
+ // TODO(ulfjack): Fix this!
+ // ASSERT_LE(0, fork());
+ // ASSERT_TRUE(MakeDirectories(path, 0755));
+}
TEST(FilePosixTest, Which) {
ASSERT_EQ("", Which(""));
ASSERT_EQ("", Which("foo"));
diff --git a/src/test/cpp/util/file_test.cc b/src/test/cpp/util/file_test.cc
index eca1ab2ae0..49c52c0533 100644
--- a/src/test/cpp/util/file_test.cc
+++ b/src/test/cpp/util/file_test.cc
@@ -11,9 +11,10 @@
// 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 <fcntl.h>
-#include <unistd.h>
-#include <algorithm>
+#include <string.h>
+
+#include <memory> // unique_ptr
+#include <thread> // NOLINT (to slience Google-internal linter)
#include "src/main/cpp/util/file.h"
#include "src/main/cpp/util/file_platform.h"
@@ -21,149 +22,31 @@
namespace blaze_util {
-using std::string;
-using std::vector;
-
-static bool Symlink(const string& old_path, const string& new_path) {
- return symlink(old_path.c_str(), new_path.c_str()) == 0;
-}
-
-static bool CreateEmptyFile(const string& path) {
- // From the man page of open (man 2 open):
- // int open(const char *pathname, int flags, mode_t mode);
- //
- // mode specifies the permissions to use in case a new file is created.
- // This argument must be supplied when O_CREAT is specified in flags;
- // if O_CREAT is not specified, then mode is ignored.
- int fd = open(path.c_str(), O_CREAT | O_WRONLY, 0700);
- if (fd == -1) {
- return false;
- }
- return close(fd) == 0;
-}
-
-TEST(FileTest, JoinPath) {
- std::string path = JoinPath("", "");
- ASSERT_EQ("", path);
-
- path = JoinPath("a", "b");
- ASSERT_EQ("a/b", path);
-
- path = JoinPath("a/", "b");
- ASSERT_EQ("a/b", path);
-
- path = JoinPath("a", "/b");
- ASSERT_EQ("a/b", path);
-
- path = JoinPath("a/", "/b");
- ASSERT_EQ("a/b", path);
-
- path = JoinPath("/", "/");
- ASSERT_EQ("/", path);
-}
-
-void MockDirectoryListingFunction(const string &path,
- DirectoryEntryConsumer *consume) {
- if (path == "root") {
- consume->Consume("root/file1", false);
- consume->Consume("root/dir2", true);
- consume->Consume("root/dir1", true);
- } else if (path == "root/dir1") {
- consume->Consume("root/dir1/dir3", true);
- consume->Consume("root/dir1/file2", false);
- } else if (path == "root/dir2") {
- consume->Consume("root/dir2/file3", false);
- } else if (path == "root/dir1/dir3") {
- consume->Consume("root/dir1/dir3/file4", false);
- consume->Consume("root/dir1/dir3/file5", false);
- } else {
- // Unexpected path
- GTEST_FAIL();
- }
+TEST(FileTest, TestSingleThreadedPipe) {
+ std::unique_ptr<IPipe> pipe(CreatePipe());
+ char buffer[50] = {0};
+ ASSERT_TRUE(pipe.get()->Send("hello", 5));
+ ASSERT_EQ(3, pipe.get()->Receive(buffer, 3));
+ ASSERT_TRUE(pipe.get()->Send(" world", 6));
+ ASSERT_EQ(5, pipe.get()->Receive(buffer + 3, 5));
+ ASSERT_EQ(3, pipe.get()->Receive(buffer + 8, 40));
+ ASSERT_EQ(0, strncmp(buffer, "hello world", 11));
}
-TEST(FileTest, GetAllFilesUnder) {
- vector<string> result;
- _GetAllFilesUnder("root", &result, &MockDirectoryListingFunction);
- std::sort(result.begin(), result.end());
-
- vector<string> expected({"root/dir1/dir3/file4",
- "root/dir1/dir3/file5",
- "root/dir1/file2",
- "root/dir2/file3",
- "root/file1"});
- ASSERT_EQ(expected, result);
-}
-
-TEST(FileTest, MakeDirectories) {
- const char* tmp_dir = getenv("TEST_TMPDIR");
- ASSERT_STRNE(tmp_dir, NULL);
- const char* test_src_dir = getenv("TEST_SRCDIR");
- ASSERT_STRNE(NULL, test_src_dir);
-
- string dir = JoinPath(tmp_dir, "x/y/z");
- bool ok = MakeDirectories(dir, 0755);
- ASSERT_TRUE(ok);
-
- // Changing permissions on an existing dir should work.
- ok = MakeDirectories(dir, 0750);
- ASSERT_TRUE(ok);
- struct stat filestat = {};
- ASSERT_EQ(0, stat(dir.c_str(), &filestat));
- ASSERT_EQ(0750, filestat.st_mode & 0777);
-
- // srcdir shouldn't be writable.
- // TODO(ulfjack): Fix this!
- // string srcdir = JoinPath(test_src_dir, "x/y/z");
- // ok = MakeDirectories(srcdir, 0755);
- // ASSERT_FALSE(ok);
- // ASSERT_EQ(EACCES, errno);
-
- // Can't make a dir out of a file.
- string non_dir = JoinPath(dir, "w");
- ASSERT_TRUE(CreateEmptyFile(non_dir));
- ok = MakeDirectories(non_dir, 0755);
- ASSERT_FALSE(ok);
- ASSERT_EQ(ENOTDIR, errno);
-
- // Valid symlink should work.
- string symlink = JoinPath(tmp_dir, "z");
- ASSERT_TRUE(Symlink(dir, symlink));
- ok = MakeDirectories(symlink, 0755);
- ASSERT_TRUE(ok);
-
- // Error: Symlink to a file.
- symlink = JoinPath(tmp_dir, "w");
- ASSERT_TRUE(Symlink(non_dir, symlink));
- ok = MakeDirectories(symlink, 0755);
- ASSERT_FALSE(ok);
- ASSERT_EQ(ENOTDIR, errno);
-
- // Error: Symlink to a dir with wrong perms.
- symlink = JoinPath(tmp_dir, "s");
- ASSERT_TRUE(Symlink("/", symlink));
-
- // These perms will force a chmod()
- // TODO(ulfjack): Fix this!
- // ok = MakeDirectories(symlink, 0000);
- // ASSERTFALSE(ok);
- // ASSERT_EQ(EPERM, errno);
-
- // Edge cases.
- ASSERT_FALSE(MakeDirectories("", 0755));
- ASSERT_EQ(EACCES, errno);
- ASSERT_FALSE(MakeDirectories("/", 0755));
- ASSERT_EQ(EACCES, errno);
-}
+TEST(FileTest, TestMultiThreadedPipe) {
+ std::unique_ptr<IPipe> pipe(CreatePipe());
+ char buffer[50] = {0};
+ std::thread writer_thread([&pipe]() {
+ ASSERT_TRUE(pipe.get()->Send("hello", 5));
+ ASSERT_TRUE(pipe.get()->Send(" world", 6));
+ });
-TEST(FileTest, HammerMakeDirectories) {
- const char* tmp_dir = getenv("TEST_TMPDIR");
- ASSERT_STRNE(tmp_dir, NULL);
+ ASSERT_EQ(3, pipe.get()->Receive(buffer, 3));
+ ASSERT_EQ(5, pipe.get()->Receive(buffer + 3, 5));
+ ASSERT_EQ(3, pipe.get()->Receive(buffer + 8, 40));
+ writer_thread.join();
- string path = JoinPath(tmp_dir, "x/y/z");
- // TODO(ulfjack): Fix this!
- // ASSERT_LE(0, fork());
- // ASSERT_TRUE(MakeDirectories(path, 0755));
+ ASSERT_EQ(0, strncmp(buffer, "hello world", 11));
}
} // namespace blaze_util