unistd_test.cpp revision 78e4f8fed2c162f8ada55180e48487ef2180cf93
1/*
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>
18#include "ScopedSignalHandler.h"
19#include "TemporaryFile.h"
20
21#include <errno.h>
22#include <fcntl.h>
23#include <limits.h>
24#include <stdint.h>
25#include <unistd.h>
26#include <sys/syscall.h>
27#include <sys/types.h>
28#include <sys/wait.h>
29
30TEST(unistd, sysconf_SC_MONOTONIC_CLOCK) {
31  ASSERT_GT(sysconf(_SC_MONOTONIC_CLOCK), 0);
32}
33
34static void* get_brk() {
35  return sbrk(0);
36}
37
38static void* page_align(uintptr_t addr) {
39  uintptr_t mask = sysconf(_SC_PAGE_SIZE) - 1;
40  return reinterpret_cast<void*>((addr + mask) & ~mask);
41}
42
43TEST(unistd, brk) {
44  void* initial_break = get_brk();
45
46  // The kernel aligns the break to a page.
47  void* new_break = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(initial_break) + 1);
48  ASSERT_EQ(0, brk(new_break));
49  ASSERT_GE(get_brk(), new_break);
50
51  new_break = page_align(reinterpret_cast<uintptr_t>(initial_break) + sysconf(_SC_PAGE_SIZE));
52  ASSERT_EQ(0, brk(new_break));
53  ASSERT_EQ(get_brk(), new_break);
54}
55
56TEST(unistd, brk_ENOMEM) {
57  ASSERT_EQ(-1, brk(reinterpret_cast<void*>(-1)));
58  ASSERT_EQ(ENOMEM, errno);
59}
60
61#if defined(__GLIBC__)
62#define SBRK_MIN INTPTR_MIN
63#define SBRK_MAX INTPTR_MAX
64#else
65#define SBRK_MIN PTRDIFF_MIN
66#define SBRK_MAX PTRDIFF_MAX
67#endif
68
69TEST(unistd, sbrk_ENOMEM) {
70#if defined(__BIONIC__) && !defined(__LP64__)
71  // There is no way to guarantee that all overflow conditions can be tested
72  // without manipulating the underlying values of the current break.
73  extern void* __bionic_brk;
74
75  class ScopedBrk {
76  public:
77    ScopedBrk() : saved_brk_(__bionic_brk) {}
78    virtual ~ScopedBrk() { __bionic_brk = saved_brk_; }
79
80  private:
81    void* saved_brk_;
82  };
83
84  ScopedBrk scope_brk;
85
86  // Set the current break to a point that will cause an overflow.
87  __bionic_brk = reinterpret_cast<void*>(static_cast<uintptr_t>(PTRDIFF_MAX) + 2);
88
89  // Can't increase by so much that we'd overflow.
90  ASSERT_EQ(reinterpret_cast<void*>(-1), sbrk(PTRDIFF_MAX));
91  ASSERT_EQ(ENOMEM, errno);
92
93  // Set the current break to a point that will cause an overflow.
94  __bionic_brk = reinterpret_cast<void*>(static_cast<uintptr_t>(PTRDIFF_MAX));
95
96  ASSERT_EQ(reinterpret_cast<void*>(-1), sbrk(PTRDIFF_MIN));
97  ASSERT_EQ(ENOMEM, errno);
98
99  __bionic_brk = reinterpret_cast<void*>(static_cast<uintptr_t>(PTRDIFF_MAX) - 1);
100
101  ASSERT_EQ(reinterpret_cast<void*>(-1), sbrk(PTRDIFF_MIN + 1));
102  ASSERT_EQ(ENOMEM, errno);
103#else
104  class ScopedBrk {
105  public:
106    ScopedBrk() : saved_brk_(get_brk()) {}
107    virtual ~ScopedBrk() { brk(saved_brk_); }
108
109  private:
110    void* saved_brk_;
111  };
112
113  ScopedBrk scope_brk;
114
115  uintptr_t cur_brk = reinterpret_cast<uintptr_t>(get_brk());
116  if (cur_brk < static_cast<uintptr_t>(-(SBRK_MIN+1))) {
117    // Do the overflow test for a max negative increment.
118    ASSERT_EQ(reinterpret_cast<void*>(-1), sbrk(SBRK_MIN));
119#if defined(__BIONIC__)
120    // GLIBC does not set errno in overflow case.
121    ASSERT_EQ(ENOMEM, errno);
122#endif
123  }
124
125  uintptr_t overflow_brk = static_cast<uintptr_t>(SBRK_MAX) + 2;
126  if (cur_brk < overflow_brk) {
127    // Try and move the value to PTRDIFF_MAX + 2.
128    cur_brk = reinterpret_cast<uintptr_t>(sbrk(overflow_brk));
129  }
130  if (cur_brk >= overflow_brk) {
131    ASSERT_EQ(reinterpret_cast<void*>(-1), sbrk(SBRK_MAX));
132#if defined(__BIONIC__)
133    // GLIBC does not set errno in overflow case.
134    ASSERT_EQ(ENOMEM, errno);
135#endif
136  }
137#endif
138}
139
140TEST(unistd, truncate) {
141  TemporaryFile tf;
142  ASSERT_EQ(0, close(tf.fd));
143  ASSERT_EQ(0, truncate(tf.filename, 123));
144
145  struct stat sb;
146  ASSERT_EQ(0, stat(tf.filename, &sb));
147  ASSERT_EQ(123, sb.st_size);
148}
149
150TEST(unistd, truncate64) {
151  TemporaryFile tf;
152  ASSERT_EQ(0, close(tf.fd));
153  ASSERT_EQ(0, truncate64(tf.filename, 123));
154
155  struct stat sb;
156  ASSERT_EQ(0, stat(tf.filename, &sb));
157  ASSERT_EQ(123, sb.st_size);
158}
159
160TEST(unistd, ftruncate) {
161  TemporaryFile tf;
162  ASSERT_EQ(0, ftruncate(tf.fd, 123));
163  ASSERT_EQ(0, close(tf.fd));
164
165  struct stat sb;
166  ASSERT_EQ(0, stat(tf.filename, &sb));
167  ASSERT_EQ(123, sb.st_size);
168}
169
170TEST(unistd, ftruncate64) {
171  TemporaryFile tf;
172  ASSERT_EQ(0, ftruncate64(tf.fd, 123));
173  ASSERT_EQ(0, close(tf.fd));
174
175  struct stat sb;
176  ASSERT_EQ(0, stat(tf.filename, &sb));
177  ASSERT_EQ(123, sb.st_size);
178}
179
180static bool g_pause_test_flag = false;
181static void PauseTestSignalHandler(int) {
182  g_pause_test_flag = true;
183}
184
185TEST(unistd, pause) {
186  ScopedSignalHandler handler(SIGALRM, PauseTestSignalHandler);
187
188  alarm(1);
189  ASSERT_FALSE(g_pause_test_flag);
190  ASSERT_EQ(-1, pause());
191  ASSERT_TRUE(g_pause_test_flag);
192}
193
194TEST(unistd, read) {
195  int fd = open("/proc/version", O_RDONLY);
196  ASSERT_TRUE(fd != -1);
197
198  char buf[5];
199  ASSERT_EQ(5, read(fd, buf, 5));
200  ASSERT_EQ(buf[0], 'L');
201  ASSERT_EQ(buf[1], 'i');
202  ASSERT_EQ(buf[2], 'n');
203  ASSERT_EQ(buf[3], 'u');
204  ASSERT_EQ(buf[4], 'x');
205  close(fd);
206}
207
208TEST(unistd, read_EBADF) {
209  // read returns ssize_t which is 64-bits on LP64, so it's worth explicitly checking that
210  // our syscall stubs correctly return a 64-bit -1.
211  char buf[1];
212  ASSERT_EQ(-1, read(-1, buf, sizeof(buf)));
213  ASSERT_EQ(EBADF, errno);
214}
215
216TEST(unistd, syscall_long) {
217  // Check that syscall(3) correctly returns long results.
218  // https://code.google.com/p/android/issues/detail?id=73952
219  // We assume that the break is > 4GiB, but this is potentially flaky.
220  uintptr_t p = reinterpret_cast<uintptr_t>(sbrk(0));
221  ASSERT_EQ(p, static_cast<uintptr_t>(syscall(__NR_brk, 0)));
222}
223
224TEST(unistd, alarm) {
225  ASSERT_EQ(0U, alarm(0));
226}
227
228TEST(unistd, _exit) {
229  int pid = fork();
230  ASSERT_NE(-1, pid) << strerror(errno);
231
232  if (pid == 0) {
233    _exit(99);
234  }
235
236  int status;
237  ASSERT_EQ(pid, waitpid(pid, &status, 0));
238  ASSERT_TRUE(WIFEXITED(status));
239  ASSERT_EQ(99, WEXITSTATUS(status));
240}
241
242TEST(unistd, getenv_unsetenv) {
243  ASSERT_EQ(0, setenv("test-variable", "hello", 1));
244  ASSERT_STREQ("hello", getenv("test-variable"));
245  ASSERT_EQ(0, unsetenv("test-variable"));
246  ASSERT_TRUE(getenv("test-variable") == NULL);
247}
248
249TEST(unistd, unsetenv_EINVAL) {
250  EXPECT_EQ(-1, unsetenv(NULL));
251  EXPECT_EQ(EINVAL, errno);
252  EXPECT_EQ(-1, unsetenv(""));
253  EXPECT_EQ(EINVAL, errno);
254  EXPECT_EQ(-1, unsetenv("a=b"));
255  EXPECT_EQ(EINVAL, errno);
256}
257
258TEST(unistd, setenv_EINVAL) {
259  EXPECT_EQ(-1, setenv(NULL, "value", 0));
260  EXPECT_EQ(EINVAL, errno);
261  EXPECT_EQ(-1, setenv(NULL, "value", 1));
262  EXPECT_EQ(EINVAL, errno);
263  EXPECT_EQ(-1, setenv("", "value", 0));
264  EXPECT_EQ(EINVAL, errno);
265  EXPECT_EQ(-1, setenv("", "value", 1));
266  EXPECT_EQ(EINVAL, errno);
267  EXPECT_EQ(-1, setenv("a=b", "value", 0));
268  EXPECT_EQ(EINVAL, errno);
269  EXPECT_EQ(-1, setenv("a=b", "value", 1));
270  EXPECT_EQ(EINVAL, errno);
271}
272
273TEST(unistd, setenv) {
274  ASSERT_EQ(0, unsetenv("test-variable"));
275
276  char a[] = "a";
277  char b[] = "b";
278  char c[] = "c";
279
280  // New value.
281  EXPECT_EQ(0, setenv("test-variable", a, 0));
282  EXPECT_STREQ(a, getenv("test-variable"));
283
284  // Existing value, no overwrite.
285  EXPECT_EQ(0, setenv("test-variable", b, 0));
286  EXPECT_STREQ(a, getenv("test-variable"));
287
288  // Existing value, overwrite.
289  EXPECT_EQ(0, setenv("test-variable", c, 1));
290  EXPECT_STREQ(c, getenv("test-variable"));
291  // But the arrays backing the values are unchanged.
292  EXPECT_EQ('a', a[0]);
293  EXPECT_EQ('b', b[0]);
294  EXPECT_EQ('c', c[0]);
295
296  ASSERT_EQ(0, unsetenv("test-variable"));
297}
298
299TEST(unistd, putenv) {
300  ASSERT_EQ(0, unsetenv("a"));
301
302  char* s1 = strdup("a=b");
303  ASSERT_EQ(0, putenv(s1));
304
305  ASSERT_STREQ("b", getenv("a"));
306  s1[2] = 'c';
307  ASSERT_STREQ("c", getenv("a"));
308
309  char* s2 = strdup("a=b");
310  ASSERT_EQ(0, putenv(s2));
311
312  ASSERT_STREQ("b", getenv("a"));
313  ASSERT_EQ('c', s1[2]);
314
315  ASSERT_EQ(0, unsetenv("a"));
316  free(s1);
317  free(s2);
318}
319
320TEST(unistd, clearenv) {
321  extern char** environ;
322
323  // Guarantee that environ is not initially empty...
324  ASSERT_EQ(0, setenv("test-variable", "a", 1));
325
326  // Stash a copy.
327  std::vector<char*> old_environ;
328  for (size_t i = 0; environ[i] != NULL; ++i) {
329    old_environ.push_back(strdup(environ[i]));
330  }
331
332  ASSERT_EQ(0, clearenv());
333
334  EXPECT_TRUE(environ == NULL || environ[0] == NULL);
335  EXPECT_EQ(NULL, getenv("test-variable"));
336  EXPECT_EQ(0, setenv("test-variable", "post-clear", 1));
337  EXPECT_STREQ("post-clear", getenv("test-variable"));
338
339  // Put the old environment back.
340  for (size_t i = 0; i < old_environ.size(); ++i) {
341    EXPECT_EQ(0, putenv(old_environ[i]));
342  }
343
344  // Check it wasn't overwritten.
345  EXPECT_STREQ("a", getenv("test-variable"));
346
347  EXPECT_EQ(0, unsetenv("test-variable"));
348}
349
350static void TestFsyncFunction(int (*fn)(int)) {
351  int fd;
352
353  // Can't sync an invalid fd.
354  errno = 0;
355  EXPECT_EQ(-1, fn(-1));
356  EXPECT_EQ(EBADF, errno);
357
358  // It doesn't matter whether you've opened a file for write or not.
359  TemporaryFile tf;
360  ASSERT_NE(-1, tf.fd);
361
362  EXPECT_EQ(0, fn(tf.fd));
363
364  ASSERT_NE(-1, fd = open(tf.filename, O_RDONLY));
365  EXPECT_EQ(0, fn(fd));
366  close(fd);
367
368  ASSERT_NE(-1, fd = open(tf.filename, O_RDWR));
369  EXPECT_EQ(0, fn(fd));
370  close(fd);
371
372  // The fd can even be a directory.
373  ASSERT_NE(-1, fd = open("/", O_RDONLY));
374  EXPECT_EQ(0, fn(fd));
375  close(fd);
376
377  // But some file systems may choose to be fussy...
378  errno = 0;
379  ASSERT_NE(-1, fd = open("/proc/version", O_RDONLY));
380  EXPECT_EQ(-1, fn(fd));
381  EXPECT_EQ(EINVAL, errno);
382  close(fd);
383}
384
385TEST(unistd, fdatasync) {
386  TestFsyncFunction(fdatasync);
387}
388
389TEST(unistd, fsync) {
390  TestFsyncFunction(fsync);
391}
392
393static void AssertGetPidCorrect() {
394  // The loop is just to make manual testing/debugging with strace easier.
395  pid_t getpid_syscall_result = syscall(__NR_getpid);
396  for (size_t i = 0; i < 128; ++i) {
397    ASSERT_EQ(getpid_syscall_result, getpid());
398  }
399}
400
401TEST(unistd, getpid_caching_and_fork) {
402  pid_t parent_pid = getpid();
403  ASSERT_EQ(syscall(__NR_getpid), parent_pid);
404
405  pid_t fork_result = fork();
406  ASSERT_NE(fork_result, -1);
407  if (fork_result == 0) {
408    // We're the child.
409    AssertGetPidCorrect();
410    ASSERT_EQ(parent_pid, getppid());
411    _exit(123);
412  } else {
413    // We're the parent.
414    ASSERT_EQ(parent_pid, getpid());
415
416    int status;
417    ASSERT_EQ(fork_result, waitpid(fork_result, &status, 0));
418    ASSERT_TRUE(WIFEXITED(status));
419    ASSERT_EQ(123, WEXITSTATUS(status));
420  }
421}
422
423static int GetPidCachingCloneStartRoutine(void*) {
424  AssertGetPidCorrect();
425  return 123;
426}
427
428TEST(unistd, getpid_caching_and_clone) {
429  pid_t parent_pid = getpid();
430  ASSERT_EQ(syscall(__NR_getpid), parent_pid);
431
432  void* child_stack[1024];
433  int clone_result = clone(GetPidCachingCloneStartRoutine, &child_stack[1024], CLONE_NEWNS | SIGCHLD, NULL);
434  ASSERT_NE(clone_result, -1);
435
436  ASSERT_EQ(parent_pid, getpid());
437
438  int status;
439  ASSERT_EQ(clone_result, waitpid(clone_result, &status, 0));
440  ASSERT_TRUE(WIFEXITED(status));
441  ASSERT_EQ(123, WEXITSTATUS(status));
442}
443
444static void* GetPidCachingPthreadStartRoutine(void*) {
445  AssertGetPidCorrect();
446  return NULL;
447}
448
449TEST(unistd, getpid_caching_and_pthread_create) {
450  pid_t parent_pid = getpid();
451
452  pthread_t t;
453  ASSERT_EQ(0, pthread_create(&t, NULL, GetPidCachingPthreadStartRoutine, NULL));
454
455  ASSERT_EQ(parent_pid, getpid());
456
457  void* result;
458  ASSERT_EQ(0, pthread_join(t, &result));
459  ASSERT_EQ(NULL, result);
460}
461