|
1 /* vim:set ts=2 sw=2 sts=2 et: */ |
|
2 /* Any copyright is dedicated to the Public Domain. |
|
3 * http://creativecommons.org/publicdomain/zero/1.0/ |
|
4 */ |
|
5 |
|
6 /* Test ReadSysFile() */ |
|
7 |
|
8 #include <sys/types.h> |
|
9 #include <sys/stat.h> |
|
10 |
|
11 #include <errno.h> |
|
12 #include <fcntl.h> |
|
13 #include <stdio.h> |
|
14 #include <string.h> |
|
15 |
|
16 #include "FileUtils.h" |
|
17 |
|
18 #include "gtest/gtest.h" |
|
19 |
|
20 namespace mozilla { |
|
21 |
|
22 #ifdef ReadSysFile_PRESENT |
|
23 |
|
24 /** |
|
25 * Create a file with the specified contents. |
|
26 */ |
|
27 static bool |
|
28 WriteFile( |
|
29 const char* aFilename, |
|
30 const void* aContents, |
|
31 size_t aContentsLen) |
|
32 { |
|
33 int fd; |
|
34 ssize_t ret; |
|
35 size_t offt; |
|
36 |
|
37 fd = MOZ_TEMP_FAILURE_RETRY( |
|
38 open(aFilename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)); |
|
39 if (fd == -1) { |
|
40 fprintf(stderr, "open(): %s: %s\n", aFilename, strerror(errno)); |
|
41 return false; |
|
42 } |
|
43 |
|
44 offt = 0; |
|
45 do { |
|
46 ret = MOZ_TEMP_FAILURE_RETRY( |
|
47 write(fd, (char*)aContents + offt, aContentsLen - offt)); |
|
48 if (ret == -1) { |
|
49 fprintf(stderr, "write(): %s: %s\n", aFilename, strerror(errno)); |
|
50 close(fd); |
|
51 return false; |
|
52 } |
|
53 offt += ret; |
|
54 } while (offt < aContentsLen); |
|
55 |
|
56 ret = MOZ_TEMP_FAILURE_RETRY(close(fd)); |
|
57 if (ret == -1) { |
|
58 fprintf(stderr, "close(): %s: %s\n", aFilename, strerror(errno)); |
|
59 return false; |
|
60 } |
|
61 return true; |
|
62 } |
|
63 |
|
64 TEST(ReadSysFile, Nonexistent) { |
|
65 bool ret; |
|
66 int errno_saved; |
|
67 |
|
68 ret = ReadSysFile("/nonexistent", nullptr, 0); |
|
69 errno_saved = errno; |
|
70 |
|
71 ASSERT_FALSE(ret); |
|
72 ASSERT_EQ(errno_saved, ENOENT); |
|
73 } |
|
74 |
|
75 TEST(ReadSysFile, Main) { |
|
76 /* Use a different file name for each test since different tests could be |
|
77 executed concurrently. */ |
|
78 static const char* fn = "TestReadSysFileMain"; |
|
79 /* If we have a file which contains "abcd" and we read it with ReadSysFile(), |
|
80 providing a buffer of size 10 bytes, we would expect 5 bytes to be written |
|
81 to that buffer: "abcd\0". */ |
|
82 struct { |
|
83 /* input (file contents), e.g. "abcd" */ |
|
84 const char* input; |
|
85 /* pretended output buffer size, e.g. 10; the actual buffer is larger |
|
86 and we check if anything was written past the end of the allowed length */ |
|
87 size_t output_size; |
|
88 /* expected number of bytes written to the output buffer, including the |
|
89 terminating '\0', e.g. 5 */ |
|
90 size_t output_len; |
|
91 /* expected output buffer contents, e.g. "abcd\0", the first output_len |
|
92 bytes of the output buffer should match the first 'output_len' bytes from |
|
93 'output', the rest of the output buffer should be untouched. */ |
|
94 const char* output; |
|
95 } tests[] = { |
|
96 /* No new lines */ |
|
97 {"", 0, 0, ""}, |
|
98 {"", 1, 1, "\0"}, /* \0 is redundant, but we write it for clarity */ |
|
99 {"", 9, 1, "\0"}, |
|
100 |
|
101 {"a", 0, 0, ""}, |
|
102 {"a", 1, 1, "\0"}, |
|
103 {"a", 2, 2, "a\0"}, |
|
104 {"a", 9, 2, "a\0"}, |
|
105 |
|
106 {"abcd", 0, 0, ""}, |
|
107 {"abcd", 1, 1, "\0"}, |
|
108 {"abcd", 2, 2, "a\0"}, |
|
109 {"abcd", 3, 3, "ab\0"}, |
|
110 {"abcd", 4, 4, "abc\0"}, |
|
111 {"abcd", 5, 5, "abcd\0"}, |
|
112 {"abcd", 9, 5, "abcd\0"}, |
|
113 |
|
114 /* A single trailing new line */ |
|
115 {"\n", 0, 0, ""}, |
|
116 {"\n", 1, 1, "\0"}, |
|
117 {"\n", 2, 1, "\0"}, |
|
118 {"\n", 9, 1, "\0"}, |
|
119 |
|
120 {"a\n", 0, 0, ""}, |
|
121 {"a\n", 1, 1, "\0"}, |
|
122 {"a\n", 2, 2, "a\0"}, |
|
123 {"a\n", 3, 2, "a\0"}, |
|
124 {"a\n", 9, 2, "a\0"}, |
|
125 |
|
126 {"abcd\n", 0, 0, ""}, |
|
127 {"abcd\n", 1, 1, "\0"}, |
|
128 {"abcd\n", 2, 2, "a\0"}, |
|
129 {"abcd\n", 3, 3, "ab\0"}, |
|
130 {"abcd\n", 4, 4, "abc\0"}, |
|
131 {"abcd\n", 5, 5, "abcd\0"}, |
|
132 {"abcd\n", 6, 5, "abcd\0"}, |
|
133 {"abcd\n", 9, 5, "abcd\0"}, |
|
134 |
|
135 /* Multiple trailing new lines */ |
|
136 {"\n\n", 0, 0, ""}, |
|
137 {"\n\n", 1, 1, "\0"}, |
|
138 {"\n\n", 2, 2, "\n\0"}, |
|
139 {"\n\n", 3, 2, "\n\0"}, |
|
140 {"\n\n", 9, 2, "\n\0"}, |
|
141 |
|
142 {"a\n\n", 0, 0, ""}, |
|
143 {"a\n\n", 1, 1, "\0"}, |
|
144 {"a\n\n", 2, 2, "a\0"}, |
|
145 {"a\n\n", 3, 3, "a\n\0"}, |
|
146 {"a\n\n", 4, 3, "a\n\0"}, |
|
147 {"a\n\n", 9, 3, "a\n\0"}, |
|
148 |
|
149 {"abcd\n\n", 0, 0, ""}, |
|
150 {"abcd\n\n", 1, 1, "\0"}, |
|
151 {"abcd\n\n", 2, 2, "a\0"}, |
|
152 {"abcd\n\n", 3, 3, "ab\0"}, |
|
153 {"abcd\n\n", 4, 4, "abc\0"}, |
|
154 {"abcd\n\n", 5, 5, "abcd\0"}, |
|
155 {"abcd\n\n", 6, 6, "abcd\n\0"}, |
|
156 {"abcd\n\n", 7, 6, "abcd\n\0"}, |
|
157 {"abcd\n\n", 9, 6, "abcd\n\0"}, |
|
158 |
|
159 /* New line in the middle */ |
|
160 {"ab\ncd", 9, 6, "ab\ncd\0"}, |
|
161 }; |
|
162 |
|
163 for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { |
|
164 ASSERT_TRUE(WriteFile(fn, tests[i].input, strlen(tests[i].input))); |
|
165 /* Leave the file to exist if some of the assertions fail. */ |
|
166 |
|
167 char buf[128]; |
|
168 static const char unmodified = 'X'; |
|
169 |
|
170 memset(buf, unmodified, sizeof(buf)); |
|
171 |
|
172 ASSERT_TRUE(ReadSysFile(fn, buf, tests[i].output_size)); |
|
173 |
|
174 if (tests[i].output_size == 0) { |
|
175 /* The buffer must be unmodified. We check only the first byte. */ |
|
176 ASSERT_EQ(unmodified, buf[0]); |
|
177 } else { |
|
178 ASSERT_EQ(tests[i].output_len, strlen(buf) + 1); |
|
179 ASSERT_STREQ(tests[i].output, buf); |
|
180 /* Check that the first byte after the trailing '\0' has not been |
|
181 modified. */ |
|
182 ASSERT_EQ(unmodified, buf[tests[i].output_len]); |
|
183 } |
|
184 } |
|
185 |
|
186 unlink(fn); |
|
187 } |
|
188 |
|
189 TEST(ReadSysFile, Int) { |
|
190 static const char* fn = "TestReadSysFileInt"; |
|
191 struct { |
|
192 /* input (file contents), e.g. "5" */ |
|
193 const char* input; |
|
194 /* expected return value, if false, then the output is not checked */ |
|
195 bool ret; |
|
196 /* expected result */ |
|
197 int output; |
|
198 } tests[] = { |
|
199 {"0", true, 0}, |
|
200 {"00", true, 0}, |
|
201 {"1", true, 1}, |
|
202 {"5", true, 5}, |
|
203 {"55", true, 55}, |
|
204 |
|
205 {" 123", true, 123}, |
|
206 {"123 ", true, 123}, |
|
207 {" 123 ", true, 123}, |
|
208 {"123\n", true, 123}, |
|
209 |
|
210 {"", false, 0}, |
|
211 {" ", false, 0}, |
|
212 {"a", false, 0}, |
|
213 |
|
214 {"-1", true, -1}, |
|
215 {" -456 ", true, -456}, |
|
216 {" -78.9 ", true, -78}, |
|
217 }; |
|
218 |
|
219 for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { |
|
220 ASSERT_TRUE(WriteFile(fn, tests[i].input, strlen(tests[i].input))); |
|
221 /* Leave the file to exist if some of the assertions fail. */ |
|
222 |
|
223 bool ret; |
|
224 int output = 424242; |
|
225 |
|
226 ret = ReadSysFile(fn, &output); |
|
227 |
|
228 ASSERT_EQ(tests[i].ret, ret); |
|
229 |
|
230 if (ret) { |
|
231 ASSERT_EQ(tests[i].output, output); |
|
232 } |
|
233 } |
|
234 |
|
235 unlink(fn); |
|
236 } |
|
237 |
|
238 TEST(ReadSysFile, Bool) { |
|
239 static const char* fn = "TestReadSysFileBool"; |
|
240 struct { |
|
241 /* input (file contents), e.g. "1" */ |
|
242 const char* input; |
|
243 /* expected return value */ |
|
244 bool ret; |
|
245 /* expected result */ |
|
246 bool output; |
|
247 } tests[] = { |
|
248 {"0", true, false}, |
|
249 {"00", true, false}, |
|
250 {"1", true, true}, |
|
251 {"5", true, true}, |
|
252 {"23", true, true}, |
|
253 {"-1", true, true}, |
|
254 |
|
255 {"", false, true /* unused */}, |
|
256 }; |
|
257 |
|
258 for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { |
|
259 ASSERT_TRUE(WriteFile(fn, tests[i].input, strlen(tests[i].input))); |
|
260 /* Leave the file to exist if some of the assertions fail. */ |
|
261 |
|
262 bool ret; |
|
263 bool output; |
|
264 |
|
265 ret = ReadSysFile(fn, &output); |
|
266 |
|
267 ASSERT_EQ(tests[i].ret, ret); |
|
268 |
|
269 if (ret) { |
|
270 ASSERT_EQ(tests[i].output, output); |
|
271 } |
|
272 } |
|
273 |
|
274 unlink(fn); |
|
275 } |
|
276 |
|
277 #endif /* ReadSysFile_PRESENT */ |
|
278 |
|
279 } |