blob: f56b767dcacc7bb27304b7ac3ec90748ffad9ba3 [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 Hughes533dde42014-04-25 18:27:38 -070021#define __STDC_LIMIT_MACROS // For glibc.
22
Elliott Hughes915fefb2014-02-18 12:34:51 -080023#include <errno.h>
Colin Cross3d19a832014-02-14 18:56:23 -080024#include <fcntl.h>
Elliott Hughes428f5562013-02-05 16:10:59 -080025#include <stdint.h>
Elliott Hughesa55f6302013-01-02 14:23:43 -080026#include <unistd.h>
Elliott Hughes764a9932014-04-08 19:44:36 -070027#include <sys/types.h>
28#include <sys/wait.h>
Elliott Hughesa55f6302013-01-02 14:23:43 -080029
30TEST(unistd, sysconf_SC_MONOTONIC_CLOCK) {
31 ASSERT_GT(sysconf(_SC_MONOTONIC_CLOCK), 0);
32}
Elliott Hughes428f5562013-02-05 16:10:59 -080033
Elliott Hughes533dde42014-04-25 18:27:38 -070034static void* get_brk() {
35 return sbrk(0);
36}
Elliott Hughes428f5562013-02-05 16:10:59 -080037
Elliott Hughes533dde42014-04-25 18:27:38 -070038static 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);
Elliott Hughes428f5562013-02-05 16:10:59 -080048 ASSERT_EQ(0, brk(new_break));
Elliott Hughes533dde42014-04-25 18:27:38 -070049 ASSERT_GE(get_brk(), new_break);
Elliott Hughes428f5562013-02-05 16:10:59 -080050
Elliott Hughes533dde42014-04-25 18:27:38 -070051 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
61TEST(unistd, sbrk_ENOMEM) {
62 intptr_t current_brk = reinterpret_cast<intptr_t>(get_brk());
63
64 // Can't increase by so much that we'd overflow.
65 ASSERT_EQ(reinterpret_cast<void*>(-1), sbrk(PTRDIFF_MAX));
66 ASSERT_EQ(ENOMEM, errno);
67
68 // Can't reduce by more than the current break.
69 ASSERT_EQ(reinterpret_cast<void*>(-1), sbrk(-(current_brk + 1)));
70 ASSERT_EQ(ENOMEM, errno);
71
72#if !defined(__GLIBC__)
73 // The maximum negative value is an interesting special case that glibc gets wrong.
74 ASSERT_EQ(reinterpret_cast<void*>(-1), sbrk(PTRDIFF_MIN));
75 ASSERT_EQ(ENOMEM, errno);
76#endif
Elliott Hughes428f5562013-02-05 16:10:59 -080077}
Elliott Hughesb4f76162013-09-19 16:27:24 -070078
79TEST(unistd, truncate) {
80 TemporaryFile tf;
81 ASSERT_EQ(0, close(tf.fd));
82 ASSERT_EQ(0, truncate(tf.filename, 123));
83
84 struct stat sb;
85 ASSERT_EQ(0, stat(tf.filename, &sb));
86 ASSERT_EQ(123, sb.st_size);
87}
88
89TEST(unistd, truncate64) {
90 TemporaryFile tf;
91 ASSERT_EQ(0, close(tf.fd));
92 ASSERT_EQ(0, truncate64(tf.filename, 123));
93
94 struct stat sb;
95 ASSERT_EQ(0, stat(tf.filename, &sb));
96 ASSERT_EQ(123, sb.st_size);
97}
98
99TEST(unistd, ftruncate) {
100 TemporaryFile tf;
101 ASSERT_EQ(0, ftruncate(tf.fd, 123));
102 ASSERT_EQ(0, close(tf.fd));
103
104 struct stat sb;
105 ASSERT_EQ(0, stat(tf.filename, &sb));
106 ASSERT_EQ(123, sb.st_size);
107}
108
109TEST(unistd, ftruncate64) {
110 TemporaryFile tf;
111 ASSERT_EQ(0, ftruncate64(tf.fd, 123));
112 ASSERT_EQ(0, close(tf.fd));
113
114 struct stat sb;
115 ASSERT_EQ(0, stat(tf.filename, &sb));
116 ASSERT_EQ(123, sb.st_size);
117}
Elliott Hughes11952072013-10-24 15:15:14 -0700118
119static bool gPauseTestFlag = false;
120static void PauseTestSignalHandler(int) {
121 gPauseTestFlag = true;
122}
123
124TEST(unistd, pause) {
Christopher Ferris13613132013-10-28 15:24:04 -0700125 ScopedSignalHandler handler(SIGALRM, PauseTestSignalHandler);
126
Elliott Hughes11952072013-10-24 15:15:14 -0700127 alarm(1);
128 ASSERT_FALSE(gPauseTestFlag);
129 ASSERT_EQ(-1, pause());
130 ASSERT_TRUE(gPauseTestFlag);
131}
Colin Cross3d19a832014-02-14 18:56:23 -0800132
133TEST(unistd, read) {
134 int fd = open("/proc/version", O_RDONLY);
135 ASSERT_TRUE(fd != -1);
136
137 char buf[5];
138 ASSERT_EQ(5, read(fd, buf, 5));
139 ASSERT_EQ(buf[0], 'L');
140 ASSERT_EQ(buf[1], 'i');
141 ASSERT_EQ(buf[2], 'n');
142 ASSERT_EQ(buf[3], 'u');
143 ASSERT_EQ(buf[4], 'x');
144 close(fd);
145}
146
147TEST(unistd, read_EBADF) {
148 // read returns ssize_t which is 64-bits on LP64, so it's worth explicitly checking that
149 // our syscall stubs correctly return a 64-bit -1.
150 char buf[1];
151 ASSERT_EQ(-1, read(-1, buf, sizeof(buf)));
152 ASSERT_EQ(EBADF, errno);
153}
Elliott Hughesaedb00d2014-03-03 14:38:20 -0800154
155TEST(unistd, alarm) {
156 ASSERT_EQ(0U, alarm(0));
157}
Elliott Hughes9f525642014-04-08 17:14:01 -0700158
159TEST(unistd, _exit) {
160 int pid = fork();
161 ASSERT_NE(-1, pid) << strerror(errno);
162
163 if (pid == 0) {
164 _exit(99);
165 }
166
167 int status;
168 ASSERT_EQ(pid, waitpid(pid, &status, 0));
169 ASSERT_TRUE(WIFEXITED(status));
170 ASSERT_EQ(99, WEXITSTATUS(status));
171}
Grigoriy Kraynovcbf6df02013-09-17 15:44:22 +0400172
173TEST(unistd, getenv_unsetenv) {
174 ASSERT_EQ(0, setenv("test-variable", "hello", 1));
175 ASSERT_STREQ("hello", getenv("test-variable"));
176 ASSERT_EQ(0, unsetenv("test-variable"));
177 ASSERT_TRUE(getenv("test-variable") == NULL);
178}
179
180TEST(unistd, unsetenv_EINVAL) {
181 EXPECT_EQ(-1, unsetenv(NULL));
182 EXPECT_EQ(EINVAL, errno);
183 EXPECT_EQ(-1, unsetenv(""));
184 EXPECT_EQ(EINVAL, errno);
185 EXPECT_EQ(-1, unsetenv("a=b"));
186 EXPECT_EQ(EINVAL, errno);
187}
188
189TEST(unistd, setenv_EINVAL) {
190 EXPECT_EQ(-1, setenv(NULL, "value", 0));
191 EXPECT_EQ(EINVAL, errno);
192 EXPECT_EQ(-1, setenv(NULL, "value", 1));
193 EXPECT_EQ(EINVAL, errno);
194 EXPECT_EQ(-1, setenv("", "value", 0));
195 EXPECT_EQ(EINVAL, errno);
196 EXPECT_EQ(-1, setenv("", "value", 1));
197 EXPECT_EQ(EINVAL, errno);
198 EXPECT_EQ(-1, setenv("a=b", "value", 0));
199 EXPECT_EQ(EINVAL, errno);
200 EXPECT_EQ(-1, setenv("a=b", "value", 1));
201 EXPECT_EQ(EINVAL, errno);
202}
203
204TEST(unistd, setenv) {
205 ASSERT_EQ(0, unsetenv("test-variable"));
206
207 char a[] = "a";
208 char b[] = "b";
209 char c[] = "c";
210
211 // New value.
212 EXPECT_EQ(0, setenv("test-variable", a, 0));
213 EXPECT_STREQ(a, getenv("test-variable"));
214
215 // Existing value, no overwrite.
216 EXPECT_EQ(0, setenv("test-variable", b, 0));
217 EXPECT_STREQ(a, getenv("test-variable"));
218
219 // Existing value, overwrite.
220 EXPECT_EQ(0, setenv("test-variable", c, 1));
221 EXPECT_STREQ(c, getenv("test-variable"));
222 // But the arrays backing the values are unchanged.
223 EXPECT_EQ('a', a[0]);
224 EXPECT_EQ('b', b[0]);
225 EXPECT_EQ('c', c[0]);
226
227 ASSERT_EQ(0, unsetenv("test-variable"));
228}
229
230TEST(unistd, putenv) {
231 ASSERT_EQ(0, unsetenv("a"));
232
233 char* s1 = strdup("a=b");
234 ASSERT_EQ(0, putenv(s1));
235
236 ASSERT_STREQ("b", getenv("a"));
237 s1[2] = 'c';
238 ASSERT_STREQ("c", getenv("a"));
239
240 char* s2 = strdup("a=b");
241 ASSERT_EQ(0, putenv(s2));
242
243 ASSERT_STREQ("b", getenv("a"));
244 ASSERT_EQ('c', s1[2]);
245
246 ASSERT_EQ(0, unsetenv("a"));
247 free(s1);
248 free(s2);
249}
250
251TEST(unistd, clearenv) {
252 extern char** environ;
253
254 // Guarantee that environ is not initially empty...
255 ASSERT_EQ(0, setenv("test-variable", "a", 1));
256
257 // Stash a copy.
258 std::vector<char*> old_environ;
259 for (size_t i = 0; environ[i] != NULL; ++i) {
260 old_environ.push_back(strdup(environ[i]));
261 }
262
263 ASSERT_EQ(0, clearenv());
264
265 EXPECT_TRUE(environ == NULL || environ[0] == NULL);
266 EXPECT_EQ(NULL, getenv("test-variable"));
267 EXPECT_EQ(0, setenv("test-variable", "post-clear", 1));
268 EXPECT_STREQ("post-clear", getenv("test-variable"));
269
270 // Put the old environment back.
271 for (size_t i = 0; i < old_environ.size(); ++i) {
272 EXPECT_EQ(0, putenv(old_environ[i]));
273 }
274
275 // Check it wasn't overwritten.
276 EXPECT_STREQ("a", getenv("test-variable"));
277
278 EXPECT_EQ(0, unsetenv("test-variable"));
279}