1 // Copyright 2017 The Fuchsia 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 <fs/pseudo-file.h>
6
7 #include <fbl/vector.h>
8 #include <initializer_list>
9 #include <unittest/unittest.h>
10
11 #define EXPECT_FSTR_EQ(expected, actual) \
12 EXPECT_BYTES_EQ(reinterpret_cast<const uint8_t*>(expected.c_str()), \
13 reinterpret_cast<const uint8_t*>(actual.c_str()), \
14 expected.size() + 1u, "unequal fbl::String")
15
16 namespace {
17
DummyReader(fbl::String * output)18 zx_status_t DummyReader(fbl::String* output) {
19 return ZX_OK;
20 }
21
DummyWriter(fbl::StringPiece input)22 zx_status_t DummyWriter(fbl::StringPiece input) {
23 return ZX_OK;
24 }
25
26 class VectorReader {
27 public:
VectorReader(std::initializer_list<fbl::String> strings)28 VectorReader(std::initializer_list<fbl::String> strings)
29 : strings_(strings) {}
30
GetHandler()31 fs::PseudoFile::ReadHandler GetHandler() {
32 return [this](fbl::String* output) {
33 if (index_ >= strings_.size())
34 return ZX_ERR_IO;
35 *output = strings_[index_++];
36 return ZX_OK;
37 };
38 }
39
strings() const40 const fbl::Vector<fbl::String>& strings() const { return strings_; }
41
42 private:
43 fbl::Vector<fbl::String> strings_;
44 size_t index_ = 0u;
45 };
46
47 class VectorWriter {
48 public:
VectorWriter(size_t max_strings)49 VectorWriter(size_t max_strings)
50 : max_strings_(max_strings) {}
51
GetHandler()52 fs::PseudoFile::WriteHandler GetHandler() {
53 return [this](fbl::StringPiece input) {
54 if (strings_.size() >= max_strings_)
55 return ZX_ERR_IO;
56 strings_.push_back(fbl::String(input));
57 return ZX_OK;
58 };
59 }
60
strings() const61 const fbl::Vector<fbl::String>& strings() const { return strings_; }
62
63 private:
64 const size_t max_strings_;
65 fbl::Vector<fbl::String> strings_;
66 };
67
CheckRead(const fbl::RefPtr<fs::Vnode> & file,zx_status_t status,size_t length,size_t offset,fbl::StringPiece expected)68 bool CheckRead(const fbl::RefPtr<fs::Vnode>& file, zx_status_t status,
69 size_t length, size_t offset, fbl::StringPiece expected) {
70 BEGIN_HELPER;
71
72 uint8_t buf[length];
73 memset(buf, '!', length);
74 size_t actual = 0u;
75 EXPECT_EQ(status, file->Read(buf, length, offset, &actual));
76 EXPECT_EQ(expected.size(), actual);
77 EXPECT_BYTES_EQ(reinterpret_cast<const uint8_t*>(expected.data()), buf, expected.size(), "");
78
79 END_HELPER;
80 }
81
CheckWrite(const fbl::RefPtr<fs::Vnode> & file,zx_status_t status,size_t offset,fbl::StringPiece content,size_t expected_actual)82 bool CheckWrite(const fbl::RefPtr<fs::Vnode>& file, zx_status_t status,
83 size_t offset, fbl::StringPiece content, size_t expected_actual) {
84 BEGIN_HELPER;
85
86 size_t actual = 0u;
87 EXPECT_EQ(status, file->Write(content.data(), content.size(), offset, &actual));
88 EXPECT_EQ(expected_actual, actual);
89
90 END_HELPER;
91 }
92
CheckAppend(const fbl::RefPtr<fs::Vnode> & file,zx_status_t status,fbl::StringPiece content,size_t expected_end,size_t expected_actual)93 bool CheckAppend(const fbl::RefPtr<fs::Vnode>& file, zx_status_t status,
94 fbl::StringPiece content, size_t expected_end, size_t expected_actual) {
95 BEGIN_HELPER;
96
97 size_t end = 0u;
98 size_t actual = 0u;
99 EXPECT_EQ(status, file->Append(content.data(), content.size(), &end, &actual));
100 EXPECT_EQ(expected_end, end);
101 EXPECT_EQ(expected_actual, actual);
102
103 END_HELPER;
104 }
105
TestOpenValidationBuffered()106 bool TestOpenValidationBuffered() {
107 BEGIN_TEST;
108
109 // no read handler, no write handler
110 {
111 auto file = fbl::AdoptRef<fs::Vnode>(new fs::BufferedPseudoFile());
112 EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(ZX_FS_RIGHT_READABLE));
113 EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE));
114 EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
115 EXPECT_EQ(ZX_ERR_NOT_DIR, file->ValidateFlags(ZX_FS_FLAG_DIRECTORY));
116 }
117
118 // read handler, no write handler
119 {
120 auto file = fbl::AdoptRef<fs::Vnode>(new fs::BufferedPseudoFile(&DummyReader));
121 EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE));
122 EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
123 EXPECT_EQ(ZX_ERR_NOT_DIR, file->ValidateFlags(ZX_FS_FLAG_DIRECTORY));
124
125 fbl::RefPtr<fs::Vnode> redirect;
126 EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_READABLE));
127 EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_READABLE, &redirect));
128 EXPECT_NONNULL(redirect);
129 }
130
131 // no read handler, write handler
132 {
133 auto file = fbl::AdoptRef<fs::Vnode>(new fs::BufferedPseudoFile(nullptr, &DummyWriter));
134 EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(ZX_FS_RIGHT_READABLE));
135 EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE));
136 EXPECT_EQ(ZX_ERR_NOT_DIR, file->ValidateFlags(ZX_FS_FLAG_DIRECTORY));
137
138 fbl::RefPtr<fs::Vnode> redirect;
139 EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
140 EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE, &redirect));
141 EXPECT_NONNULL(redirect);
142 }
143
144 // read handler, write handler
145 {
146 auto file = fbl::AdoptRef<fs::Vnode>(new fs::BufferedPseudoFile(&DummyReader, &DummyWriter));
147 EXPECT_EQ(ZX_ERR_NOT_DIR, file->ValidateFlags(ZX_FS_FLAG_DIRECTORY));
148
149 fbl::RefPtr<fs::Vnode> redirect;
150 EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_READABLE));
151 EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_READABLE, &redirect));
152 EXPECT_NONNULL(redirect);
153 redirect.reset();
154 EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE));
155 EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE, &redirect));
156 EXPECT_NONNULL(redirect);
157 redirect.reset();
158 EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
159 EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE, &redirect));
160 EXPECT_NONNULL(redirect);
161 }
162
163 END_TEST;
164 }
165
TestOpenValidationUnbuffered()166 bool TestOpenValidationUnbuffered() {
167 BEGIN_TEST;
168
169 // no read handler, no write handler
170 {
171 auto file = fbl::AdoptRef<fs::Vnode>(new fs::UnbufferedPseudoFile());
172 EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(ZX_FS_RIGHT_READABLE));
173 EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE));
174 EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
175 EXPECT_EQ(ZX_ERR_NOT_DIR, file->ValidateFlags(ZX_FS_FLAG_DIRECTORY));
176 }
177
178 // read handler, no write handler
179 {
180 auto file = fbl::AdoptRef<fs::Vnode>(new fs::UnbufferedPseudoFile(&DummyReader));
181 EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE));
182 EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
183 EXPECT_EQ(ZX_ERR_NOT_DIR, file->ValidateFlags(ZX_FS_FLAG_DIRECTORY));
184 fbl::RefPtr<fs::Vnode> redirect;
185 EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_READABLE));
186 EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_READABLE, &redirect));
187 EXPECT_NONNULL(redirect);
188 }
189
190 // no read handler, write handler
191 {
192 auto file = fbl::AdoptRef<fs::Vnode>(new fs::UnbufferedPseudoFile(nullptr, &DummyWriter));
193 EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(ZX_FS_RIGHT_READABLE));
194 EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file->ValidateFlags(ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE));
195 EXPECT_EQ(ZX_ERR_NOT_DIR, file->ValidateFlags(ZX_FS_FLAG_DIRECTORY));
196 fbl::RefPtr<fs::Vnode> redirect;
197 EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
198 EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE, &redirect));
199 EXPECT_NONNULL(redirect);
200 }
201
202 // read handler, write handler
203 {
204 auto file = fbl::AdoptRef<fs::Vnode>(new fs::UnbufferedPseudoFile(&DummyReader, &DummyWriter));
205 EXPECT_EQ(ZX_ERR_NOT_DIR, file->ValidateFlags(ZX_FS_FLAG_DIRECTORY));
206 fbl::RefPtr<fs::Vnode> redirect;
207 EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_READABLE));
208 EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_READABLE, &redirect));
209 EXPECT_NONNULL(redirect);
210 redirect.reset();
211 EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE));
212 EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE, &redirect));
213 EXPECT_NONNULL(redirect);
214 redirect.reset();
215 EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
216 EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE, &redirect));
217 EXPECT_NONNULL(redirect);
218 }
219
220 END_TEST;
221 }
222
TestGetattrBuffered()223 bool TestGetattrBuffered() {
224 BEGIN_TEST;
225
226 // no read handler, no write handler
227 {
228 auto file = fbl::AdoptRef<fs::Vnode>(new fs::BufferedPseudoFile());
229 vnattr_t attr;
230 EXPECT_EQ(ZX_OK, file->Getattr(&attr));
231 EXPECT_EQ(V_TYPE_FILE, attr.mode);
232 EXPECT_EQ(1, attr.nlink);
233 EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_FLAG_VNODE_REF_ONLY));
234 vnattr_t path_attr;
235 EXPECT_EQ(ZX_OK, file->Getattr(&path_attr));
236 EXPECT_BYTES_EQ((uint8_t*) &attr, (uint8_t*) &path_attr, sizeof(attr), "");
237 }
238
239 // read handler, no write handler
240 {
241 auto file = fbl::AdoptRef<fs::Vnode>(new fs::BufferedPseudoFile(&DummyReader));
242 vnattr_t attr;
243 EXPECT_EQ(ZX_OK, file->Getattr(&attr));
244 EXPECT_EQ(V_TYPE_FILE | V_IRUSR, attr.mode);
245 EXPECT_EQ(1, attr.nlink);
246
247 fbl::RefPtr<fs::Vnode> redirect;
248 EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_READABLE));
249 EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_READABLE, &redirect));
250 vnattr_t open_attr;
251 EXPECT_EQ(ZX_OK, file->Getattr(&open_attr));
252 EXPECT_BYTES_EQ((uint8_t*)&attr, (uint8_t*)&open_attr, sizeof(attr), "");
253 }
254
255 // no read handler, write handler
256 {
257 auto file = fbl::AdoptRef<fs::Vnode>(new fs::BufferedPseudoFile(nullptr, &DummyWriter));
258 vnattr_t attr;
259 EXPECT_EQ(ZX_OK, file->Getattr(&attr));
260 EXPECT_EQ(V_TYPE_FILE | V_IWUSR, attr.mode);
261 EXPECT_EQ(1, attr.nlink);
262
263 fbl::RefPtr<fs::Vnode> redirect;
264 EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
265 EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE, &redirect));
266 vnattr_t open_attr;
267 EXPECT_EQ(ZX_OK, file->Getattr(&open_attr));
268 EXPECT_BYTES_EQ((uint8_t*)&attr, (uint8_t*)&open_attr, sizeof(attr), "");
269 }
270
271 // read handler, write handler
272 {
273 auto file = fbl::AdoptRef<fs::Vnode>(new fs::BufferedPseudoFile(&DummyReader, &DummyWriter));
274 vnattr_t attr;
275 EXPECT_EQ(ZX_OK, file->Getattr(&attr));
276 EXPECT_EQ(V_TYPE_FILE | V_IRUSR | V_IWUSR, attr.mode);
277 EXPECT_EQ(1, attr.nlink);
278
279 fbl::RefPtr<fs::Vnode> redirect;
280 EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE));
281 EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE, &redirect));
282 vnattr_t open_attr;
283 EXPECT_EQ(ZX_OK, file->Getattr(&open_attr));
284 EXPECT_BYTES_EQ((uint8_t*)&attr, (uint8_t*)&open_attr, sizeof(attr), "");
285 }
286
287 END_TEST;
288 }
289
TestGetattrUnbuffered()290 bool TestGetattrUnbuffered() {
291 BEGIN_TEST;
292
293 // no read handler, no write handler
294 {
295 auto file = fbl::AdoptRef<fs::Vnode>(new fs::UnbufferedPseudoFile());
296 vnattr_t attr;
297 EXPECT_EQ(ZX_OK, file->Getattr(&attr));
298 EXPECT_EQ(V_TYPE_FILE, attr.mode);
299 EXPECT_EQ(1, attr.nlink);
300
301 EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_FLAG_VNODE_REF_ONLY));
302 vnattr_t path_attr;
303 EXPECT_EQ(ZX_OK, file->Getattr(&path_attr));
304 EXPECT_BYTES_EQ((uint8_t*) &attr, (uint8_t*) &path_attr, sizeof(attr), "");
305 }
306
307 // read handler, no write handler
308 {
309 auto file = fbl::AdoptRef<fs::Vnode>(new fs::UnbufferedPseudoFile(&DummyReader));
310 vnattr_t attr;
311 EXPECT_EQ(ZX_OK, file->Getattr(&attr));
312 EXPECT_EQ(V_TYPE_FILE | V_IRUSR, attr.mode);
313 EXPECT_EQ(1, attr.nlink);
314
315 fbl::RefPtr<fs::Vnode> redirect;
316 EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_READABLE));
317 EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_READABLE, &redirect));
318 vnattr_t open_attr;
319 EXPECT_EQ(ZX_OK, file->Getattr(&open_attr));
320 EXPECT_BYTES_EQ((uint8_t*)&attr, (uint8_t*)&open_attr, sizeof(attr), "");
321 }
322
323 // no read handler, write handler
324 {
325 auto file = fbl::AdoptRef<fs::Vnode>(new fs::UnbufferedPseudoFile(nullptr, &DummyWriter));
326 vnattr_t attr;
327 EXPECT_EQ(ZX_OK, file->Getattr(&attr));
328 EXPECT_EQ(V_TYPE_FILE | V_IWUSR, attr.mode);
329 EXPECT_EQ(1, attr.nlink);
330
331 fbl::RefPtr<fs::Vnode> redirect;
332 EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
333 EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE, &redirect));
334 vnattr_t open_attr;
335 EXPECT_EQ(ZX_OK, file->Getattr(&open_attr));
336 EXPECT_BYTES_EQ((uint8_t*)&attr, (uint8_t*)&open_attr, sizeof(attr), "");
337 }
338
339 // read handler, write handler
340 {
341 auto file = fbl::AdoptRef<fs::Vnode>(new fs::UnbufferedPseudoFile(&DummyReader, &DummyWriter));
342 vnattr_t attr;
343 EXPECT_EQ(ZX_OK, file->Getattr(&attr));
344 EXPECT_EQ(V_TYPE_FILE | V_IRUSR | V_IWUSR, attr.mode);
345 EXPECT_EQ(1, attr.nlink);
346
347 fbl::RefPtr<fs::Vnode> redirect;
348 EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE));
349 EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE, &redirect));
350 vnattr_t open_attr;
351 EXPECT_EQ(ZX_OK, file->Getattr(&open_attr));
352 EXPECT_BYTES_EQ((uint8_t*)&attr, (uint8_t*)&open_attr, sizeof(attr), "");
353 }
354
355 END_TEST;
356 }
357
TestReadBuffered()358 bool TestReadBuffered() {
359 BEGIN_TEST;
360
361 VectorReader reader{"first", "second", "",
362 fbl::String(fbl::StringPiece("null\0null", 9u))};
363 auto file = fbl::AdoptRef<fs::Vnode>(new fs::BufferedPseudoFile(reader.GetHandler()));
364
365 {
366 fbl::RefPtr<fs::Vnode> redirect;
367 EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_READABLE));
368 EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_READABLE, &redirect));
369 EXPECT_TRUE(CheckRead(redirect, ZX_OK, 0u, 0u, ""));
370 EXPECT_TRUE(CheckRead(redirect, ZX_OK, 4u, 0u, "firs"));
371 EXPECT_TRUE(CheckRead(redirect, ZX_OK, 4u, 2u, "rst"));
372 EXPECT_TRUE(CheckRead(redirect, ZX_OK, 5u, 0u, "first"));
373 EXPECT_TRUE(CheckRead(redirect, ZX_OK, 8u, 0u, "first"));
374 EXPECT_EQ(ZX_OK, redirect->Close());
375 }
376
377 {
378 fbl::RefPtr<fs::Vnode> redirect;
379 EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_READABLE));
380 EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_READABLE, &redirect));
381 EXPECT_TRUE(CheckRead(redirect, ZX_OK, 4u, 2u, "cond"));
382 EXPECT_TRUE(CheckRead(redirect, ZX_OK, 6u, 0u, "second"));
383 EXPECT_TRUE(CheckRead(redirect, ZX_OK, 8u, 0u, "second"));
384 EXPECT_EQ(ZX_OK, redirect->Close());
385 }
386
387 {
388 fbl::RefPtr<fs::Vnode> redirect;
389 EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_READABLE));
390 EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_READABLE, &redirect));
391 EXPECT_TRUE(CheckRead(redirect, ZX_OK, 4u, 0u, ""));
392 EXPECT_TRUE(CheckRead(redirect, ZX_OK, 4u, 2u, ""));
393 EXPECT_EQ(ZX_OK, redirect->Close());
394 }
395
396 {
397 fbl::RefPtr<fs::Vnode> redirect;
398 EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_READABLE, &redirect));
399 EXPECT_TRUE(CheckRead(redirect, ZX_OK, 0u, 0u, ""));
400 EXPECT_TRUE(CheckRead(redirect, ZX_OK, 4u, 0u, "null"));
401 EXPECT_TRUE(CheckRead(redirect, ZX_OK, 4u, 2u, fbl::StringPiece("ll\0n", 4u)));
402 EXPECT_TRUE(CheckRead(redirect, ZX_OK, 9u, 0u, fbl::StringPiece("null\0null", 9u)));
403 EXPECT_TRUE(CheckRead(redirect, ZX_OK, 12u, 0u, fbl::StringPiece("null\0null", 9u)));
404 EXPECT_EQ(ZX_OK, redirect->Close());
405 }
406
407 {
408 fbl::RefPtr<fs::Vnode> redirect;
409 EXPECT_EQ(ZX_ERR_IO, file->Open(ZX_FS_RIGHT_READABLE, &redirect));
410 }
411
412 END_TEST;
413 }
414
TestReadUnbuffered()415 bool TestReadUnbuffered() {
416 BEGIN_TEST;
417
418 VectorReader reader{"first", "second", "third", "fourth", "fifth", "",
419 fbl::String(fbl::StringPiece("null\0null", 9u))};
420 auto file = fbl::AdoptRef<fs::Vnode>(new fs::UnbufferedPseudoFile(reader.GetHandler()));
421
422 {
423 fbl::RefPtr<fs::Vnode> redirect;
424 EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_READABLE));
425 EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_READABLE, &redirect));
426 EXPECT_TRUE(CheckRead(redirect, ZX_OK, 0u, 0u, ""));
427 EXPECT_TRUE(CheckRead(redirect, ZX_OK, 4u, 0u, "seco"));
428 EXPECT_TRUE(CheckRead(redirect, ZX_OK, 4u, 2u, ""));
429 EXPECT_TRUE(CheckRead(redirect, ZX_OK, 3u, 0u, "thi"));
430 EXPECT_TRUE(CheckRead(redirect, ZX_OK, 6u, 0u, "fourth"));
431 EXPECT_EQ(ZX_OK, redirect->Close());
432 }
433
434 {
435 fbl::RefPtr<fs::Vnode> redirect;
436 EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_READABLE));
437 EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_READABLE, &redirect));
438 EXPECT_TRUE(CheckRead(redirect, ZX_OK, 8u, 0u, "fifth"));
439 EXPECT_TRUE(CheckRead(redirect, ZX_OK, 4u, 0u, ""));
440 EXPECT_TRUE(CheckRead(redirect, ZX_OK, 12u, 0u, fbl::StringPiece("null\0null", 9u)));
441 EXPECT_TRUE(CheckRead(redirect, ZX_ERR_IO, 0u, 0u, ""));
442 EXPECT_EQ(ZX_OK, redirect->Close());
443 }
444
445 END_TEST;
446 }
447
TestWriteBuffered()448 bool TestWriteBuffered() {
449 BEGIN_TEST;
450
451 VectorWriter writer(6u);
452 auto file = fbl::AdoptRef<fs::Vnode>(new fs::BufferedPseudoFile(nullptr, writer.GetHandler(), 10u));
453
454 {
455 fbl::RefPtr<fs::Vnode> redirect;
456 EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
457 EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE, &redirect));
458 EXPECT_TRUE(CheckWrite(redirect, ZX_OK, 0u, "fixx", 4u));
459 EXPECT_TRUE(CheckWrite(redirect, ZX_OK, 0u, "", 0u));
460 EXPECT_TRUE(CheckWrite(redirect, ZX_OK, 2u, "rst", 3u));
461 EXPECT_EQ(ZX_OK, redirect->Close());
462 }
463
464 {
465 fbl::RefPtr<fs::Vnode> redirect;
466 EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
467 EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE, &redirect));
468 EXPECT_TRUE(CheckWrite(redirect, ZX_OK, 0u, "second", 6u));
469 EXPECT_EQ(ZX_OK, redirect->Close());
470 }
471
472 {
473 fbl::RefPtr<fs::Vnode> redirect;
474 EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
475 EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE, &redirect));
476 EXPECT_EQ(ZX_OK, redirect->Close());
477 }
478
479 {
480 fbl::RefPtr<fs::Vnode> redirect;
481 EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
482 EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE, &redirect));
483 EXPECT_TRUE(CheckAppend(redirect, ZX_OK, "thxrxxx", 7u, 7u));
484 EXPECT_TRUE(CheckWrite(redirect, ZX_OK, 2u, "i", 1u));
485 EXPECT_EQ(ZX_OK, redirect->Truncate(4u));
486 EXPECT_TRUE(CheckAppend(redirect, ZX_OK, "d", 5u, 1u));
487 EXPECT_EQ(ZX_OK, redirect->Close());
488 }
489
490 {
491 fbl::RefPtr<fs::Vnode> redirect;
492 EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
493 EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE, &redirect));
494 EXPECT_TRUE(CheckWrite(redirect, ZX_OK, 0u, "null", 4u));
495 EXPECT_EQ(ZX_OK, redirect->Truncate(5u));
496 EXPECT_TRUE(CheckAppend(redirect, ZX_OK, "null", 9u, 4u));
497 EXPECT_EQ(ZX_OK, redirect->Close());
498 }
499
500 {
501 fbl::RefPtr<fs::Vnode> redirect;
502 EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
503 EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE, &redirect));
504 EXPECT_EQ(ZX_ERR_NO_SPACE, redirect->Truncate(11u));
505 EXPECT_TRUE(CheckAppend(redirect, ZX_OK, "too-long", 8u, 8u));
506 EXPECT_TRUE(CheckAppend(redirect, ZX_OK, "-off-the-end", 10u, 2u));
507 EXPECT_TRUE(CheckAppend(redirect, ZX_ERR_NO_SPACE, "-overflow", 0u, 0u));
508 EXPECT_EQ(ZX_OK, redirect->Close());
509 }
510
511 {
512 fbl::RefPtr<fs::Vnode> redirect;
513 EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
514 EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE, &redirect));
515 EXPECT_EQ(ZX_ERR_IO, redirect->Close());
516 }
517
518 EXPECT_EQ(6u, writer.strings().size());
519 EXPECT_FSTR_EQ(writer.strings()[0], fbl::String("first"));
520 EXPECT_FSTR_EQ(writer.strings()[1], fbl::String("second"));
521 EXPECT_FSTR_EQ(writer.strings()[2], fbl::String(""));
522 EXPECT_FSTR_EQ(writer.strings()[3], fbl::String("third"));
523 EXPECT_FSTR_EQ(writer.strings()[4], fbl::String("null\0null", 9u));
524 EXPECT_FSTR_EQ(writer.strings()[5], fbl::String("too-long-o"));
525
526 END_TEST;
527 }
528
TestWriteUnbuffered()529 bool TestWriteUnbuffered() {
530 BEGIN_TEST;
531
532 VectorWriter writer(12u);
533 auto file = fbl::AdoptRef<fs::Vnode>(new fs::UnbufferedPseudoFile(nullptr, writer.GetHandler()));
534
535 {
536 fbl::RefPtr<fs::Vnode> redirect;
537 EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
538 EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE, &redirect));
539 EXPECT_TRUE(CheckWrite(redirect, ZX_OK, 0u, "first", 5u));
540 EXPECT_TRUE(CheckWrite(redirect, ZX_ERR_NO_SPACE, 2u, "xxx", 0u));
541 EXPECT_TRUE(CheckWrite(redirect, ZX_OK, 0u, "second", 6u));
542 EXPECT_EQ(ZX_OK, redirect->Close());
543 }
544
545 {
546 fbl::RefPtr<fs::Vnode> redirect;
547 EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
548 EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE, &redirect));
549 EXPECT_TRUE(CheckWrite(redirect, ZX_OK, 0u, "", 0u));
550 EXPECT_TRUE(CheckAppend(redirect, ZX_OK, "third", 5u, 5u));
551 EXPECT_TRUE(CheckAppend(redirect, ZX_OK, fbl::StringPiece("null\0null", 9u), 9u, 9u));
552 EXPECT_EQ(ZX_OK, redirect->Close());
553 }
554
555 {
556 fbl::RefPtr<fs::Vnode> redirect;
557 EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE | ZX_FS_FLAG_TRUNCATE));
558 EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE | ZX_FS_FLAG_TRUNCATE, &redirect));
559 EXPECT_EQ(ZX_OK, redirect->Close());
560 }
561
562 {
563 fbl::RefPtr<fs::Vnode> redirect;
564 EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE | ZX_FS_FLAG_CREATE));
565 EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE | ZX_FS_FLAG_CREATE, &redirect));
566 EXPECT_EQ(ZX_OK, redirect->Close());
567 }
568
569 {
570 fbl::RefPtr<fs::Vnode> redirect;
571 EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
572 EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE, &redirect));
573 EXPECT_EQ(ZX_OK, redirect->Truncate(0u));
574 EXPECT_EQ(ZX_OK, redirect->Close());
575 }
576
577 {
578 fbl::RefPtr<fs::Vnode> redirect;
579 EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
580 EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE, &redirect));
581 EXPECT_TRUE(CheckAppend(redirect, ZX_OK, "fourth", 6u, 6u));
582 EXPECT_EQ(ZX_OK, redirect->Close());
583 }
584
585 {
586 fbl::RefPtr<fs::Vnode> redirect;
587 EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
588 EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE, &redirect));
589 EXPECT_EQ(ZX_OK, redirect->Close());
590 }
591
592 {
593 fbl::RefPtr<fs::Vnode> redirect;
594 EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
595 EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE, &redirect));
596 EXPECT_TRUE(CheckAppend(redirect, ZX_OK, "fifth", 5u, 5u));
597 EXPECT_EQ(ZX_ERR_INVALID_ARGS, redirect->Truncate(10u));
598 EXPECT_EQ(ZX_OK, redirect->Truncate(0u));
599 EXPECT_EQ(ZX_OK, redirect->Close());
600 }
601
602 {
603 fbl::RefPtr<fs::Vnode> redirect;
604 EXPECT_EQ(ZX_OK, file->ValidateFlags(ZX_FS_RIGHT_WRITABLE));
605 EXPECT_EQ(ZX_OK, file->Open(ZX_FS_RIGHT_WRITABLE, &redirect));
606 EXPECT_TRUE(CheckWrite(redirect, ZX_OK, 0u, "a long string", 13u));
607 EXPECT_EQ(ZX_OK, redirect->Truncate(0u));
608 EXPECT_EQ(ZX_ERR_IO, redirect->Close());
609 }
610
611 EXPECT_EQ(12u, writer.strings().size());
612 EXPECT_FSTR_EQ(writer.strings()[0], fbl::String("first"));
613 EXPECT_FSTR_EQ(writer.strings()[1], fbl::String("second"));
614 EXPECT_FSTR_EQ(writer.strings()[2], fbl::String(""));
615 EXPECT_FSTR_EQ(writer.strings()[3], fbl::String("third"));
616 EXPECT_FSTR_EQ(writer.strings()[4], fbl::String("null\0null", 9u));
617 EXPECT_FSTR_EQ(writer.strings()[5], fbl::String(""));
618 EXPECT_FSTR_EQ(writer.strings()[6], fbl::String(""));
619 EXPECT_FSTR_EQ(writer.strings()[7], fbl::String(""));
620 EXPECT_FSTR_EQ(writer.strings()[8], fbl::String("fourth"));
621 EXPECT_FSTR_EQ(writer.strings()[9], fbl::String("fifth"));
622 EXPECT_FSTR_EQ(writer.strings()[10], fbl::String(""));
623 EXPECT_FSTR_EQ(writer.strings()[11], fbl::String("a long string"));
624
625 END_TEST;
626 }
627
628 } // namespace
629
630 BEGIN_TEST_CASE(pseudo_file_tests)
631 RUN_TEST(TestOpenValidationBuffered)
632 RUN_TEST(TestOpenValidationUnbuffered)
633 RUN_TEST(TestGetattrBuffered)
634 RUN_TEST(TestGetattrUnbuffered)
635 RUN_TEST(TestReadBuffered)
636 RUN_TEST(TestReadUnbuffered)
637 RUN_TEST(TestWriteBuffered)
638 RUN_TEST(TestWriteUnbuffered)
639 END_TEST_CASE(pseudo_file_tests)
640