blob: 2b51aad59a52e5ec24cb043df8b255f4a4d097d9 [file] [log] [blame]
Elliott Hughesa55f6302013-01-02 14:23:43 -08001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <gtest/gtest.h>
Christopher Ferris13613132013-10-28 15:24:04 -070018#include "ScopedSignalHandler.h"
Elliott Hughesb4f76162013-09-19 16:27:24 -070019#include "TemporaryFile.h"
Elliott Hughesa55f6302013-01-02 14:23:43 -080020
Elliott Hughes915fefb2014-02-18 12:34:51 -080021#include <errno.h>
Colin Cross3d19a832014-02-14 18:56:23 -080022#include <fcntl.h>
Elliott Hughes428f5562013-02-05 16:10:59 -080023#include <stdint.h>
Elliott Hughesa55f6302013-01-02 14:23:43 -080024#include <unistd.h>
Elliott Hughes764a9932014-04-08 19:44:36 -070025#include <sys/types.h>
26#include <sys/wait.h>
Elliott Hughesa55f6302013-01-02 14:23:43 -080027
28TEST(unistd, sysconf_SC_MONOTONIC_CLOCK) {
29 ASSERT_GT(sysconf(_SC_MONOTONIC_CLOCK), 0);
30}
Elliott Hughes428f5562013-02-05 16:10:59 -080031
Elliott Hughes533dde42014-04-25 18:27:38 -070032static void* get_brk() {
33 return sbrk(0);
34}
Elliott Hughes428f5562013-02-05 16:10:59 -080035
Elliott Hughes533dde42014-04-25 18:27:38 -070036static void* page_align(uintptr_t addr) {
37 uintptr_t mask = sysconf(_SC_PAGE_SIZE) - 1;
38 return reinterpret_cast<void*>((addr + mask) & ~mask);
39}
40
41TEST(unistd, brk) {
42 void* initial_break = get_brk();
43
44 // The kernel aligns the break to a page.
45 void* new_break = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(initial_break) + 1);
Elliott Hughes428f5562013-02-05 16:10:59 -080046 ASSERT_EQ(0, brk(new_break));
Elliott Hughes533dde42014-04-25 18:27:38 -070047 ASSERT_GE(get_brk(), new_break);
Elliott Hughes428f5562013-02-05 16:10:59 -080048
Elliott Hughes533dde42014-04-25 18:27:38 -070049 new_break = page_align(reinterpret_cast<uintptr_t>(initial_break) + sysconf(_SC_PAGE_SIZE));
50 ASSERT_EQ(0, brk(new_break));
51 ASSERT_EQ(get_brk(), new_break);
52}
53
54TEST(unistd, brk_ENOMEM) {
55 ASSERT_EQ(-1, brk(reinterpret_cast<void*>(-1)));
56 ASSERT_EQ(ENOMEM, errno);
57}
58
59TEST(unistd, sbrk_ENOMEM) {
60 intptr_t current_brk = reinterpret_cast<intptr_t>(get_brk());
61
62 // Can't increase by so much that we'd overflow.
63 ASSERT_EQ(reinterpret_cast<void*>(-1), sbrk(PTRDIFF_MAX));
64 ASSERT_EQ(ENOMEM, errno);
65
66 // Can't reduce by more than the current break.
67 ASSERT_EQ(reinterpret_cast<void*>(-1), sbrk(-(current_brk + 1)));
68 ASSERT_EQ(ENOMEM, errno);
69
70#if !defined(__GLIBC__)
71 // The maximum negative value is an interesting special case that glibc gets wrong.
72 ASSERT_EQ(reinterpret_cast<void*>(-1), sbrk(PTRDIFF_MIN));
73 ASSERT_EQ(ENOMEM, errno);
74#endif
Elliott Hughes428f5562013-02-05 16:10:59 -080075}
Elliott Hughesb4f76162013-09-19 16:27:24 -070076
77TEST(unistd, truncate) {
78 TemporaryFile tf;
79 ASSERT_EQ(0, close(tf.fd));
80 ASSERT_EQ(0, truncate(tf.filename, 123));
81
82 struct stat sb;
83 ASSERT_EQ(0, stat(tf.filename, &sb));
84 ASSERT_EQ(123, sb.st_size);
85}
86
87TEST(unistd, truncate64) {
88 TemporaryFile tf;
89 ASSERT_EQ(0, close(tf.fd));
90 ASSERT_EQ(0, truncate64(tf.filename, 123));
91
92 struct stat sb;
93 ASSERT_EQ(0, stat(tf.filename, &sb));
94 ASSERT_EQ(123, sb.st_size);
95}
96
97TEST(unistd, ftruncate) {
98 TemporaryFile tf;
99 ASSERT_EQ(0, ftruncate(tf.fd, 123));
100 ASSERT_EQ(0, close(tf.fd));
101
102 struct stat sb;
103 ASSERT_EQ(0, stat(tf.filename, &sb));
104 ASSERT_EQ(123, sb.st_size);
105}
106
107TEST(unistd, ftruncate64) {
108 TemporaryFile tf;
109 ASSERT_EQ(0, ftruncate64(tf.fd, 123));
110 ASSERT_EQ(0, close(tf.fd));
111
112 struct stat sb;
113 ASSERT_EQ(0, stat(tf.filename, &sb));
114 ASSERT_EQ(123, sb.st_size);
115}
Elliott Hughes11952072013-10-24 15:15:14 -0700116
117static bool gPauseTestFlag = false;
118static void PauseTestSignalHandler(int) {
119 gPauseTestFlag = true;
120}
121
122TEST(unistd, pause) {
Christopher Ferris13613132013-10-28 15:24:04 -0700123 ScopedSignalHandler handler(SIGALRM, PauseTestSignalHandler);
124
Elliott Hughes11952072013-10-24 15:15:14 -0700125 alarm(1);
126 ASSERT_FALSE(gPauseTestFlag);
127 ASSERT_EQ(-1, pause());
128 ASSERT_TRUE(gPauseTestFlag);
129}
Colin Cross3d19a832014-02-14 18:56:23 -0800130
131TEST(unistd, read) {
132 int fd = open("/proc/version", O_RDONLY);
133 ASSERT_TRUE(fd != -1);
134
135 char buf[5];
136 ASSERT_EQ(5, read(fd, buf, 5));
137 ASSERT_EQ(buf[0], 'L');
138 ASSERT_EQ(buf[1], 'i');
139 ASSERT_EQ(buf[2], 'n');
140 ASSERT_EQ(buf[3], 'u');
141 ASSERT_EQ(buf[4], 'x');
142 close(fd);
143}
144
145TEST(unistd, read_EBADF) {
146 // read returns ssize_t which is 64-bits on LP64, so it's worth explicitly checking that
147 // our syscall stubs correctly return a 64-bit -1.
148 char buf[1];
149 ASSERT_EQ(-1, read(-1, buf, sizeof(buf)));
150 ASSERT_EQ(EBADF, errno);
151}
Elliott Hughesaedb00d2014-03-03 14:38:20 -0800152
153TEST(unistd, alarm) {
154 ASSERT_EQ(0U, alarm(0));
155}
Elliott Hughes9f525642014-04-08 17:14:01 -0700156
157TEST(unistd, _exit) {
158 int pid = fork();
159 ASSERT_NE(-1, pid) << strerror(errno);
160
161 if (pid == 0) {
162 _exit(99);
163 }
164
165 int status;
166 ASSERT_EQ(pid, waitpid(pid, &status, 0));
167 ASSERT_TRUE(WIFEXITED(status));
168 ASSERT_EQ(99, WEXITSTATUS(status));
169}
Grigoriy Kraynovcbf6df02013-09-17 15:44:22 +0400170
171TEST(unistd, getenv_unsetenv) {
172 ASSERT_EQ(0, setenv("test-variable", "hello", 1));
173 ASSERT_STREQ("hello", getenv("test-variable"));
174 ASSERT_EQ(0, unsetenv("test-variable"));
175 ASSERT_TRUE(getenv("test-variable") == NULL);
176}
177
178TEST(unistd, unsetenv_EINVAL) {
179 EXPECT_EQ(-1, unsetenv(NULL));
180 EXPECT_EQ(EINVAL, errno);
181 EXPECT_EQ(-1, unsetenv(""));
182 EXPECT_EQ(EINVAL, errno);
183 EXPECT_EQ(-1, unsetenv("a=b"));
184 EXPECT_EQ(EINVAL, errno);
185}
186
187TEST(unistd, setenv_EINVAL) {
188 EXPECT_EQ(-1, setenv(NULL, "value", 0));
189 EXPECT_EQ(EINVAL, errno);
190 EXPECT_EQ(-1, setenv(NULL, "value", 1));
191 EXPECT_EQ(EINVAL, errno);
192 EXPECT_EQ(-1, setenv("", "value", 0));
193 EXPECT_EQ(EINVAL, errno);
194 EXPECT_EQ(-1, setenv("", "value", 1));
195 EXPECT_EQ(EINVAL, errno);
196 EXPECT_EQ(-1, setenv("a=b", "value", 0));
197 EXPECT_EQ(EINVAL, errno);
198 EXPECT_EQ(-1, setenv("a=b", "value", 1));
199 EXPECT_EQ(EINVAL, errno);
200}
201
202TEST(unistd, setenv) {
203 ASSERT_EQ(0, unsetenv("test-variable"));
204
205 char a[] = "a";
206 char b[] = "b";
207 char c[] = "c";
208
209 // New value.
210 EXPECT_EQ(0, setenv("test-variable", a, 0));
211 EXPECT_STREQ(a, getenv("test-variable"));
212
213 // Existing value, no overwrite.
214 EXPECT_EQ(0, setenv("test-variable", b, 0));
215 EXPECT_STREQ(a, getenv("test-variable"));
216
217 // Existing value, overwrite.
218 EXPECT_EQ(0, setenv("test-variable", c, 1));
219 EXPECT_STREQ(c, getenv("test-variable"));
220 // But the arrays backing the values are unchanged.
221 EXPECT_EQ('a', a[0]);
222 EXPECT_EQ('b', b[0]);
223 EXPECT_EQ('c', c[0]);
224
225 ASSERT_EQ(0, unsetenv("test-variable"));
226}
227
228TEST(unistd, putenv) {
229 ASSERT_EQ(0, unsetenv("a"));
230
231 char* s1 = strdup("a=b");
232 ASSERT_EQ(0, putenv(s1));
233
234 ASSERT_STREQ("b", getenv("a"));
235 s1[2] = 'c';
236 ASSERT_STREQ("c", getenv("a"));
237
238 char* s2 = strdup("a=b");
239 ASSERT_EQ(0, putenv(s2));
240
241 ASSERT_STREQ("b", getenv("a"));
242 ASSERT_EQ('c', s1[2]);
243
244 ASSERT_EQ(0, unsetenv("a"));
245 free(s1);
246 free(s2);
247}
248
249TEST(unistd, clearenv) {
250 extern char** environ;
251
252 // Guarantee that environ is not initially empty...
253 ASSERT_EQ(0, setenv("test-variable", "a", 1));
254
255 // Stash a copy.
256 std::vector<char*> old_environ;
257 for (size_t i = 0; environ[i] != NULL; ++i) {
258 old_environ.push_back(strdup(environ[i]));
259 }
260
261 ASSERT_EQ(0, clearenv());
262
263 EXPECT_TRUE(environ == NULL || environ[0] == NULL);
264 EXPECT_EQ(NULL, getenv("test-variable"));
265 EXPECT_EQ(0, setenv("test-variable", "post-clear", 1));
266 EXPECT_STREQ("post-clear", getenv("test-variable"));
267
268 // Put the old environment back.
269 for (size_t i = 0; i < old_environ.size(); ++i) {
270 EXPECT_EQ(0, putenv(old_environ[i]));
271 }
272
273 // Check it wasn't overwritten.
274 EXPECT_STREQ("a", getenv("test-variable"));
275
276 EXPECT_EQ(0, unsetenv("test-variable"));
277}
Elliott Hughesa62a28d2014-05-07 14:30:33 -0700278
279static void TestFsyncFunction(int (*fn)(int)) {
280 int fd;
281
282 // Can't sync an invalid fd.
283 errno = 0;
284 EXPECT_EQ(-1, fn(-1));
285 EXPECT_EQ(EBADF, errno);
286
287 // It doesn't matter whether you've opened a file for write or not.
288 TemporaryFile tf;
289 ASSERT_NE(-1, tf.fd);
290
291 EXPECT_EQ(0, fn(tf.fd));
292
293 ASSERT_NE(-1, fd = open(tf.filename, O_RDONLY));
294 EXPECT_EQ(0, fn(fd));
295 close(fd);
296
297 ASSERT_NE(-1, fd = open(tf.filename, O_RDWR));
298 EXPECT_EQ(0, fn(fd));
299 close(fd);
300
301 // The fd can even be a directory.
302 ASSERT_NE(-1, fd = open("/", O_RDONLY));
303 EXPECT_EQ(0, fn(fd));
304 close(fd);
305
306 // But some file systems may choose to be fussy...
307 errno = 0;
308 ASSERT_NE(-1, fd = open("/proc/version", O_RDONLY));
309 EXPECT_EQ(-1, fn(fd));
310 EXPECT_EQ(EINVAL, errno);
311 close(fd);
312}
313
314TEST(unistd, fdatasync) {
315 TestFsyncFunction(fdatasync);
316}
317
318TEST(unistd, fsync) {
319 TestFsyncFunction(fsync);
320}