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