unistd_test.cpp revision a62a28d1d9c8df7cb77e4bca19814922729b5291
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 <stdint.h>
24#include <unistd.h>
25#include <sys/types.h>
26#include <sys/wait.h>
27
28TEST(unistd, sysconf_SC_MONOTONIC_CLOCK) {
29  ASSERT_GT(sysconf(_SC_MONOTONIC_CLOCK), 0);
30}
31
32static void* get_brk() {
33  return sbrk(0);
34}
35
36static 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);
46  ASSERT_EQ(0, brk(new_break));
47  ASSERT_GE(get_brk(), new_break);
48
49  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
75}
76
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}
116
117static bool gPauseTestFlag = false;
118static void PauseTestSignalHandler(int) {
119  gPauseTestFlag = true;
120}
121
122TEST(unistd, pause) {
123  ScopedSignalHandler handler(SIGALRM, PauseTestSignalHandler);
124
125  alarm(1);
126  ASSERT_FALSE(gPauseTestFlag);
127  ASSERT_EQ(-1, pause());
128  ASSERT_TRUE(gPauseTestFlag);
129}
130
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}
152
153TEST(unistd, alarm) {
154  ASSERT_EQ(0U, alarm(0));
155}
156
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}
170
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}
278
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}
321