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/vmo-file.h>
6
7 #include <limits.h>
8
9 #include <fuchsia/io/c/fidl.h>
10 #include <zircon/syscalls.h>
11 #include <zircon/syscalls/object.h>
12
13 #include <unittest/unittest.h>
14 #include <lib/zx/vmo.h>
15
16 namespace {
17
18 constexpr size_t VMO_SIZE = PAGE_SIZE * 3u;
19 constexpr size_t PAGE_0 = 0u;
20 constexpr size_t PAGE_1 = PAGE_SIZE;
21 constexpr size_t PAGE_2 = PAGE_SIZE * 2u;
22
GetKoid(zx_handle_t handle)23 zx_koid_t GetKoid(zx_handle_t handle) {
24 zx_info_handle_basic_t info;
25 zx_status_t status = zx_object_get_info(handle, ZX_INFO_HANDLE_BASIC, &info,
26 sizeof(info), nullptr, nullptr);
27 return status == ZX_OK ? info.koid : ZX_KOID_INVALID;
28 }
29
GetRights(zx_handle_t handle)30 zx_rights_t GetRights(zx_handle_t handle) {
31 zx_info_handle_basic_t info;
32 zx_status_t status = zx_object_get_info(handle, ZX_INFO_HANDLE_BASIC, &info,
33 sizeof(info), nullptr, nullptr);
34 return status == ZX_OK ? info.rights : 0u;
35 }
36
FillVmo(const zx::vmo & vmo,size_t offset,size_t length,uint8_t byte)37 bool FillVmo(const zx::vmo& vmo, size_t offset, size_t length, uint8_t byte) {
38 BEGIN_HELPER;
39
40 uint8_t data[length];
41 memset(data, byte, length);
42
43 zx_status_t status = vmo.write(data, offset, length);
44 ASSERT_EQ(ZX_OK, status);
45
46 END_HELPER;
47 }
48
CheckVmo(const zx::vmo & vmo,size_t offset,size_t length,uint8_t expected_byte)49 bool CheckVmo(const zx::vmo& vmo, size_t offset, size_t length, uint8_t expected_byte) {
50 BEGIN_HELPER;
51
52 uint8_t data[length];
53
54 zx_status_t status = vmo.read(data, offset, length);
55 ASSERT_EQ(ZX_OK, status);
56
57 for (size_t i = 0; i < length; i++) {
58 ASSERT_EQ(expected_byte, data[i]);
59 }
60
61 END_HELPER;
62 }
63
CheckData(uint8_t * data,size_t offset,size_t length,uint8_t expected_byte)64 bool CheckData(uint8_t* data, size_t offset, size_t length, uint8_t expected_byte) {
65 BEGIN_HELPER;
66
67 for (size_t i = 0; i < length; i++) {
68 ASSERT_EQ(expected_byte, data[i + offset]);
69 }
70
71 END_HELPER;
72 }
73
CreateVmoABC(zx::vmo * out_vmo)74 bool CreateVmoABC(zx::vmo* out_vmo) {
75 BEGIN_HELPER;
76
77 zx_status_t status = zx::vmo::create(VMO_SIZE, 0u, out_vmo);
78 ASSERT_EQ(ZX_OK, status);
79
80 ASSERT_TRUE(FillVmo(*out_vmo, PAGE_0, PAGE_SIZE, 'A'));
81 ASSERT_TRUE(FillVmo(*out_vmo, PAGE_1, PAGE_SIZE, 'B'));
82 ASSERT_TRUE(FillVmo(*out_vmo, PAGE_2, PAGE_SIZE, 'C'));
83
84 END_HELPER;
85 }
86
TestConstructor()87 bool TestConstructor() {
88 BEGIN_TEST;
89
90 zx::vmo abc;
91 ASSERT_TRUE(CreateVmoABC(&abc));
92
93 // default parameters
94 {
95 fs::VmoFile file(abc, 0u, PAGE_SIZE);
96 EXPECT_EQ(abc.get(), file.vmo_handle());
97 EXPECT_EQ(0u, file.offset());
98 EXPECT_EQ(PAGE_SIZE, file.length());
99 EXPECT_FALSE(file.is_writable());
100 EXPECT_EQ(fs::VmoFile::VmoSharing::DUPLICATE, file.vmo_sharing());
101 }
102
103 // everything explicit
104 {
105 fs::VmoFile file(abc, 3u, PAGE_2 + 1u, true, fs::VmoFile::VmoSharing::CLONE_COW);
106 EXPECT_EQ(abc.get(), file.vmo_handle());
107 EXPECT_EQ(3u, file.offset());
108 EXPECT_EQ(PAGE_2 + 1u, file.length());
109 EXPECT_TRUE(file.is_writable());
110 EXPECT_EQ(fs::VmoFile::VmoSharing::CLONE_COW, file.vmo_sharing());
111 }
112
113 END_TEST;
114 }
115
TestOpen()116 bool TestOpen() {
117 BEGIN_TEST;
118
119 zx::vmo abc;
120 ASSERT_TRUE(CreateVmoABC(&abc));
121
122 // read-only
123 {
124 fs::VmoFile file(abc, 0u, 0u);
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_NULL(redirect);
129 EXPECT_EQ(ZX_ERR_ACCESS_DENIED,
130 file.ValidateFlags(ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE));
131 EXPECT_NULL(redirect);
132 EXPECT_EQ(ZX_ERR_ACCESS_DENIED, file.ValidateFlags(ZX_FS_RIGHT_WRITABLE));
133 EXPECT_NULL(redirect);
134 EXPECT_EQ(ZX_ERR_NOT_DIR, file.ValidateFlags(ZX_FS_FLAG_DIRECTORY));
135 EXPECT_NULL(redirect);
136 }
137
138 // writable
139 {
140 fs::VmoFile file(abc, 0u, 0u, true);
141 fbl::RefPtr<fs::Vnode> redirect;
142 EXPECT_EQ(ZX_OK, file.ValidateFlags(ZX_FS_RIGHT_READABLE));
143 EXPECT_EQ(ZX_OK, file.Open(ZX_FS_RIGHT_READABLE, &redirect));
144 EXPECT_NULL(redirect);
145 EXPECT_EQ(ZX_OK, file.ValidateFlags(ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE));
146 EXPECT_EQ(ZX_OK, file.Open(ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE, &redirect));
147 EXPECT_NULL(redirect);
148 EXPECT_EQ(ZX_OK, file.ValidateFlags(ZX_FS_RIGHT_WRITABLE));
149 EXPECT_EQ(ZX_OK, file.Open(ZX_FS_RIGHT_WRITABLE, &redirect));
150 EXPECT_NULL(redirect);
151 EXPECT_EQ(ZX_ERR_NOT_DIR, file.ValidateFlags(ZX_FS_FLAG_DIRECTORY));
152 EXPECT_NULL(redirect);
153 }
154
155 END_TEST;
156 }
157
TestRead()158 bool TestRead() {
159 BEGIN_TEST;
160
161 zx::vmo abc;
162 ASSERT_TRUE(CreateVmoABC(&abc));
163
164 uint8_t data[VMO_SIZE];
165 memset(data, 0, VMO_SIZE);
166
167 // empty read of non-empty file
168 {
169 fs::VmoFile file(abc, 0u, PAGE_SIZE);
170 size_t actual = UINT64_MAX;
171 EXPECT_EQ(ZX_OK, file.Read(data, 0u, 0u, &actual));
172 EXPECT_EQ(0u, actual);
173 }
174
175 // non-empty read of empty file
176 {
177 fs::VmoFile file(abc, 0u, 0u);
178 size_t actual = UINT64_MAX;
179 EXPECT_EQ(ZX_OK, file.Read(data, 1u, 0u, &actual));
180 EXPECT_EQ(0u, actual);
181 }
182
183 // empty read at end of file
184 {
185 fs::VmoFile file(abc, 0u, 10u);
186 size_t actual = UINT64_MAX;
187 EXPECT_EQ(ZX_OK, file.Read(data, 0u, 10u, &actual));
188 EXPECT_EQ(0u, actual);
189 }
190
191 // non-empty read at end of file
192 {
193 fs::VmoFile file(abc, 0u, 10u);
194 size_t actual = UINT64_MAX;
195 EXPECT_EQ(ZX_OK, file.Read(data, 1u, 10u, &actual));
196 EXPECT_EQ(0u, actual);
197 }
198
199 // empty read beyond end of file
200 {
201 fs::VmoFile file(abc, 0u, 10u);
202 size_t actual = UINT64_MAX;
203 EXPECT_EQ(ZX_OK, file.Read(data, 0u, 11u, &actual));
204 EXPECT_EQ(0u, actual);
205 }
206
207 // non-empty read beyond end of file
208 {
209 fs::VmoFile file(abc, 0u, 10u);
210 size_t actual = UINT64_MAX;
211 EXPECT_EQ(ZX_OK, file.Read(data, 1u, 11u, &actual));
212 EXPECT_EQ(0u, actual);
213 }
214
215 // short read of non-empty file
216 {
217 fs::VmoFile file(abc, PAGE_1 - 3u, 10u);
218 size_t actual = UINT64_MAX;
219 EXPECT_EQ(ZX_OK, file.Read(data, 11u, 1u, &actual));
220 EXPECT_EQ(9u, actual);
221 EXPECT_TRUE(CheckData(data, 0u, 2u, 'A'));
222 EXPECT_TRUE(CheckData(data, 2u, 7u, 'B'));
223 }
224
225 // full read
226 {
227 fs::VmoFile file(abc, 0u, VMO_SIZE);
228 size_t actual = UINT64_MAX;
229 EXPECT_EQ(ZX_OK, file.Read(data, VMO_SIZE, 0u, &actual));
230 EXPECT_EQ(VMO_SIZE, actual);
231 EXPECT_TRUE(CheckData(data, PAGE_0, PAGE_SIZE, 'A'));
232 EXPECT_TRUE(CheckData(data, PAGE_1, PAGE_SIZE, 'B'));
233 EXPECT_TRUE(CheckData(data, PAGE_2, PAGE_SIZE, 'C'));
234 }
235
236 END_TEST;
237 }
238
TestWrite()239 bool TestWrite() {
240 BEGIN_TEST;
241
242 zx::vmo abc;
243 ASSERT_TRUE(CreateVmoABC(&abc));
244
245 uint8_t data[VMO_SIZE];
246 memset(data, '!', VMO_SIZE);
247
248 // empty write of non-empty file
249 {
250 fs::VmoFile file(abc, 0u, PAGE_SIZE, true);
251 size_t actual = UINT64_MAX;
252 EXPECT_EQ(ZX_OK, file.Write(data, 0u, 0u, &actual));
253 EXPECT_EQ(0u, actual);
254 EXPECT_TRUE(CheckVmo(abc, PAGE_0, PAGE_SIZE, 'A'));
255 EXPECT_TRUE(CheckVmo(abc, PAGE_1, PAGE_SIZE, 'B'));
256 EXPECT_TRUE(CheckVmo(abc, PAGE_2, PAGE_SIZE, 'C'));
257 }
258
259 // non-empty write of empty file
260 {
261 fs::VmoFile file(abc, 0u, 0u, true);
262 size_t actual = UINT64_MAX;
263 EXPECT_EQ(ZX_ERR_NO_SPACE, file.Write(data, 1u, 0u, &actual));
264 }
265
266 // empty write at end of file
267 {
268 fs::VmoFile file(abc, 0u, 10u, true);
269 size_t actual = UINT64_MAX;
270 EXPECT_EQ(ZX_OK, file.Write(data, 0u, 10u, &actual));
271 EXPECT_EQ(0u, actual);
272 EXPECT_TRUE(CheckVmo(abc, PAGE_0, PAGE_SIZE, 'A'));
273 EXPECT_TRUE(CheckVmo(abc, PAGE_1, PAGE_SIZE, 'B'));
274 EXPECT_TRUE(CheckVmo(abc, PAGE_2, PAGE_SIZE, 'C'));
275 }
276
277 // non-empty write at end of file
278 {
279 fs::VmoFile file(abc, 0u, 10u, true);
280 size_t actual = UINT64_MAX;
281 EXPECT_EQ(ZX_ERR_NO_SPACE, file.Write(data, 1u, 10u, &actual));
282 }
283
284 // empty write beyond end of file
285 {
286 fs::VmoFile file(abc, 0u, 10u, true);
287 size_t actual = UINT64_MAX;
288 EXPECT_EQ(ZX_OK, file.Write(data, 0u, 11u, &actual));
289 EXPECT_EQ(0u, actual);
290 EXPECT_TRUE(CheckVmo(abc, PAGE_0, PAGE_SIZE, 'A'));
291 EXPECT_TRUE(CheckVmo(abc, PAGE_1, PAGE_SIZE, 'B'));
292 EXPECT_TRUE(CheckVmo(abc, PAGE_2, PAGE_SIZE, 'C'));
293 }
294
295 // non-empty write beyond end of file
296 {
297 fs::VmoFile file(abc, 0u, 10u, true);
298 size_t actual = UINT64_MAX;
299 EXPECT_EQ(ZX_ERR_NO_SPACE, file.Write(data, 1u, 11u, &actual));
300 }
301
302 // short write of non-empty file
303 {
304 fs::VmoFile file(abc, PAGE_1 - 3u, 10u, true);
305 size_t actual = UINT64_MAX;
306 EXPECT_EQ(ZX_OK, file.Write(data, 11u, 1u, &actual));
307 EXPECT_EQ(9u, actual);
308 EXPECT_TRUE(CheckVmo(abc, PAGE_0, PAGE_SIZE - 2u, 'A'));
309 EXPECT_TRUE(CheckVmo(abc, PAGE_1 - 2u, 9u, '!'));
310 EXPECT_TRUE(CheckVmo(abc, PAGE_1 + 7u, PAGE_SIZE - 7u, 'B'));
311 EXPECT_TRUE(CheckVmo(abc, PAGE_2, PAGE_SIZE, 'C'));
312 }
313
314 // full write
315 {
316 fs::VmoFile file(abc, 0u, VMO_SIZE, true);
317 size_t actual = UINT64_MAX;
318 EXPECT_EQ(ZX_OK, file.Write(data, VMO_SIZE, 0u, &actual));
319 EXPECT_EQ(VMO_SIZE, actual);
320 EXPECT_TRUE(CheckVmo(abc, 0u, VMO_SIZE, '!'));
321 }
322
323 END_TEST;
324 }
325
TestGetattr()326 bool TestGetattr() {
327 BEGIN_TEST;
328
329 zx::vmo abc;
330 ASSERT_TRUE(CreateVmoABC(&abc));
331
332 // read-only
333 {
334 fs::VmoFile file(abc, 0u, PAGE_SIZE * 3u + 117u);
335 vnattr_t attr;
336 EXPECT_EQ(ZX_OK, file.Getattr(&attr));
337 EXPECT_EQ(V_TYPE_FILE | V_IRUSR, attr.mode);
338 EXPECT_EQ(PAGE_SIZE * 3u + 117u, attr.size);
339 EXPECT_EQ(PAGE_SIZE, attr.blksize);
340 EXPECT_EQ(4u * PAGE_SIZE / VNATTR_BLKSIZE, attr.blkcount);
341 EXPECT_EQ(1u, attr.nlink);
342 }
343
344 // writable
345 {
346 fs::VmoFile file(abc, 0u, PAGE_SIZE * 3u + 117u, true);
347 vnattr_t attr;
348 EXPECT_EQ(ZX_OK, file.Getattr(&attr));
349 EXPECT_EQ(V_TYPE_FILE | V_IRUSR | V_IWUSR, attr.mode);
350 EXPECT_EQ(PAGE_SIZE * 3u + 117u, attr.size);
351 EXPECT_EQ(PAGE_SIZE, attr.blksize);
352 EXPECT_EQ(4u * PAGE_SIZE / VNATTR_BLKSIZE, attr.blkcount);
353 EXPECT_EQ(1u, attr.nlink);
354 }
355
356 END_TEST;
357 }
358
TestGetHandles()359 bool TestGetHandles() {
360 BEGIN_TEST;
361
362 // sharing = VmoSharing::NONE
363 {
364 zx::vmo abc;
365 ASSERT_TRUE(CreateVmoABC(&abc));
366
367 fuchsia_io_NodeInfo info;
368 fs::VmoFile file(abc, PAGE_1 - 5u, 23u, false, fs::VmoFile::VmoSharing::NONE);
369 EXPECT_EQ(ZX_ERR_NOT_SUPPORTED, file.GetHandles(ZX_FS_RIGHT_READABLE, &info));
370 }
371
372 // sharing = VmoSharing::DUPLICATE, read only
373 {
374 zx::vmo abc;
375 ASSERT_TRUE(CreateVmoABC(&abc));
376
377 fuchsia_io_NodeInfo info;
378 fs::VmoFile file(abc, PAGE_1 - 5u, 23u, false, fs::VmoFile::VmoSharing::DUPLICATE);
379 EXPECT_EQ(ZX_OK, file.GetHandles(ZX_FS_RIGHT_READABLE, &info));
380 zx::vmo vmo(info.vmofile.vmo);
381 EXPECT_NE(abc.get(), vmo.get());
382 EXPECT_EQ(GetKoid(abc.get()), GetKoid(vmo.get()));
383 EXPECT_EQ(ZX_RIGHTS_BASIC | ZX_RIGHT_MAP | ZX_RIGHT_READ | ZX_RIGHT_EXECUTE,
384 GetRights(vmo.get()));
385 EXPECT_EQ(fuchsia_io_NodeInfoTag_vmofile, info.tag);
386 EXPECT_EQ(PAGE_1 - 5u, info.vmofile.offset);
387 EXPECT_EQ(23u, info.vmofile.length);
388
389 EXPECT_TRUE(CheckVmo(vmo, PAGE_1 - 5u, 5u, 'A'));
390 EXPECT_TRUE(CheckVmo(vmo, PAGE_1, 18u, 'B'));
391 }
392
393 // sharing = VmoSharing::DUPLICATE, read-write
394 {
395 zx::vmo abc;
396 ASSERT_TRUE(CreateVmoABC(&abc));
397
398 fuchsia_io_NodeInfo info;
399 fs::VmoFile file(abc, PAGE_1 - 5u, 23u, true, fs::VmoFile::VmoSharing::DUPLICATE);
400 EXPECT_EQ(ZX_OK, file.GetHandles(ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE, &info));
401 zx::vmo vmo(info.vmofile.vmo);
402 EXPECT_NE(abc.get(), vmo.get());
403 EXPECT_EQ(GetKoid(abc.get()), GetKoid(vmo.get()));
404 EXPECT_EQ(ZX_RIGHTS_BASIC | ZX_RIGHT_MAP | ZX_RIGHT_READ | ZX_RIGHT_WRITE,
405 GetRights(vmo.get()));
406 EXPECT_EQ(fuchsia_io_NodeInfoTag_vmofile, info.tag);
407 EXPECT_EQ(PAGE_1 - 5u, info.vmofile.offset);
408 EXPECT_EQ(23u, info.vmofile.length);
409
410 EXPECT_TRUE(CheckVmo(vmo, PAGE_1 - 5u, 5u, 'A'));
411 EXPECT_TRUE(CheckVmo(vmo, PAGE_1, 18u, 'B'));
412
413 EXPECT_TRUE(FillVmo(vmo, PAGE_1 - 5u, 23u, '!'));
414
415 EXPECT_TRUE(CheckVmo(abc, 0u, PAGE_SIZE - 5u, 'A'));
416 EXPECT_TRUE(CheckVmo(abc, PAGE_1 - 5u, 23u, '!'));
417 EXPECT_TRUE(CheckVmo(abc, PAGE_1 + 18u, PAGE_SIZE - 18u, 'B'));
418 EXPECT_TRUE(CheckVmo(abc, PAGE_2, PAGE_SIZE, 'C'));
419 }
420
421 // sharing = VmoSharing::DUPLICATE, write only
422 {
423 zx::vmo abc;
424 ASSERT_TRUE(CreateVmoABC(&abc));
425
426 fuchsia_io_NodeInfo info;
427 fs::VmoFile file(abc, PAGE_1 - 5u, 23u, true, fs::VmoFile::VmoSharing::DUPLICATE);
428 EXPECT_EQ(ZX_OK, file.GetHandles(ZX_FS_RIGHT_WRITABLE, &info));
429 zx::vmo vmo(info.vmofile.vmo);
430 EXPECT_NE(abc.get(), vmo.get());
431 EXPECT_EQ(GetKoid(abc.get()), GetKoid(vmo.get()));
432 EXPECT_EQ(ZX_RIGHTS_BASIC | ZX_RIGHT_MAP | ZX_RIGHT_WRITE,
433 GetRights(vmo.get()));
434 EXPECT_EQ(fuchsia_io_NodeInfoTag_vmofile, info.tag);
435 EXPECT_EQ(PAGE_1 - 5u, info.vmofile.offset);
436 EXPECT_EQ(23u, info.vmofile.length);
437
438 EXPECT_TRUE(FillVmo(vmo, PAGE_1 - 5u, 23u, '!'));
439
440 EXPECT_TRUE(CheckVmo(abc, 0u, PAGE_SIZE - 5u, 'A'));
441 EXPECT_TRUE(CheckVmo(abc, PAGE_1 - 5u, 23u, '!'));
442 EXPECT_TRUE(CheckVmo(abc, PAGE_1 + 18u, PAGE_SIZE - 18u, 'B'));
443 EXPECT_TRUE(CheckVmo(abc, PAGE_2, PAGE_SIZE, 'C'));
444 }
445
446 // sharing = VmoSharing::CLONE_COW, read only
447 {
448 zx::vmo abc;
449 ASSERT_TRUE(CreateVmoABC(&abc));
450
451 fuchsia_io_NodeInfo info;
452 fs::VmoFile file(abc, PAGE_2 - 5u, 23u, false, fs::VmoFile::VmoSharing::CLONE_COW);
453 EXPECT_EQ(ZX_OK, file.GetHandles(ZX_FS_RIGHT_READABLE, &info));
454 zx::vmo vmo(info.vmofile.vmo);
455 EXPECT_NE(abc.get(), vmo.get());
456 EXPECT_NE(GetKoid(abc.get()), GetKoid(vmo.get()));
457 EXPECT_EQ(ZX_RIGHTS_BASIC | ZX_RIGHT_MAP | ZX_RIGHT_READ | ZX_RIGHT_EXECUTE,
458 GetRights(vmo.get()));
459 EXPECT_EQ(fuchsia_io_NodeInfoTag_vmofile, info.tag);
460 EXPECT_EQ(PAGE_SIZE - 5u, info.vmofile.offset);
461 EXPECT_EQ(23u, info.vmofile.length);
462
463 EXPECT_TRUE(CheckVmo(vmo, PAGE_SIZE - 5u, 5u, 'B'));
464 EXPECT_TRUE(CheckVmo(vmo, PAGE_SIZE, 18u, 'C'));
465 }
466
467 // sharing = VmoSharing::CLONE_COW, read-write
468 {
469 zx::vmo abc;
470 ASSERT_TRUE(CreateVmoABC(&abc));
471
472 fuchsia_io_NodeInfo info;
473 fs::VmoFile file(abc, PAGE_2 - 5u, 23u, true, fs::VmoFile::VmoSharing::CLONE_COW);
474 EXPECT_EQ(ZX_OK, file.GetHandles(ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE, &info));
475 zx::vmo vmo(info.vmofile.vmo);
476 EXPECT_NE(abc.get(), vmo.get());
477 EXPECT_NE(GetKoid(abc.get()), GetKoid(vmo.get()));
478 EXPECT_EQ(ZX_RIGHTS_BASIC | ZX_RIGHT_MAP | ZX_RIGHT_READ | ZX_RIGHT_WRITE,
479 GetRights(vmo.get()));
480 EXPECT_EQ(fuchsia_io_NodeInfoTag_vmofile, info.tag);
481 EXPECT_EQ(PAGE_SIZE - 5u, info.vmofile.offset);
482 EXPECT_EQ(23u, info.vmofile.length);
483
484 EXPECT_TRUE(CheckVmo(vmo, PAGE_SIZE - 5u, 5u, 'B'));
485 EXPECT_TRUE(CheckVmo(vmo, PAGE_SIZE, 18u, 'C'));
486
487 EXPECT_TRUE(FillVmo(vmo, PAGE_SIZE - 5u, 23u, '!'));
488
489 EXPECT_TRUE(CheckVmo(abc, PAGE_0, PAGE_SIZE, 'A'));
490 EXPECT_TRUE(CheckVmo(abc, PAGE_1, PAGE_SIZE, 'B'));
491 EXPECT_TRUE(CheckVmo(abc, PAGE_2, PAGE_SIZE, 'C'));
492 }
493
494 // sharing = VmoSharing::CLONE_COW, write only
495 {
496 zx::vmo abc;
497 ASSERT_TRUE(CreateVmoABC(&abc));
498
499 fuchsia_io_NodeInfo info;
500 fs::VmoFile file(abc, PAGE_2 - 5u, 23u, true, fs::VmoFile::VmoSharing::CLONE_COW);
501 EXPECT_EQ(ZX_OK, file.GetHandles(ZX_FS_RIGHT_WRITABLE, &info));
502 zx::vmo vmo(info.vmofile.vmo);
503 EXPECT_NE(abc.get(), vmo.get());
504 EXPECT_NE(GetKoid(abc.get()), GetKoid(vmo.get()));
505 EXPECT_EQ(ZX_RIGHTS_BASIC | ZX_RIGHT_MAP | ZX_RIGHT_WRITE,
506 GetRights(vmo.get()));
507 EXPECT_EQ(fuchsia_io_NodeInfoTag_vmofile, info.tag);
508 EXPECT_EQ(PAGE_SIZE - 5u, info.vmofile.offset);
509 EXPECT_EQ(23u, info.vmofile.length);
510
511 EXPECT_TRUE(FillVmo(vmo, PAGE_SIZE - 5u, 23u, '!'));
512
513 EXPECT_TRUE(CheckVmo(abc, PAGE_0, PAGE_SIZE, 'A'));
514 EXPECT_TRUE(CheckVmo(abc, PAGE_1, PAGE_SIZE, 'B'));
515 EXPECT_TRUE(CheckVmo(abc, PAGE_2, PAGE_SIZE, 'C'));
516 }
517
518 END_TEST;
519 }
520
521 } // namespace
522
523 BEGIN_TEST_CASE(vmo_file_tests)
524 RUN_TEST(TestConstructor)
525 RUN_TEST(TestOpen)
526 RUN_TEST(TestRead)
527 RUN_TEST(TestWrite)
528 RUN_TEST(TestGetattr)
529 RUN_TEST(TestGetHandles)
530 END_TEST_CASE(vmo_file_tests)
531