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