OLD | NEW |
| (Empty) |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "files/public/c/lib/file_fd_impl.h" | |
6 | |
7 #include <errno.h> | |
8 | |
9 #include <string> | |
10 | |
11 #include "files/public/c/mojio_sys_stat.h" | |
12 #include "files/public/c/mojio_unistd.h" | |
13 #include "files/public/c/tests/mock_errno_impl.h" | |
14 #include "files/public/c/tests/mojio_impl_test_base.h" | |
15 #include "files/public/c/tests/test_utils.h" | |
16 #include "files/public/interfaces/files.mojom.h" | |
17 #include "files/public/interfaces/types.mojom.h" | |
18 | |
19 namespace mojio { | |
20 namespace { | |
21 | |
22 using FileFDImplTest = mojio::test::MojioImplTestBase; | |
23 | |
24 const int kLastErrorSentinel = -12345; | |
25 | |
26 TEST_F(FileFDImplTest, ConstructClose) { | |
27 test::MockErrnoImpl errno_impl(kLastErrorSentinel); | |
28 FileFDImpl ffdi(&errno_impl, | |
29 test::OpenFileAt(&directory(), "my_file", | |
30 mojo::files::kOpenFlagWrite | | |
31 mojo::files::kOpenFlagCreate)); | |
32 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
33 | |
34 errno_impl.Reset(kLastErrorSentinel); | |
35 EXPECT_TRUE(ffdi.Close()); | |
36 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
37 } | |
38 | |
39 TEST_F(FileFDImplTest, Dup) { | |
40 test::CreateTestFileAt(&directory(), "my_file", 1000); | |
41 | |
42 test::MockErrnoImpl errno_impl(kLastErrorSentinel); | |
43 FileFDImpl ffdi(&errno_impl, test::OpenFileAt(&directory(), "my_file", | |
44 mojo::files::kOpenFlagRead)); | |
45 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
46 | |
47 errno_impl.Reset(kLastErrorSentinel); | |
48 std::unique_ptr<FDImpl> duped_ffdi = ffdi.Dup(); | |
49 EXPECT_TRUE(duped_ffdi); | |
50 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
51 | |
52 // Seeking in one should change the position in the other. | |
53 errno_impl.Reset(kLastErrorSentinel); | |
54 EXPECT_EQ(123, ffdi.Lseek(123, MOJIO_SEEK_SET)); | |
55 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
56 errno_impl.Reset(kLastErrorSentinel); | |
57 EXPECT_EQ(123, duped_ffdi->Lseek(0, MOJIO_SEEK_CUR)); | |
58 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
59 | |
60 // And vice versa. | |
61 errno_impl.Reset(kLastErrorSentinel); | |
62 EXPECT_EQ(123 + 456, duped_ffdi->Lseek(456, MOJIO_SEEK_CUR)); | |
63 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
64 errno_impl.Reset(kLastErrorSentinel); | |
65 EXPECT_EQ(123 + 456, ffdi.Lseek(0, MOJIO_SEEK_CUR)); | |
66 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
67 } | |
68 | |
69 TEST_F(FileFDImplTest, Ftruncate) { | |
70 test::CreateTestFileAt(&directory(), "my_file", 1000); | |
71 | |
72 test::MockErrnoImpl errno_impl(kLastErrorSentinel); | |
73 FileFDImpl ffdi(&errno_impl, test::OpenFileAt(&directory(), "my_file", | |
74 mojo::files::kOpenFlagWrite)); | |
75 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
76 | |
77 // Truncate. | |
78 errno_impl.Reset(kLastErrorSentinel); | |
79 EXPECT_TRUE(ffdi.Ftruncate(123)); | |
80 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
81 EXPECT_EQ(123, test::GetFileSize(&directory(), "my_file")); | |
82 | |
83 // Can also extend. | |
84 errno_impl.Reset(kLastErrorSentinel); | |
85 EXPECT_TRUE(ffdi.Ftruncate(456)); | |
86 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
87 EXPECT_EQ(456, test::GetFileSize(&directory(), "my_file")); | |
88 | |
89 // TODO(vtl): Check file position after |Ftruncate()|. | |
90 | |
91 // Invalid size. | |
92 errno_impl.Reset(kLastErrorSentinel); | |
93 EXPECT_FALSE(ffdi.Ftruncate(-1)); | |
94 EXPECT_EQ(EINVAL, errno_impl.Get()); | |
95 } | |
96 | |
97 TEST_F(FileFDImplTest, Lseek) { | |
98 test::CreateTestFileAt(&directory(), "my_file", 123); | |
99 | |
100 test::MockErrnoImpl errno_impl(kLastErrorSentinel); | |
101 FileFDImpl ffdi(&errno_impl, test::OpenFileAt(&directory(), "my_file", | |
102 mojo::files::kOpenFlagWrite)); | |
103 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
104 | |
105 // Seek and write in various places. | |
106 | |
107 // 5 from beginning. | |
108 errno_impl.Reset(kLastErrorSentinel); | |
109 EXPECT_EQ(5, ffdi.Lseek(5, MOJIO_SEEK_SET)); | |
110 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
111 | |
112 // Write a byte. | |
113 errno_impl.Reset(kLastErrorSentinel); | |
114 char c = 42; | |
115 EXPECT_EQ(1, ffdi.Write(&c, 1)); | |
116 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
117 | |
118 // 42 from current. | |
119 errno_impl.Reset(kLastErrorSentinel); | |
120 EXPECT_EQ(5 + 1 + 42, ffdi.Lseek(42, MOJIO_SEEK_CUR)); | |
121 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
122 | |
123 // Write a byte. | |
124 errno_impl.Reset(kLastErrorSentinel); | |
125 c = 5; | |
126 EXPECT_EQ(1, ffdi.Write(&c, 1)); | |
127 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
128 | |
129 // 5 before end. | |
130 errno_impl.Reset(kLastErrorSentinel); | |
131 EXPECT_EQ(123 - 5, ffdi.Lseek(-5, MOJIO_SEEK_END)); | |
132 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
133 | |
134 // Write a byte. | |
135 errno_impl.Reset(kLastErrorSentinel); | |
136 c = 0; | |
137 EXPECT_EQ(1, ffdi.Write(&c, 1)); | |
138 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
139 | |
140 // Now read everything and check. | |
141 std::string expected_contents(123, '\0'); | |
142 for (size_t i = 0; i < 123; i++) { | |
143 unsigned char c = static_cast<unsigned char>(i); | |
144 expected_contents[i] = *reinterpret_cast<char*>(&c); | |
145 } | |
146 expected_contents[5] = 42; | |
147 expected_contents[5 + 1 + 42] = 5; | |
148 expected_contents[123 - 5] = 0; | |
149 EXPECT_EQ(expected_contents, test::GetFileContents(&directory(), "my_file")); | |
150 } | |
151 | |
152 TEST_F(FileFDImplTest, Read) { | |
153 test::CreateTestFileAt(&directory(), "my_file", 123); | |
154 | |
155 test::MockErrnoImpl errno_impl(kLastErrorSentinel); | |
156 FileFDImpl ffdi(&errno_impl, test::OpenFileAt(&directory(), "my_file", | |
157 mojo::files::kOpenFlagRead)); | |
158 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
159 | |
160 // Read a bit. | |
161 errno_impl.Reset(kLastErrorSentinel); | |
162 unsigned char buffer[1000] = {}; | |
163 EXPECT_EQ(23, ffdi.Read(buffer, 23)); | |
164 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
165 for (size_t i = 0; i < 23; i++) | |
166 EXPECT_EQ(static_cast<unsigned char>(i), buffer[i]) << i; | |
167 | |
168 // Read too much. | |
169 errno_impl.Reset(kLastErrorSentinel); | |
170 EXPECT_EQ(100, ffdi.Read(buffer, sizeof(buffer))); | |
171 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
172 for (size_t i = 0; i < 100; i++) | |
173 EXPECT_EQ(static_cast<unsigned char>(23 + i), buffer[i]) << i; | |
174 | |
175 // Invalid |count| (must fit within |ssize_t|). | |
176 errno_impl.Reset(kLastErrorSentinel); | |
177 EXPECT_EQ(-1, ffdi.Read(buffer, static_cast<size_t>(-1))); | |
178 EXPECT_EQ(EINVAL, errno_impl.Get()); | |
179 } | |
180 | |
181 TEST_F(FileFDImplTest, Write) { | |
182 test::MockErrnoImpl errno_impl(kLastErrorSentinel); | |
183 FileFDImpl ffdi(&errno_impl, | |
184 test::OpenFileAt(&directory(), "my_file", | |
185 mojo::files::kOpenFlagWrite | | |
186 mojo::files::kOpenFlagCreate | | |
187 mojo::files::kOpenFlagExclusive)); | |
188 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
189 | |
190 // Write something. | |
191 errno_impl.Reset(kLastErrorSentinel); | |
192 const char kHello[] = {'h', 'e', 'l', 'l', 'o', ' '}; | |
193 EXPECT_EQ(static_cast<mojio_off_t>(sizeof(kHello)), | |
194 ffdi.Write(kHello, sizeof(kHello))); | |
195 | |
196 // Write something else. | |
197 const char kMojio[] = {'m', 'o', 'j', 'i', 'o'}; | |
198 EXPECT_EQ(static_cast<mojio_off_t>(sizeof(kMojio)), | |
199 ffdi.Write(kMojio, sizeof(kMojio))); | |
200 | |
201 EXPECT_EQ(std::string("hello mojio"), | |
202 test::GetFileContents(&directory(), "my_file")); | |
203 | |
204 // Invalid |count| (must fit within |ssize_t|). | |
205 errno_impl.Reset(kLastErrorSentinel); | |
206 EXPECT_EQ(-1, ffdi.Write(kHello, static_cast<size_t>(-1))); | |
207 EXPECT_EQ(EINVAL, errno_impl.Get()); | |
208 } | |
209 | |
210 TEST_F(FileFDImplTest, Fstat) { | |
211 test::CreateTestFileAt(&directory(), "my_file_0", 0); | |
212 test::CreateTestFileAt(&directory(), "my_file_1", 512); | |
213 test::CreateTestFileAt(&directory(), "my_file_2", 513); | |
214 | |
215 test::MockErrnoImpl errno_impl(kLastErrorSentinel); | |
216 FileFDImpl ffdi0(&errno_impl, test::OpenFileAt(&directory(), "my_file_0", | |
217 mojo::files::kOpenFlagRead)); | |
218 FileFDImpl ffdi1(&errno_impl, test::OpenFileAt(&directory(), "my_file_1", | |
219 mojo::files::kOpenFlagRead)); | |
220 FileFDImpl ffdi2(&errno_impl, test::OpenFileAt(&directory(), "my_file_2", | |
221 mojo::files::kOpenFlagRead)); | |
222 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
223 | |
224 errno_impl.Reset(kLastErrorSentinel); | |
225 struct mojio_stat buf0 = {}; | |
226 EXPECT_TRUE(ffdi0.Fstat(&buf0)); | |
227 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
228 // Note: Don't check the unfilled values. (Some of the checks may also be | |
229 // fragile, depending on our level of support.) | |
230 EXPECT_EQ(static_cast<mojio_mode_t>(MOJIO_S_IRWXU | MOJIO_S_IFREG), | |
231 buf0.st_mode); // Fragile. | |
232 EXPECT_EQ(1u, buf0.st_nlink); // Fragile. | |
233 EXPECT_EQ(0, buf0.st_size); | |
234 // Just check that |st_atim.tv_sec|, etc. are positive (a bit fragile). | |
235 EXPECT_GT(buf0.st_atim.tv_sec, 0); | |
236 EXPECT_GT(buf0.st_mtim.tv_sec, 0); | |
237 EXPECT_GT(buf0.st_ctim.tv_sec, 0); | |
238 EXPECT_EQ(1024, buf0.st_blksize); // Fragile. | |
239 EXPECT_EQ(0u, buf0.st_blocks); | |
240 | |
241 errno_impl.Reset(kLastErrorSentinel); | |
242 struct mojio_stat buf1 = {}; | |
243 EXPECT_TRUE(ffdi1.Fstat(&buf1)); | |
244 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
245 // Only check the things that should be (interestingly) different. | |
246 EXPECT_EQ(512, buf1.st_size); | |
247 EXPECT_EQ(1u, buf1.st_blocks); | |
248 | |
249 errno_impl.Reset(kLastErrorSentinel); | |
250 struct mojio_stat buf2 = {}; | |
251 EXPECT_TRUE(ffdi2.Fstat(&buf2)); | |
252 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
253 // Only check the things that should be (interestingly) different. | |
254 EXPECT_EQ(513, buf2.st_size); | |
255 EXPECT_EQ(2u, buf2.st_blocks); | |
256 } | |
257 | |
258 TEST_F(FileFDImplTest, Efault) { | |
259 test::MockErrnoImpl errno_impl(kLastErrorSentinel); | |
260 FileFDImpl ffdi(&errno_impl, | |
261 test::OpenFileAt(&directory(), "my_file", | |
262 mojo::files::kOpenFlagRead | | |
263 mojo::files::kOpenFlagWrite | | |
264 mojo::files::kOpenFlagCreate | | |
265 mojo::files::kOpenFlagExclusive)); | |
266 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
267 | |
268 errno_impl.Reset(kLastErrorSentinel); | |
269 EXPECT_EQ(-1, ffdi.Read(nullptr, 1)); | |
270 EXPECT_EQ(EFAULT, errno_impl.Get()); | |
271 | |
272 errno_impl.Reset(kLastErrorSentinel); | |
273 EXPECT_EQ(-1, ffdi.Write(nullptr, 1)); | |
274 EXPECT_EQ(EFAULT, errno_impl.Get()); | |
275 | |
276 errno_impl.Reset(kLastErrorSentinel); | |
277 EXPECT_FALSE(ffdi.Fstat(nullptr)); | |
278 EXPECT_EQ(EFAULT, errno_impl.Get()); | |
279 } | |
280 | |
281 } // namespace | |
282 } // namespace mojio | |
OLD | NEW |