| // Copyright 2020 The Fuchsia Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #![cfg(test)] | |
| use { | |
| blobfs_ramdisk::BlobfsRamdisk, | |
| fuchsia_async as fasync, | |
| fuchsia_pkg_testing::{PackageBuilder, SystemImageBuilder}, | |
| fuchsia_zircon::Status, | |
| pkgfs_ramdisk::PkgfsRamdisk, | |
| std::convert::{TryFrom as _, TryInto as _}, | |
| }; | |
| fn make_file_contents(size: usize) -> impl Iterator<Item = u8> { | |
| b"ABCD".iter().copied().cycle().take(size) | |
| } | |
| // zero is a multiple | |
| fn round_up_to_4096_multiple(val: usize) -> usize { | |
| (val + 4095) & !4095 | |
| } | |
| // meta far file VMOs are zero-padded to the smallest multiple of 4096 | |
| fn validate_vmo_contents(file_size: usize, vmo_contents: &[u8]) { | |
| let vmo_size = round_up_to_4096_multiple(file_size); | |
| assert!( | |
| make_file_contents(file_size) | |
| .chain(std::iter::repeat(b'\0')) | |
| .take(vmo_size) | |
| .eq(vmo_contents.iter().copied()), | |
| "vmo content mismatch for file size {}", | |
| file_size | |
| ); | |
| } | |
| #[fasync::run_singlethreaded(test)] | |
| async fn meta_far_file() { | |
| let file_sizes = [0, 1, 4095, 4096, 4097]; | |
| let mut base_pkg_with_meta_files = PackageBuilder::new("example"); | |
| for size in &file_sizes { | |
| base_pkg_with_meta_files = base_pkg_with_meta_files.add_resource_at( | |
| format!("meta/{}", size), | |
| make_file_contents(*size).collect::<Vec<u8>>().as_slice(), | |
| ); | |
| } | |
| let base_pkg_with_meta_files = base_pkg_with_meta_files.build().await.expect("build package"); | |
| let system_image = | |
| SystemImageBuilder::new().static_packages(&[&base_pkg_with_meta_files]).build().await; | |
| let blobfs = BlobfsRamdisk::start().unwrap(); | |
| system_image.write_to_blobfs_dir(&blobfs.root_dir().unwrap()); | |
| base_pkg_with_meta_files.write_to_blobfs_dir(&blobfs.root_dir().unwrap()); | |
| let pkgfs = PkgfsRamdisk::builder() | |
| .blobfs(blobfs) | |
| .system_image_merkle(system_image.meta_far_merkle_root()) | |
| .start() | |
| .unwrap(); | |
| let d = pkgfs.root_dir_proxy().expect("getting pkgfs root dir"); | |
| for size in &file_sizes { | |
| let meta_far_file = io_util::directory::open_file( | |
| &d, | |
| &format!("versions/{}/meta/{}", base_pkg_with_meta_files.meta_far_merkle_root(), size), | |
| io_util::OPEN_RIGHT_READABLE, | |
| ) | |
| .await | |
| .unwrap(); | |
| let (status, buffer) = meta_far_file | |
| .get_buffer(fidl_fuchsia_io::VMO_FLAG_READ | fidl_fuchsia_io::VMO_FLAG_PRIVATE) | |
| .await | |
| .unwrap(); | |
| Status::ok(status).unwrap(); | |
| let buffer = buffer.unwrap(); | |
| assert_eq!(buffer.size, u64::try_from(*size).unwrap()); | |
| let vmo_size = buffer.vmo.get_size().unwrap().try_into().unwrap(); | |
| let mut actual_contents = vec![0u8; vmo_size]; | |
| let () = buffer.vmo.read(actual_contents.as_mut_slice(), 0).unwrap(); | |
| validate_vmo_contents(*size, &actual_contents); | |
| } | |
| // Drop the directory before we shutdown the server that's serving it. | |
| // In practice, this probably doesn't make a difference. | |
| drop(d); | |
| pkgfs.stop().await.expect("stopping pkgfs"); | |
| } |