Damien Martin-Guillerez | f88f4d8 | 2015-09-25 13:56:55 +0000 | [diff] [blame] | 1 | // Copyright 2015 The Bazel Authors. All rights reserved. |
Ulf Adams | 7a046e1 | 2015-09-07 10:57:46 +0000 | [diff] [blame] | 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | |
Mostyn Bramley-Moore | 44e8d10 | 2015-11-10 11:27:39 +0000 | [diff] [blame] | 15 | #include <errno.h> |
Ulf Adams | 7a046e1 | 2015-09-07 10:57:46 +0000 | [diff] [blame] | 16 | #include <fcntl.h> |
| 17 | #include <stddef.h> |
| 18 | #include <stdlib.h> |
| 19 | #include <unistd.h> |
| 20 | #include <string> |
| 21 | #include <vector> |
| 22 | |
Ulf Adams | 2aad9d7 | 2015-09-08 08:43:40 +0000 | [diff] [blame] | 23 | #include "src/main/cpp/blaze_util.h" |
Laszlo Csomor | cefa9a2 | 2016-11-22 10:50:07 +0000 | [diff] [blame] | 24 | #include "src/main/cpp/blaze_util_platform.h" |
Ulf Adams | 2aad9d7 | 2015-09-08 08:43:40 +0000 | [diff] [blame] | 25 | #include "src/main/cpp/util/file.h" |
Ulf Adams | 7a046e1 | 2015-09-07 10:57:46 +0000 | [diff] [blame] | 26 | #include "gtest/gtest.h" |
| 27 | |
| 28 | namespace blaze { |
| 29 | |
Thiago Farina | 80bb0f2 | 2016-10-17 15:57:13 +0000 | [diff] [blame] | 30 | using std::string; |
| 31 | |
Ulf Adams | 7a046e1 | 2015-09-07 10:57:46 +0000 | [diff] [blame] | 32 | static bool Symlink(const string& old_path, const string& new_path) { |
| 33 | return symlink(old_path.c_str(), new_path.c_str()) == 0; |
| 34 | } |
| 35 | |
| 36 | static bool CreateEmptyFile(const string& path) { |
Luis Fernando Pino Duque | 738c892 | 2016-10-26 20:48:09 +0000 | [diff] [blame] | 37 | // From the man page of open (man 2 open): |
| 38 | // int open(const char *pathname, int flags, mode_t mode); |
| 39 | // |
| 40 | // mode specifies the permissions to use in case a new file is created. |
| 41 | // This argument must be supplied when O_CREAT is specified in flags; |
| 42 | // if O_CREAT is not specified, then mode is ignored. |
| 43 | int fd = open(path.c_str(), O_CREAT | O_WRONLY, 0700); |
Ulf Adams | 7a046e1 | 2015-09-07 10:57:46 +0000 | [diff] [blame] | 44 | if (fd == -1) { |
| 45 | return false; |
| 46 | } |
| 47 | return close(fd) == 0; |
| 48 | } |
| 49 | |
| 50 | class BlazeUtilTest : public ::testing::Test { |
| 51 | protected: |
| 52 | BlazeUtilTest() { |
| 53 | } |
| 54 | |
| 55 | virtual ~BlazeUtilTest() { |
| 56 | } |
| 57 | |
| 58 | static void ForkAndWrite(int fds[], string input1, string input2) { |
| 59 | int r = fork(); |
| 60 | if (r == 0) { |
| 61 | close(fds[0]); |
| 62 | write(fds[1], input1.c_str(), input1.size()); |
| 63 | usleep(500); // sleep for 50ms |
| 64 | write(fds[1], input2.c_str(), input2.size()); |
| 65 | close(fds[1]); |
| 66 | exit(0); |
| 67 | } else if (r < 0) { |
| 68 | perror("fork()"); |
| 69 | FAIL(); |
| 70 | } else { |
| 71 | close(fds[1]); |
| 72 | } |
| 73 | } |
| 74 | |
| 75 | static int WriteFileDescriptor2(string input1, string input2) { |
| 76 | // create a fd for the input string |
| 77 | int fds[2]; |
Damien Martin-Guillerez | 87a3c49 | 2015-09-08 11:19:40 +0000 | [diff] [blame] | 78 | if (pipe(fds) == -1) { |
| 79 | return -1; |
| 80 | } |
| 81 | if (fcntl(fds[0], F_SETFL, O_NONBLOCK) == -1 |
| 82 | || fcntl(fds[1], F_SETFL, O_NONBLOCK) == -1) { |
Ulf Adams | 7a046e1 | 2015-09-07 10:57:46 +0000 | [diff] [blame] | 83 | return -1; |
| 84 | } |
| 85 | if (input2.size() > 0) { |
| 86 | ForkAndWrite(fds, input1, input2); |
| 87 | } else { |
| 88 | write(fds[1], input1.c_str(), input1.size()); |
| 89 | close(fds[1]); |
| 90 | } |
| 91 | return fds[0]; |
| 92 | } |
| 93 | |
| 94 | static void AssertReadFileDescriptor2(string input1, string input2) { |
| 95 | int fd = WriteFileDescriptor2(input1, input2); |
| 96 | if (fd < 0) { |
| 97 | FAIL() << "Unable to create a pipe!"; |
| 98 | } else { |
| 99 | string result; |
| 100 | if (!ReadFileDescriptor(fd, &result)) { |
| 101 | perror("ReadFileDescriptor"); |
| 102 | FAIL() << "Unable to read file descriptor!"; |
| 103 | } else { |
| 104 | ASSERT_EQ(input1 + input2, result); |
| 105 | } |
| 106 | } |
| 107 | } |
| 108 | |
| 109 | static void AssertReadFileDescriptor(string input) { |
| 110 | AssertReadFileDescriptor2(input, ""); |
| 111 | } |
| 112 | |
Ulf Adams | 7a046e1 | 2015-09-07 10:57:46 +0000 | [diff] [blame] | 113 | static void AssertReadJvmVersion(string expected, string input) { |
Lukacs Berki | 00d613a | 2016-04-25 15:39:28 +0000 | [diff] [blame] | 114 | ASSERT_EQ(expected, ReadJvmVersion(input)); |
Ulf Adams | 7a046e1 | 2015-09-07 10:57:46 +0000 | [diff] [blame] | 115 | } |
| 116 | |
| 117 | void ReadFileDescriptorTest() const { |
| 118 | AssertReadFileDescriptor("DummyJDK Blabla\n" |
Lukacs Berki | 00d613a | 2016-04-25 15:39:28 +0000 | [diff] [blame] | 119 | "More DummyJDK Blabla\n"); |
Ulf Adams | 7a046e1 | 2015-09-07 10:57:46 +0000 | [diff] [blame] | 120 | AssertReadFileDescriptor("dummyjdk version \"1.42.qual\"\n" |
| 121 | "DummyJDK Blabla\n" |
Lukacs Berki | 00d613a | 2016-04-25 15:39:28 +0000 | [diff] [blame] | 122 | "More DummyJDK Blabla\n"); |
Ulf Adams | 7a046e1 | 2015-09-07 10:57:46 +0000 | [diff] [blame] | 123 | AssertReadFileDescriptor2("first_line\n", |
Lukacs Berki | 00d613a | 2016-04-25 15:39:28 +0000 | [diff] [blame] | 124 | "second line version \"1.4.2_0\"\n"); |
Ulf Adams | 7a046e1 | 2015-09-07 10:57:46 +0000 | [diff] [blame] | 125 | } |
| 126 | |
| 127 | void ReadJvmVersionTest() const { |
| 128 | AssertReadJvmVersion("1.42", "dummyjdk version \"1.42\"\n" |
| 129 | "DummyJDK Blabla\n" |
| 130 | "More DummyJDK Blabla\n"); |
| 131 | AssertReadJvmVersion("1.42.qual", "dummyjdk version \"1.42.qual\"\n" |
| 132 | "DummyJDK Blabla\n" |
| 133 | "More DummyJDK Blabla\n"); |
| 134 | AssertReadJvmVersion("1.42.qualifie", "dummyjdk version \"1.42.qualifie"); |
| 135 | AssertReadJvmVersion("", "dummyjdk version "); |
Lukacs Berki | 00d613a | 2016-04-25 15:39:28 +0000 | [diff] [blame] | 136 | AssertReadJvmVersion("1.4.2_0", |
| 137 | "first_line\nsecond line version \"1.4.2_0\"\n"); |
Ulf Adams | 7a046e1 | 2015-09-07 10:57:46 +0000 | [diff] [blame] | 138 | } |
| 139 | |
| 140 | void CheckJavaVersionIsAtLeastTest() const { |
| 141 | ASSERT_TRUE(CheckJavaVersionIsAtLeast("1.7.0-ver-specifier-42", "")); |
| 142 | ASSERT_TRUE(CheckJavaVersionIsAtLeast("1.7.0-ver-specifier-42", "0")); |
| 143 | ASSERT_TRUE(CheckJavaVersionIsAtLeast("1.7.0-ver-specifier-42", "1")); |
| 144 | ASSERT_TRUE(CheckJavaVersionIsAtLeast("1.7.0-ver-specifier-42", "1.7")); |
| 145 | ASSERT_TRUE(CheckJavaVersionIsAtLeast("1.7.0-ver-specifier-42", "1.7.0")); |
| 146 | ASSERT_TRUE(CheckJavaVersionIsAtLeast("1.7.0-ver-specifier-42", "1.0")); |
| 147 | ASSERT_TRUE(CheckJavaVersionIsAtLeast("1.7.0-ver-specifier-42", "1.6")); |
| 148 | ASSERT_TRUE(CheckJavaVersionIsAtLeast("1.42", "1")); |
| 149 | ASSERT_TRUE(CheckJavaVersionIsAtLeast("1.42", "1.7")); |
| 150 | ASSERT_TRUE(CheckJavaVersionIsAtLeast("1.42", "1.11")); |
| 151 | ASSERT_TRUE(CheckJavaVersionIsAtLeast("1.42.42", "1.11")); |
| 152 | ASSERT_TRUE(CheckJavaVersionIsAtLeast("1.42.42", "1.11.11")); |
| 153 | |
| 154 | ASSERT_FALSE(CheckJavaVersionIsAtLeast("1.7.0-ver-specifier-42", "42")); |
| 155 | ASSERT_FALSE(CheckJavaVersionIsAtLeast("1.7.0-ver-specifier-42", "2")); |
| 156 | ASSERT_FALSE(CheckJavaVersionIsAtLeast("1.7.0-ver-specifier-42", "1.8")); |
| 157 | ASSERT_FALSE(CheckJavaVersionIsAtLeast("1.7.0-ver-specifier-42", "1.7.1")); |
| 158 | ASSERT_FALSE(CheckJavaVersionIsAtLeast("1.7.0-ver-specifier-42", "1.42")); |
| 159 | ASSERT_FALSE(CheckJavaVersionIsAtLeast("1.42", "2")); |
| 160 | ASSERT_FALSE(CheckJavaVersionIsAtLeast("1.42", "1.69")); |
| 161 | ASSERT_FALSE(CheckJavaVersionIsAtLeast("1.42", "1.42.1")); |
| 162 | ASSERT_FALSE(CheckJavaVersionIsAtLeast("1.42.42", "1.42.43")); |
| 163 | ASSERT_FALSE(CheckJavaVersionIsAtLeast("1.42.42.0", "1.42.42.1")); |
| 164 | } |
| 165 | }; |
| 166 | |
| 167 | TEST_F(BlazeUtilTest, CheckJavaVersionIsAtLeast) { |
| 168 | CheckJavaVersionIsAtLeastTest(); |
| 169 | } |
| 170 | |
| 171 | TEST_F(BlazeUtilTest, ReadFileDescriptor) { |
| 172 | ReadFileDescriptorTest(); |
| 173 | } |
| 174 | |
| 175 | TEST_F(BlazeUtilTest, ReadJvmVersion) { |
| 176 | ReadJvmVersionTest(); |
| 177 | } |
| 178 | |
| 179 | TEST_F(BlazeUtilTest, MakeDirectories) { |
Ulf Adams | 2aad9d7 | 2015-09-08 08:43:40 +0000 | [diff] [blame] | 180 | const char* tmp_dir = getenv("TEST_TMPDIR"); |
| 181 | ASSERT_STRNE(tmp_dir, NULL); |
| 182 | const char* test_src_dir = getenv("TEST_SRCDIR"); |
| 183 | ASSERT_STRNE(NULL, test_src_dir); |
| 184 | |
| 185 | string dir = blaze_util::JoinPath(tmp_dir, "x/y/z"); |
Laszlo Csomor | cefa9a2 | 2016-11-22 10:50:07 +0000 | [diff] [blame] | 186 | bool ok = MakeDirectories(dir, 0755); |
| 187 | ASSERT_TRUE(ok); |
Ulf Adams | 7a046e1 | 2015-09-07 10:57:46 +0000 | [diff] [blame] | 188 | |
| 189 | // Changing permissions on an existing dir should work. |
| 190 | ok = MakeDirectories(dir, 0750); |
Laszlo Csomor | cefa9a2 | 2016-11-22 10:50:07 +0000 | [diff] [blame] | 191 | ASSERT_TRUE(ok); |
Ulf Adams | 7a046e1 | 2015-09-07 10:57:46 +0000 | [diff] [blame] | 192 | struct stat filestat = {}; |
| 193 | ASSERT_EQ(0, stat(dir.c_str(), &filestat)); |
| 194 | ASSERT_EQ(0750, filestat.st_mode & 0777); |
| 195 | |
| 196 | // srcdir shouldn't be writable. |
Luis Fernando Pino Duque | af91553 | 2016-10-28 15:56:11 +0000 | [diff] [blame] | 197 | // TODO(ulfjack): Fix this! |
| 198 | // string srcdir = blaze_util::JoinPath(test_src_dir, "x/y/z"); |
| 199 | // ok = MakeDirectories(srcdir, 0755); |
Laszlo Csomor | cefa9a2 | 2016-11-22 10:50:07 +0000 | [diff] [blame] | 200 | // ASSERT_FALSE(ok); |
Luis Fernando Pino Duque | af91553 | 2016-10-28 15:56:11 +0000 | [diff] [blame] | 201 | // ASSERT_EQ(EACCES, errno); |
Ulf Adams | 7a046e1 | 2015-09-07 10:57:46 +0000 | [diff] [blame] | 202 | |
| 203 | // Can't make a dir out of a file. |
| 204 | string non_dir = blaze_util::JoinPath(dir, "w"); |
Ulf Adams | 2aad9d7 | 2015-09-08 08:43:40 +0000 | [diff] [blame] | 205 | ASSERT_TRUE(CreateEmptyFile(non_dir)); |
Ulf Adams | 7a046e1 | 2015-09-07 10:57:46 +0000 | [diff] [blame] | 206 | ok = MakeDirectories(non_dir, 0755); |
Laszlo Csomor | cefa9a2 | 2016-11-22 10:50:07 +0000 | [diff] [blame] | 207 | ASSERT_FALSE(ok); |
Ulf Adams | 7a046e1 | 2015-09-07 10:57:46 +0000 | [diff] [blame] | 208 | ASSERT_EQ(ENOTDIR, errno); |
| 209 | |
| 210 | // Valid symlink should work. |
Ulf Adams | 2aad9d7 | 2015-09-08 08:43:40 +0000 | [diff] [blame] | 211 | string symlink = blaze_util::JoinPath(tmp_dir, "z"); |
| 212 | ASSERT_TRUE(Symlink(dir, symlink)); |
Ulf Adams | 7a046e1 | 2015-09-07 10:57:46 +0000 | [diff] [blame] | 213 | ok = MakeDirectories(symlink, 0755); |
Laszlo Csomor | cefa9a2 | 2016-11-22 10:50:07 +0000 | [diff] [blame] | 214 | ASSERT_TRUE(ok); |
Ulf Adams | 7a046e1 | 2015-09-07 10:57:46 +0000 | [diff] [blame] | 215 | |
| 216 | // Error: Symlink to a file. |
Ulf Adams | 2aad9d7 | 2015-09-08 08:43:40 +0000 | [diff] [blame] | 217 | symlink = blaze_util::JoinPath(tmp_dir, "w"); |
| 218 | ASSERT_TRUE(Symlink(non_dir, symlink)); |
Ulf Adams | 7a046e1 | 2015-09-07 10:57:46 +0000 | [diff] [blame] | 219 | ok = MakeDirectories(symlink, 0755); |
Laszlo Csomor | cefa9a2 | 2016-11-22 10:50:07 +0000 | [diff] [blame] | 220 | ASSERT_FALSE(ok); |
Ulf Adams | 7a046e1 | 2015-09-07 10:57:46 +0000 | [diff] [blame] | 221 | ASSERT_EQ(ENOTDIR, errno); |
| 222 | |
| 223 | // Error: Symlink to a dir with wrong perms. |
Ulf Adams | 2aad9d7 | 2015-09-08 08:43:40 +0000 | [diff] [blame] | 224 | symlink = blaze_util::JoinPath(tmp_dir, "s"); |
| 225 | ASSERT_TRUE(Symlink("/", symlink)); |
Ulf Adams | 7a046e1 | 2015-09-07 10:57:46 +0000 | [diff] [blame] | 226 | |
| 227 | // These perms will force a chmod() |
Luis Fernando Pino Duque | af91553 | 2016-10-28 15:56:11 +0000 | [diff] [blame] | 228 | // TODO(ulfjack): Fix this! |
| 229 | // ok = MakeDirectories(symlink, 0000); |
Laszlo Csomor | cefa9a2 | 2016-11-22 10:50:07 +0000 | [diff] [blame] | 230 | // ASSERTFALSE(ok); |
Luis Fernando Pino Duque | af91553 | 2016-10-28 15:56:11 +0000 | [diff] [blame] | 231 | // ASSERT_EQ(EPERM, errno); |
Ulf Adams | 7a046e1 | 2015-09-07 10:57:46 +0000 | [diff] [blame] | 232 | |
| 233 | // Edge cases. |
Laszlo Csomor | cefa9a2 | 2016-11-22 10:50:07 +0000 | [diff] [blame] | 234 | ASSERT_FALSE(MakeDirectories("", 0755)); |
Ulf Adams | 7a046e1 | 2015-09-07 10:57:46 +0000 | [diff] [blame] | 235 | ASSERT_EQ(EACCES, errno); |
Laszlo Csomor | cefa9a2 | 2016-11-22 10:50:07 +0000 | [diff] [blame] | 236 | ASSERT_FALSE(MakeDirectories("/", 0755)); |
Ulf Adams | 7a046e1 | 2015-09-07 10:57:46 +0000 | [diff] [blame] | 237 | ASSERT_EQ(EACCES, errno); |
| 238 | } |
| 239 | |
| 240 | TEST_F(BlazeUtilTest, HammerMakeDirectories) { |
Ulf Adams | 2aad9d7 | 2015-09-08 08:43:40 +0000 | [diff] [blame] | 241 | const char* tmp_dir = getenv("TEST_TMPDIR"); |
| 242 | ASSERT_STRNE(tmp_dir, NULL); |
| 243 | |
| 244 | string path = blaze_util::JoinPath(tmp_dir, "x/y/z"); |
Luis Fernando Pino Duque | af91553 | 2016-10-28 15:56:11 +0000 | [diff] [blame] | 245 | // TODO(ulfjack): Fix this! |
| 246 | // ASSERT_LE(0, fork()); |
Laszlo Csomor | cefa9a2 | 2016-11-22 10:50:07 +0000 | [diff] [blame] | 247 | // ASSERT_TRUE(MakeDirectories(path, 0755)); |
Ulf Adams | 7a046e1 | 2015-09-07 10:57:46 +0000 | [diff] [blame] | 248 | } |
| 249 | |
| 250 | } // namespace blaze |