blob: bb0faf01823e99e5c5379e179267a709c05f5503 [file] [log] [blame]
Damien Martin-Guillerezf88f4d82015-09-25 13:56:55 +00001// Copyright 2015 The Bazel Authors. All rights reserved.
Ulf Adams7a046e12015-09-07 10:57:46 +00002//
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-Moore44e8d102015-11-10 11:27:39 +000015#include <errno.h>
Ulf Adams7a046e12015-09-07 10:57:46 +000016#include <fcntl.h>
17#include <stddef.h>
18#include <stdlib.h>
19#include <unistd.h>
20#include <string>
21#include <vector>
22
Ulf Adams2aad9d72015-09-08 08:43:40 +000023#include "src/main/cpp/blaze_util.h"
Laszlo Csomorcefa9a22016-11-22 10:50:07 +000024#include "src/main/cpp/blaze_util_platform.h"
Ulf Adams2aad9d72015-09-08 08:43:40 +000025#include "src/main/cpp/util/file.h"
Ulf Adams7a046e12015-09-07 10:57:46 +000026#include "gtest/gtest.h"
27
28namespace blaze {
29
Thiago Farina80bb0f22016-10-17 15:57:13 +000030using std::string;
31
Ulf Adams7a046e12015-09-07 10:57:46 +000032static bool Symlink(const string& old_path, const string& new_path) {
33 return symlink(old_path.c_str(), new_path.c_str()) == 0;
34}
35
36static bool CreateEmptyFile(const string& path) {
Luis Fernando Pino Duque738c8922016-10-26 20:48:09 +000037 // 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 Adams7a046e12015-09-07 10:57:46 +000044 if (fd == -1) {
45 return false;
46 }
47 return close(fd) == 0;
48}
49
50class 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-Guillerez87a3c492015-09-08 11:19:40 +000078 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 Adams7a046e12015-09-07 10:57:46 +000083 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 Adams7a046e12015-09-07 10:57:46 +0000113 static void AssertReadJvmVersion(string expected, string input) {
Lukacs Berki00d613a2016-04-25 15:39:28 +0000114 ASSERT_EQ(expected, ReadJvmVersion(input));
Ulf Adams7a046e12015-09-07 10:57:46 +0000115 }
116
117 void ReadFileDescriptorTest() const {
118 AssertReadFileDescriptor("DummyJDK Blabla\n"
Lukacs Berki00d613a2016-04-25 15:39:28 +0000119 "More DummyJDK Blabla\n");
Ulf Adams7a046e12015-09-07 10:57:46 +0000120 AssertReadFileDescriptor("dummyjdk version \"1.42.qual\"\n"
121 "DummyJDK Blabla\n"
Lukacs Berki00d613a2016-04-25 15:39:28 +0000122 "More DummyJDK Blabla\n");
Ulf Adams7a046e12015-09-07 10:57:46 +0000123 AssertReadFileDescriptor2("first_line\n",
Lukacs Berki00d613a2016-04-25 15:39:28 +0000124 "second line version \"1.4.2_0\"\n");
Ulf Adams7a046e12015-09-07 10:57:46 +0000125 }
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 Berki00d613a2016-04-25 15:39:28 +0000136 AssertReadJvmVersion("1.4.2_0",
137 "first_line\nsecond line version \"1.4.2_0\"\n");
Ulf Adams7a046e12015-09-07 10:57:46 +0000138 }
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
167TEST_F(BlazeUtilTest, CheckJavaVersionIsAtLeast) {
168 CheckJavaVersionIsAtLeastTest();
169}
170
171TEST_F(BlazeUtilTest, ReadFileDescriptor) {
172 ReadFileDescriptorTest();
173}
174
175TEST_F(BlazeUtilTest, ReadJvmVersion) {
176 ReadJvmVersionTest();
177}
178
179TEST_F(BlazeUtilTest, MakeDirectories) {
Ulf Adams2aad9d72015-09-08 08:43:40 +0000180 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 Csomorcefa9a22016-11-22 10:50:07 +0000186 bool ok = MakeDirectories(dir, 0755);
187 ASSERT_TRUE(ok);
Ulf Adams7a046e12015-09-07 10:57:46 +0000188
189 // Changing permissions on an existing dir should work.
190 ok = MakeDirectories(dir, 0750);
Laszlo Csomorcefa9a22016-11-22 10:50:07 +0000191 ASSERT_TRUE(ok);
Ulf Adams7a046e12015-09-07 10:57:46 +0000192 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 Duqueaf915532016-10-28 15:56:11 +0000197 // TODO(ulfjack): Fix this!
198// string srcdir = blaze_util::JoinPath(test_src_dir, "x/y/z");
199// ok = MakeDirectories(srcdir, 0755);
Laszlo Csomorcefa9a22016-11-22 10:50:07 +0000200// ASSERT_FALSE(ok);
Luis Fernando Pino Duqueaf915532016-10-28 15:56:11 +0000201// ASSERT_EQ(EACCES, errno);
Ulf Adams7a046e12015-09-07 10:57:46 +0000202
203 // Can't make a dir out of a file.
204 string non_dir = blaze_util::JoinPath(dir, "w");
Ulf Adams2aad9d72015-09-08 08:43:40 +0000205 ASSERT_TRUE(CreateEmptyFile(non_dir));
Ulf Adams7a046e12015-09-07 10:57:46 +0000206 ok = MakeDirectories(non_dir, 0755);
Laszlo Csomorcefa9a22016-11-22 10:50:07 +0000207 ASSERT_FALSE(ok);
Ulf Adams7a046e12015-09-07 10:57:46 +0000208 ASSERT_EQ(ENOTDIR, errno);
209
210 // Valid symlink should work.
Ulf Adams2aad9d72015-09-08 08:43:40 +0000211 string symlink = blaze_util::JoinPath(tmp_dir, "z");
212 ASSERT_TRUE(Symlink(dir, symlink));
Ulf Adams7a046e12015-09-07 10:57:46 +0000213 ok = MakeDirectories(symlink, 0755);
Laszlo Csomorcefa9a22016-11-22 10:50:07 +0000214 ASSERT_TRUE(ok);
Ulf Adams7a046e12015-09-07 10:57:46 +0000215
216 // Error: Symlink to a file.
Ulf Adams2aad9d72015-09-08 08:43:40 +0000217 symlink = blaze_util::JoinPath(tmp_dir, "w");
218 ASSERT_TRUE(Symlink(non_dir, symlink));
Ulf Adams7a046e12015-09-07 10:57:46 +0000219 ok = MakeDirectories(symlink, 0755);
Laszlo Csomorcefa9a22016-11-22 10:50:07 +0000220 ASSERT_FALSE(ok);
Ulf Adams7a046e12015-09-07 10:57:46 +0000221 ASSERT_EQ(ENOTDIR, errno);
222
223 // Error: Symlink to a dir with wrong perms.
Ulf Adams2aad9d72015-09-08 08:43:40 +0000224 symlink = blaze_util::JoinPath(tmp_dir, "s");
225 ASSERT_TRUE(Symlink("/", symlink));
Ulf Adams7a046e12015-09-07 10:57:46 +0000226
227 // These perms will force a chmod()
Luis Fernando Pino Duqueaf915532016-10-28 15:56:11 +0000228 // TODO(ulfjack): Fix this!
229// ok = MakeDirectories(symlink, 0000);
Laszlo Csomorcefa9a22016-11-22 10:50:07 +0000230// ASSERTFALSE(ok);
Luis Fernando Pino Duqueaf915532016-10-28 15:56:11 +0000231// ASSERT_EQ(EPERM, errno);
Ulf Adams7a046e12015-09-07 10:57:46 +0000232
233 // Edge cases.
Laszlo Csomorcefa9a22016-11-22 10:50:07 +0000234 ASSERT_FALSE(MakeDirectories("", 0755));
Ulf Adams7a046e12015-09-07 10:57:46 +0000235 ASSERT_EQ(EACCES, errno);
Laszlo Csomorcefa9a22016-11-22 10:50:07 +0000236 ASSERT_FALSE(MakeDirectories("/", 0755));
Ulf Adams7a046e12015-09-07 10:57:46 +0000237 ASSERT_EQ(EACCES, errno);
238}
239
240TEST_F(BlazeUtilTest, HammerMakeDirectories) {
Ulf Adams2aad9d72015-09-08 08:43:40 +0000241 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 Duqueaf915532016-10-28 15:56:11 +0000245 // TODO(ulfjack): Fix this!
246// ASSERT_LE(0, fork());
Laszlo Csomorcefa9a22016-11-22 10:50:07 +0000247// ASSERT_TRUE(MakeDirectories(path, 0755));
Ulf Adams7a046e12015-09-07 10:57:46 +0000248}
249
250} // namespace blaze