vfs/file/
test_utils.rs

1// Copyright 2019 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//! Common utilities used by pseudo-file related tests.
6
7use crate::directory::entry::DirectoryEntry;
8use crate::test_utils::run::{self, AsyncServerClientTestParams};
9
10use fidl_fuchsia_io as fio;
11use futures::Future;
12use std::sync::Arc;
13use zx_status::Status;
14
15pub use run::{run_client, test_client};
16
17/// A thin wrapper around [`run::run_server_client()`] that sets the `Marker` to be
18/// [`FileMarker`], and providing explicit type for the `get_client` closure argument.  This makes
19/// it possible for the caller not to provide explicit types.
20pub fn run_server_client<GetClientRes>(
21    flags: fio::OpenFlags,
22    server: Arc<dyn DirectoryEntry>,
23    get_client: impl FnOnce(fio::FileProxy) -> GetClientRes,
24) where
25    GetClientRes: Future<Output = ()>,
26{
27    run::run_server_client::<fio::FileMarker, _, _>(flags, server, get_client)
28}
29
30/// A thin wrapper around [`run::test_server_client()`] that sets the `Marker` to be
31/// [`FileMarker`], and providing explicit type for the `get_client` closure argument.  This makes
32/// it possible for the caller not to provide explicit types.
33pub fn test_server_client<'test_refs, GetClientRes>(
34    flags: fio::OpenFlags,
35    server: Arc<dyn DirectoryEntry>,
36    get_client: impl FnOnce(fio::FileProxy) -> GetClientRes + 'test_refs,
37) -> AsyncServerClientTestParams<'test_refs, fio::FileMarker>
38where
39    GetClientRes: Future<Output = ()> + 'test_refs,
40{
41    run::test_server_client::<fio::FileMarker, _, _>(flags, server, get_client)
42}
43
44/// Possible errors for the [`assert_vmo_content()`] function.
45pub enum AssertVmoContentError {
46    /// Failure returned from the `vmo.get_content_size()` call.
47    GetContentSizeFailed(Status),
48    /// Failure returned from the `vmo.read()` call.
49    VmoReadFailed(Status),
50    /// Expected content and the actual VMO content did not match.
51    UnexpectedContent(Vec<u8>),
52}
53
54/// Reads the VMO content and matches it against the expectation.
55#[cfg(target_os = "fuchsia")]
56pub fn assert_vmo_content(vmo: &fidl::Vmo, expected: &[u8]) -> Result<(), AssertVmoContentError> {
57    let size =
58        vmo.get_content_size().map_err(AssertVmoContentError::GetContentSizeFailed)? as usize;
59    let mut buffer = vec![0; size];
60    vmo.read(&mut buffer, 0).map_err(AssertVmoContentError::VmoReadFailed)?;
61    if buffer != expected {
62        Err(AssertVmoContentError::UnexpectedContent(buffer))
63    } else {
64        Ok(())
65    }
66}
67
68/// Wraps an [`assert_vmo_content()`] call, panicking with a descriptive error message for any `Err`
69/// return values.
70#[macro_export]
71macro_rules! assert_vmo_content {
72    ($vmo:expr, $expected:expr) => {{
73        use $crate::file::test_utils::{assert_vmo_content, AssertVmoContentError};
74
75        let expected = $expected;
76        match assert_vmo_content($vmo, expected) {
77            Ok(()) => (),
78            Err(AssertVmoContentError::GetContentSizeFailed(status)) => {
79                panic!("`vmo.get_content_size()` failed: {}", status)
80            }
81            Err(AssertVmoContentError::VmoReadFailed(status)) => {
82                panic!("`vmo.read(&mut buffer, 0)` failed: {}", status)
83            }
84            Err(AssertVmoContentError::UnexpectedContent(buffer)) => panic!(
85                "Unexpected content:\n\
86                 Expected: {:x?}\n\
87                 Actual:   {:x?}\n\
88                 Expected as UTF-8 lossy: {:?}\n\
89                 Actual as UTF-8 lossy:   {:?}",
90                expected,
91                &buffer,
92                String::from_utf8_lossy(expected),
93                String::from_utf8_lossy(&buffer),
94            ),
95        }
96    }};
97}