// Copyright 2019 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.

pub mod admin_protocol;
use {
    crate::{
        channel,
        model::{
            component::{BindReason, ComponentInstance},
            component_id_index::ComponentInstanceId,
            error::ModelError,
        },
    },
    anyhow::Error,
    clonable_error::ClonableError,
    cm_rust::CapabilityPath,
    fidl::endpoints,
    fidl_fuchsia_io::{
        DirectoryMarker, DirectoryProxy, MODE_TYPE_DIRECTORY, OPEN_RIGHT_READABLE,
        OPEN_RIGHT_WRITABLE,
    },
    moniker::{AbsoluteMoniker, RelativeMoniker},
    std::{path::PathBuf, sync::Arc},
    thiserror::Error,
};

const FLAGS: u32 = OPEN_RIGHT_READABLE | OPEN_RIGHT_WRITABLE;

/// Errors related to isolated storage.
#[derive(Debug, Error, Clone)]
pub enum StorageError {
    #[error(
        "failed to open isolated storage from {:?}'s directory {} for {} (instance_id={:?}): {} ",
        dir_source_moniker,
        dir_source_path,
        relative_moniker,
        instance_id,
        err
    )]
    Open {
        dir_source_moniker: Option<AbsoluteMoniker>,
        dir_source_path: CapabilityPath,
        relative_moniker: RelativeMoniker,
        instance_id: Option<ComponentInstanceId>,
        #[source]
        err: ClonableError,
    },
    #[error(
        "failed to remove isolated storage from {:?}'s directory {} for {} (instance_id={:?}): {} ",
        dir_source_moniker,
        dir_source_path,
        relative_moniker,
        instance_id,
        err
    )]
    Remove {
        dir_source_moniker: Option<AbsoluteMoniker>,
        dir_source_path: CapabilityPath,
        relative_moniker: RelativeMoniker,
        instance_id: Option<ComponentInstanceId>,
        #[source]
        err: ClonableError,
    },
    #[error(
        "storage path for relative_moniker={}, instance_id={:?} is invalid",
        relative_moniker,
        instance_id
    )]
    InvalidStoragePath {
        relative_moniker: RelativeMoniker,
        instance_id: Option<ComponentInstanceId>,
    },
}

impl StorageError {
    pub fn open(
        dir_source_moniker: Option<AbsoluteMoniker>,
        dir_source_path: CapabilityPath,
        relative_moniker: RelativeMoniker,
        instance_id: Option<ComponentInstanceId>,
        err: impl Into<Error>,
    ) -> Self {
        Self::Open {
            dir_source_moniker,
            dir_source_path,
            relative_moniker,
            instance_id,
            err: err.into().into(),
        }
    }

    pub fn remove(
        dir_source_moniker: Option<AbsoluteMoniker>,
        dir_source_path: CapabilityPath,
        relative_moniker: RelativeMoniker,
        instance_id: Option<ComponentInstanceId>,
        err: impl Into<Error>,
    ) -> Self {
        Self::Remove {
            dir_source_moniker,
            dir_source_path,
            relative_moniker,
            instance_id,
            err: err.into().into(),
        }
    }

    pub fn invalid_storage_path(
        relative_moniker: RelativeMoniker,
        instance_id: Option<ComponentInstanceId>,
    ) -> Self {
        Self::InvalidStoragePath { relative_moniker, instance_id }
    }
}

/// Information returned by the route_storage_capability function on the source of a storage
/// capability.
#[derive(Clone, Debug)]
pub struct StorageCapabilitySource {
    /// The component that's providing the backing directory capability for this storage
    /// capability. If None, then the backing directory comes from component_manager's namespace.
    pub storage_provider: Option<Arc<ComponentInstance>>,

    /// The path to the backing directory in the providing component's outgoing directory (or
    /// component_manager's namespace).
    pub backing_directory_path: CapabilityPath,

    /// The subdirectory inside of the backing directory capability to use, if any
    pub backing_directory_subdir: Option<PathBuf>,

    /// The subdirectory inside of the backing directory's sub-directory to use, if any. The
    /// difference between this and backing_directory_subdir is that backing_directory_subdir is
    /// appended to backing_directory_path first, and component_manager will create this subdir if
    /// it doesn't exist but won't create backing_directory_subdir.
    pub storage_subdir: Option<PathBuf>,
}

/// Open the isolated storage sub-directory for the given component, creating it if necessary.
/// `dir_source_component` and `dir_source_path` are the component hosting the directory and its
/// capability path.
///
/// The storage sub-directory is based on provided instance ID if present, otherwise it is based on
/// the provided relative moniker.
pub async fn open_isolated_storage(
    storage_source_info: StorageCapabilitySource,
    relative_moniker: RelativeMoniker,
    instance_id: Option<&ComponentInstanceId>,
    open_mode: u32,
    bind_reason: &BindReason,
) -> Result<DirectoryProxy, ModelError> {
    // TODO: The `use` declaration for storage implicitly carries these rights. While this is
    // correct, it would be more consistent to get the rights from `CapabilityState` and pass them
    // here.
    const FLAGS: u32 = OPEN_RIGHT_READABLE | OPEN_RIGHT_WRITABLE;
    let (mut dir_proxy, local_server_end) =
        endpoints::create_proxy::<DirectoryMarker>().expect("failed to create proxy");
    let mut local_server_end = local_server_end.into_channel();
    let full_backing_directory_path = match storage_source_info.backing_directory_subdir.as_ref() {
        Some(subdir) => storage_source_info.backing_directory_path.to_path_buf().join(subdir),
        None => storage_source_info.backing_directory_path.to_path_buf(),
    };
    if let Some(dir_source_component) = storage_source_info.storage_provider.as_ref() {
        dir_source_component
            .bind(bind_reason)
            .await?
            .open_outgoing(
                FLAGS,
                open_mode,
                full_backing_directory_path.clone(),
                &mut local_server_end,
            )
            .await?;
    } else {
        // If storage_source_info.storage_provider is None, the directory comes from component_manager's namespace
        let local_server_end = channel::take_channel(&mut local_server_end);
        let path = full_backing_directory_path
            .to_str()
            .ok_or_else(|| ModelError::path_is_not_utf8(full_backing_directory_path.clone()))?;
        io_util::connect_in_namespace(path, local_server_end, FLAGS).map_err(|e| {
            ModelError::from(StorageError::open(
                None,
                storage_source_info.backing_directory_path.clone(),
                relative_moniker.clone(),
                instance_id.cloned(),
                e,
            ))
        })?;
    }
    if let Some(subdir) = storage_source_info.storage_subdir.as_ref() {
        dir_proxy = io_util::create_sub_directories(&dir_proxy, subdir.as_path()).map_err(|e| {
            ModelError::from(StorageError::open(
                storage_source_info.storage_provider.as_ref().map(|r| r.abs_moniker.clone()),
                storage_source_info.backing_directory_path.clone(),
                relative_moniker.clone(),
                instance_id.cloned(),
                e,
            ))
        })?;
    }
    let storage_path = instance_id
        .map(|id| generate_instance_id_based_storage_path(id))
        .unwrap_or_else(|| generate_moniker_based_storage_path(&relative_moniker));

    io_util::create_sub_directories(&dir_proxy, &storage_path).map_err(|e| {
        ModelError::from(StorageError::open(
            storage_source_info.storage_provider.as_ref().map(|r| r.abs_moniker.clone()),
            storage_source_info.backing_directory_path.clone(),
            relative_moniker.clone(),
            instance_id.cloned(),
            e,
        ))
    })
}

/// Delete the isolated storage sub-directory for the given component.  `dir_source_component` and
/// `dir_source_path` are the component hosting the directory and its capability path.
pub async fn delete_isolated_storage(
    storage_source_info: StorageCapabilitySource,
    relative_moniker: RelativeMoniker,
    instance_id: Option<&ComponentInstanceId>,
) -> Result<(), ModelError> {
    let (root_dir, local_server_end) =
        endpoints::create_proxy::<DirectoryMarker>().expect("failed to create proxy");
    let mut local_server_end = local_server_end.into_channel();
    let full_backing_directory_path = match storage_source_info.backing_directory_subdir.as_ref() {
        Some(subdir) => storage_source_info.backing_directory_path.to_path_buf().join(subdir),
        None => storage_source_info.backing_directory_path.to_path_buf(),
    };
    if let Some(dir_source_component) = storage_source_info.storage_provider.as_ref() {
        // TODO(fxbug.dev/50716): This BindReason is wrong. We need to refactor the Storage
        // capability to plumb through the correct BindReason.
        dir_source_component
            .bind(&BindReason::Unsupported)
            .await?
            .open_outgoing(
                FLAGS,
                MODE_TYPE_DIRECTORY,
                full_backing_directory_path,
                &mut local_server_end,
            )
            .await?;
    } else {
        let local_server_end = channel::take_channel(&mut local_server_end);
        let path = full_backing_directory_path
            .to_str()
            .ok_or_else(|| ModelError::path_is_not_utf8(full_backing_directory_path.clone()))?;
        io_util::connect_in_namespace(path, local_server_end, FLAGS).map_err(|e| {
            StorageError::open(
                None,
                storage_source_info.backing_directory_path.clone(),
                relative_moniker.clone(),
                None,
                e,
            )
        })?;
    }

    let (dir, name) = if let Some(instance_id) = instance_id {
        let storage_path = generate_instance_id_based_storage_path(instance_id);
        let file_name = storage_path
            .file_name()
            .ok_or_else(|| {
                StorageError::invalid_storage_path(
                    relative_moniker.clone(),
                    Some(instance_id.clone()),
                )
            })?
            .to_str()
            .ok_or_else(|| ModelError::name_is_not_utf8(storage_path.clone().into_os_string()))?
            .to_string();

        let parent_path = storage_path.parent().ok_or_else(|| {
            StorageError::invalid_storage_path(relative_moniker.clone(), Some(instance_id.clone()))
        })?;
        let dir = if parent_path
            .to_str()
            .ok_or_else(|| ModelError::name_is_not_utf8(storage_path.clone().into_os_string()))?
            .is_empty()
        {
            root_dir
        } else {
            io_util::open_directory(&root_dir, parent_path, FLAGS).map_err(|e| {
                StorageError::open(
                    storage_source_info.storage_provider.as_ref().map(|r| r.abs_moniker.clone()),
                    storage_source_info.backing_directory_path.clone(),
                    relative_moniker.clone(),
                    None,
                    e,
                )
            })?
        };
        (dir, file_name)
    } else {
        let storage_path = generate_moniker_based_storage_path(&relative_moniker);
        // We want to strip off the "data" portion of the path, and then one more level to get to the
        // directory holding the target component's storage.
        if storage_path.parent().and_then(|p| p.parent()).is_none() {
            return Err(StorageError::invalid_storage_path(relative_moniker.clone(), None).into());
        }
        let mut dir_path = storage_path.parent().unwrap().parent().unwrap().to_path_buf();
        let name = storage_path.parent().unwrap().file_name().ok_or_else(|| {
            ModelError::from(StorageError::invalid_storage_path(relative_moniker.clone(), None))
        })?;
        let name =
            name.to_str().ok_or_else(|| ModelError::name_is_not_utf8(name.to_os_string()))?;
        if let Some(subdir) = storage_source_info.storage_subdir.as_ref() {
            dir_path = subdir.join(dir_path);
        }

        let dir = if dir_path.parent().is_none() {
            root_dir
        } else {
            io_util::open_directory(&root_dir, &dir_path, FLAGS).map_err(|e| {
                StorageError::open(
                    storage_source_info.storage_provider.as_ref().map(|r| r.abs_moniker.clone()),
                    storage_source_info.backing_directory_path.clone(),
                    relative_moniker.clone(),
                    None,
                    e,
                )
            })?
        };
        (dir, name.to_string())
    };

    // TODO(fxbug.dev/36377): This function is subject to races. If another process has a handle to the
    // isolated storage directory, it can add files while this function is running. That could
    // cause it to spin or fail because a subdir was not empty after it removed all the contents.
    // It's also possible that the directory was already deleted by the backing component or a
    // prior run.
    files_async::remove_dir_recursive(&dir, &name).await.map_err(|e| {
        StorageError::remove(
            storage_source_info.storage_provider.as_ref().map(|r| r.abs_moniker.clone()),
            storage_source_info.backing_directory_path.clone(),
            relative_moniker.clone(),
            instance_id.cloned(),
            e,
        )
    })?;
    Ok(())
}

/// Generates the path into a directory the provided component will be afforded for storage
///
/// The path of the sub-directory for a component that uses a storage capability is based on each
/// component instance's child moniker as given in the `children` section of its parent's manifest,
/// for each component instance in the path from the `storage` declaration to the
/// `use` declaration.
///
/// These names are used as path elements, separated by elements of the name "children". The
/// string "data" is then appended to this path for compatibility reasons.
///
/// For example, if the following component instance tree exists, with `a` declaring storage
/// capabilities, and then storage being offered down the chain to `d`:
///
/// ```
///  a  <- declares storage "cache", offers "cache" to b
///  |
///  b  <- offers "cache" to c
///  |
///  c  <- offers "cache" to d
///  |
///  d  <- uses "cache" storage as `/my_cache`
/// ```
///
/// When `d` attempts to access `/my_cache` the framework creates the sub-directory
/// `b:0/children/c:0/children/d:0/data` in the directory used by `a` to declare storage
/// capabilities.  Then, the framework gives 'd' access to this new directory.
fn generate_moniker_based_storage_path(relative_moniker: &RelativeMoniker) -> PathBuf {
    assert!(
        !relative_moniker.down_path().is_empty(),
        "storage capability appears to have been exposed or used by its source"
    );

    let mut down_path = relative_moniker.down_path().iter();
    let mut dir_path = vec![down_path.next().unwrap().as_str().to_string()];
    while let Some(p) = down_path.next() {
        dir_path.push("children".to_string());
        dir_path.push(p.as_str().to_string());
    }

    // Storage capabilities used to have a hardcoded set of types, which would be appended
    // here. To maintain compatibility with the old paths (and thus not lose data when this was
    // migrated) we append "data" here. This works because this is the only type of storage
    // that was actually used in the wild.
    //
    // This is only temporary, until the storage instance id migration changes this layout.
    dir_path.push("data".to_string());
    dir_path.into_iter().collect()
}

/// Generates the component storage directory path for the provided component instance.
///
/// Components which do not have an instance ID use a generate moniker-based storage path instead.
fn generate_instance_id_based_storage_path(instance_id: &ComponentInstanceId) -> PathBuf {
    [instance_id].iter().collect()
}

#[cfg(test)]
mod tests {
    use super::*;
    use {
        crate::model::{
            component::BindReason,
            rights,
            routing::error::OpenResourceError,
            testing::routing_test_helpers::{RoutingTest, RoutingTestBuilder},
            testing::test_helpers::{self, component_decl_with_test_runner, ComponentDeclBuilder},
        },
        cm_rust::*,
        component_id_index, fidl_fuchsia_io2 as fio2,
        matches::assert_matches,
        rand::{self, distributions::Alphanumeric, Rng},
        std::convert::{TryFrom, TryInto},
    };

    #[fuchsia::test]
    async fn open_isolated_storage_test() {
        let components = vec![
            ("a", ComponentDeclBuilder::new().add_lazy_child("b").add_lazy_child("c").build()),
            (
                "b",
                ComponentDeclBuilder::new()
                    .directory(DirectoryDecl {
                        name: "data".into(),
                        source_path: "/data".try_into().unwrap(),
                        rights: *rights::READ_RIGHTS | *rights::WRITE_RIGHTS,
                    })
                    .expose(ExposeDecl::Directory(ExposeDirectoryDecl {
                        source_name: "data".try_into().unwrap(),
                        source: ExposeSource::Self_,
                        target_name: "data".try_into().unwrap(),
                        target: ExposeTarget::Parent,
                        rights: Some(fio2::Operations::Connect),
                        subdir: None,
                    }))
                    .build(),
            ),
        ];
        let test = RoutingTest::new("a", components).await;
        let b_component = test
            .model
            .look_up(&vec!["b:0"].into())
            .await
            .expect("failed to find component for b:0");
        let dir_source_path = CapabilityPath::try_from("/data").unwrap();
        let relative_moniker = RelativeMoniker::new(vec![], vec!["c:0".into(), "coll:d:1".into()]);

        // Open.
        let dir = open_isolated_storage(
            StorageCapabilitySource {
                storage_provider: Some(Arc::clone(&b_component)),
                backing_directory_path: dir_source_path.clone(),
                backing_directory_subdir: None,
                storage_subdir: None,
            },
            relative_moniker.clone(),
            None,
            OPEN_RIGHT_READABLE | OPEN_RIGHT_WRITABLE,
            &BindReason::Eager,
        )
        .await
        .expect("failed to open isolated storage");
        assert_eq!(test_helpers::list_directory(&dir).await, Vec::<String>::new());
        test_helpers::write_file(&dir, "file", "hippos").await;
        assert_eq!(test_helpers::list_directory(&dir).await, vec!["file".to_string()]);

        // Open again.
        let dir = open_isolated_storage(
            StorageCapabilitySource {
                storage_provider: Some(Arc::clone(&b_component)),
                backing_directory_path: dir_source_path.clone(),
                backing_directory_subdir: None,
                storage_subdir: None,
            },
            relative_moniker.clone(),
            None,
            OPEN_RIGHT_READABLE | OPEN_RIGHT_WRITABLE,
            &BindReason::Eager,
        )
        .await
        .expect("failed to open isolated storage");
        assert_eq!(test_helpers::list_directory(&dir).await, vec!["file".to_string()]);

        // Open another component's storage.
        let relative_moniker =
            RelativeMoniker::new(vec![], vec!["c:0".into(), "coll:d:1".into(), "e:0".into()]);
        let dir = open_isolated_storage(
            StorageCapabilitySource {
                storage_provider: Some(Arc::clone(&b_component)),
                backing_directory_path: dir_source_path.clone(),
                backing_directory_subdir: None,
                storage_subdir: None,
            },
            relative_moniker.clone(),
            None,
            OPEN_RIGHT_READABLE | OPEN_RIGHT_WRITABLE,
            &BindReason::Eager,
        )
        .await
        .expect("failed to open isolated storage");
        assert_eq!(test_helpers::list_directory(&dir).await, Vec::<String>::new());
        test_helpers::write_file(&dir, "file", "hippos").await;
        assert_eq!(test_helpers::list_directory(&dir).await, vec!["file".to_string()]);
    }

    #[fuchsia::test]
    async fn open_isolated_storage_instance_id() {
        let components = vec![
            ("a", ComponentDeclBuilder::new().add_lazy_child("b").add_lazy_child("c").build()),
            (
                "b",
                ComponentDeclBuilder::new()
                    .directory(DirectoryDecl {
                        name: "data".into(),
                        source_path: "/data".try_into().unwrap(),
                        rights: *rights::READ_RIGHTS | *rights::WRITE_RIGHTS,
                    })
                    .expose(ExposeDecl::Directory(ExposeDirectoryDecl {
                        source_name: "data".try_into().unwrap(),
                        source: ExposeSource::Self_,
                        target_name: "data".try_into().unwrap(),
                        target: ExposeTarget::Parent,
                        rights: Some(fio2::Operations::Connect),
                        subdir: None,
                    }))
                    .build(),
            ),
        ];
        let test = RoutingTest::new("a", components).await;
        let b_component = test
            .model
            .look_up(&vec!["b:0"].into())
            .await
            .expect("failed to find component for b:0");
        let dir_source_path = CapabilityPath::try_from("/data").unwrap();
        let relative_moniker = RelativeMoniker::new(vec![], vec!["c:0".into(), "coll:d:1".into()]);

        // open the storage directory using instance ID.
        let instance_id = Some(component_id_index::gen_instance_id(&mut rand::thread_rng()));
        let mut dir = open_isolated_storage(
            StorageCapabilitySource {
                storage_provider: Some(Arc::clone(&b_component)),
                backing_directory_path: dir_source_path.clone(),
                backing_directory_subdir: None,
                storage_subdir: None,
            },
            relative_moniker.clone(),
            instance_id.as_ref(),
            OPEN_RIGHT_READABLE | OPEN_RIGHT_WRITABLE,
            &BindReason::Eager,
        )
        .await
        .expect("failed to open isolated storage");

        // ensure the directory is actually open before querying its parent about it.
        dir.describe().await.expect("failed to open directory");

        // check that an instance-ID based directory was created:
        assert!(test_helpers::list_directory(&test.test_dir_proxy)
            .await
            .contains(&instance_id.clone().unwrap()));

        // check that a moniker-based directory was NOT created:
        assert!(!test_helpers::list_directory_recursive(&test.test_dir_proxy).await.contains(
            &generate_moniker_based_storage_path(&relative_moniker).to_str().unwrap().to_string()
        ));

        // check that the directory is writable by writing a marker file in it.
        let marker_file_name: String =
            rand::thread_rng().sample_iter(&Alphanumeric).take(7).map(char::from).collect();
        assert_eq!(test_helpers::list_directory(&dir).await, Vec::<String>::new());
        test_helpers::write_file(&dir, &marker_file_name, "contents").await;
        assert_eq!(test_helpers::list_directory(&dir).await, vec![marker_file_name.clone()]);

        // check that re-opening the directory gives us the same marker file.
        dir = open_isolated_storage(
            StorageCapabilitySource {
                storage_provider: Some(Arc::clone(&b_component)),
                backing_directory_path: dir_source_path.clone(),
                backing_directory_subdir: None,
                storage_subdir: None,
            },
            relative_moniker.clone(),
            instance_id.as_ref(),
            OPEN_RIGHT_READABLE | OPEN_RIGHT_WRITABLE,
            &BindReason::Eager,
        )
        .await
        .expect("failed to open isolated storage");

        assert_eq!(test_helpers::list_directory(&dir).await, vec![marker_file_name.clone()]);
    }

    // TODO: test with different subdirs

    #[fuchsia::test]
    async fn open_isolated_storage_failure_test() {
        let components = vec![("a", component_decl_with_test_runner())];

        // Create a universe with a single component, whose outgoing directory service
        // simply closes the channel of incoming requests.
        let test = RoutingTestBuilder::new("a", components)
            .set_component_outgoing_host_fn("a", Box::new(|_| {}))
            .build()
            .await;
        test.bind_instance_and_wait_start(&AbsoluteMoniker::root()).await.unwrap();

        // Try to open the storage. We expect an error.
        let relative_moniker = RelativeMoniker::new(vec![], vec!["c:0".into(), "coll:d:1".into()]);
        let res = open_isolated_storage(
            StorageCapabilitySource {
                storage_provider: Some(Arc::clone(&test.model.root)),
                backing_directory_path: CapabilityPath::try_from("/data").unwrap().clone(),
                backing_directory_subdir: None,
                storage_subdir: None,
            },
            relative_moniker.clone(),
            None,
            OPEN_RIGHT_READABLE | OPEN_RIGHT_WRITABLE,
            &BindReason::Eager,
        )
        .await;
        assert_matches!(
            res,
            Err(ModelError::OpenResourceError {
                err: OpenResourceError::OpenOutgoingFailed { .. }
            })
        );
    }

    #[fuchsia::test]
    async fn delete_isolated_storage_test() {
        let components = vec![
            ("a", ComponentDeclBuilder::new().add_lazy_child("b").add_lazy_child("c").build()),
            (
                "b",
                ComponentDeclBuilder::new()
                    .directory(DirectoryDecl {
                        name: "data".into(),
                        source_path: "/data".try_into().unwrap(),
                        rights: *rights::READ_RIGHTS | *rights::WRITE_RIGHTS,
                    })
                    .expose(ExposeDecl::Directory(ExposeDirectoryDecl {
                        source_name: "data".try_into().unwrap(),
                        source: ExposeSource::Self_,
                        target_name: "data".try_into().unwrap(),
                        target: ExposeTarget::Parent,
                        rights: Some(fio2::Operations::Connect),
                        subdir: None,
                    }))
                    .build(),
            ),
        ];
        let test = RoutingTest::new("a", components).await;
        let b_component = test
            .model
            .look_up(&vec!["b:0"].into())
            .await
            .expect("failed to find component for b:0");
        let dir_source_path = CapabilityPath::try_from("/data").unwrap();
        let parent_moniker = RelativeMoniker::new(vec![], vec!["c:0".into()]);
        let child_moniker = RelativeMoniker::new(vec![], vec!["c:0".into(), "coll:d:1".into()]);

        // Open and write to the storage for child.
        let dir = open_isolated_storage(
            StorageCapabilitySource {
                storage_provider: Some(Arc::clone(&b_component)),
                backing_directory_path: dir_source_path.clone(),
                backing_directory_subdir: None,
                storage_subdir: None,
            },
            child_moniker.clone(),
            None,
            OPEN_RIGHT_READABLE | OPEN_RIGHT_WRITABLE,
            &BindReason::Eager,
        )
        .await
        .expect("failed to open isolated storage");
        assert_eq!(test_helpers::list_directory(&dir).await, Vec::<String>::new());
        test_helpers::write_file(&dir, "file", "hippos").await;
        assert_eq!(test_helpers::list_directory(&dir).await, vec!["file".to_string()]);

        // Open parent's storage.
        let dir = open_isolated_storage(
            StorageCapabilitySource {
                storage_provider: Some(Arc::clone(&b_component)),
                backing_directory_path: dir_source_path.clone(),
                backing_directory_subdir: None,
                storage_subdir: None,
            },
            parent_moniker.clone(),
            None,
            OPEN_RIGHT_READABLE | OPEN_RIGHT_WRITABLE,
            &BindReason::Eager,
        )
        .await
        .expect("failed to open isolated storage");
        assert_eq!(test_helpers::list_directory(&dir).await, Vec::<String>::new());
        test_helpers::write_file(&dir, "file", "hippos").await;
        assert_eq!(test_helpers::list_directory(&dir).await, vec!["file".to_string()]);

        // Delete the child's storage.
        delete_isolated_storage(
            StorageCapabilitySource {
                storage_provider: Some(Arc::clone(&b_component)),
                backing_directory_path: dir_source_path.clone(),
                backing_directory_subdir: None,
                storage_subdir: None,
            },
            child_moniker.clone(),
            None,
        )
        .await
        .expect("failed to delete child's isolated storage");

        // Open parent's storage again. Should work.
        let dir = open_isolated_storage(
            StorageCapabilitySource {
                storage_provider: Some(Arc::clone(&b_component)),
                backing_directory_path: dir_source_path.clone(),
                backing_directory_subdir: None,
                storage_subdir: None,
            },
            parent_moniker.clone(),
            None,
            OPEN_RIGHT_READABLE | OPEN_RIGHT_WRITABLE,
            &BindReason::Eager,
        )
        .await
        .expect("failed to open isolated storage");
        assert_eq!(test_helpers::list_directory(&dir).await, vec!["file".to_string()]);

        // Open list of children from parent. Should not contain child directory.
        assert_eq!(
            test.list_directory_in_storage(None, parent_moniker.clone(), None, "children").await,
            Vec::<String>::new(),
        );

        // Error -- tried to delete nonexistent storage.
        let err = delete_isolated_storage(
            StorageCapabilitySource {
                storage_provider: Some(Arc::clone(&b_component)),
                backing_directory_path: dir_source_path,
                backing_directory_subdir: None,
                storage_subdir: None,
            },
            child_moniker,
            None,
        )
        .await
        .expect_err("delete isolated storage not meant to succeed");
        match err {
            ModelError::StorageError { err: StorageError::Remove { .. } } => {}
            _ => {
                panic!("unexpected error: {:?}", err);
            }
        }
    }

    #[fuchsia::test]
    async fn delete_isolated_storage_instance_id_test() {
        let components = vec![
            ("a", ComponentDeclBuilder::new().add_lazy_child("b").add_lazy_child("c").build()),
            (
                "b",
                ComponentDeclBuilder::new()
                    .directory(DirectoryDecl {
                        name: "data".into(),
                        source_path: "/data".try_into().unwrap(),
                        rights: *rights::READ_RIGHTS | *rights::WRITE_RIGHTS,
                    })
                    .expose(ExposeDecl::Directory(ExposeDirectoryDecl {
                        source_name: "data".try_into().unwrap(),
                        source: ExposeSource::Self_,
                        target_name: "data".try_into().unwrap(),
                        target: ExposeTarget::Parent,
                        rights: Some(fio2::Operations::Connect),
                        subdir: None,
                    }))
                    .build(),
            ),
        ];
        let test = RoutingTest::new("a", components).await;
        let b_component = test
            .model
            .look_up(&vec!["b:0"].into())
            .await
            .expect("failed to find component for b:0");
        let dir_source_path = CapabilityPath::try_from("/data").unwrap();
        let child_moniker = RelativeMoniker::new(vec![], vec!["c:0".into(), "coll:d:1".into()]);
        let instance_id = Some(component_id_index::gen_instance_id(&mut rand::thread_rng()));
        // Open and write to the storage for child.
        let dir = open_isolated_storage(
            StorageCapabilitySource {
                storage_provider: Some(Arc::clone(&b_component)),
                backing_directory_path: dir_source_path.clone(),
                backing_directory_subdir: None,
                storage_subdir: None,
            },
            child_moniker.clone(),
            instance_id.as_ref(),
            OPEN_RIGHT_READABLE | OPEN_RIGHT_WRITABLE,
            &BindReason::Eager,
        )
        .await
        .expect("failed to open isolated storage");

        // ensure the directory is actually open before querying its parent about it.
        dir.describe().await.expect("failed to open directory");

        // check that an instance-ID based directory was created:
        assert!(test_helpers::list_directory(&test.test_dir_proxy)
            .await
            .contains(&instance_id.clone().unwrap()));

        assert_eq!(test_helpers::list_directory(&dir).await, Vec::<String>::new());
        test_helpers::write_file(&dir, "file", "hippos").await;
        assert_eq!(test_helpers::list_directory(&dir).await, vec!["file".to_string()]);

        // Delete the child's storage.
        delete_isolated_storage(
            StorageCapabilitySource {
                storage_provider: Some(Arc::clone(&b_component)),
                backing_directory_path: dir_source_path.clone(),
                backing_directory_subdir: None,
                storage_subdir: None,
            },
            child_moniker.clone(),
            instance_id.as_ref(),
        )
        .await
        .expect("failed to delete child's isolated storage");

        // check that an instance-ID based directory was deleted:
        assert!(!test_helpers::list_directory(&test.test_dir_proxy)
            .await
            .contains(&instance_id.clone().unwrap()));

        // Error -- tried to delete nonexistent storage.
        let err = delete_isolated_storage(
            StorageCapabilitySource {
                storage_provider: Some(Arc::clone(&b_component)),
                backing_directory_path: dir_source_path,
                backing_directory_subdir: None,
                storage_subdir: None,
            },
            child_moniker,
            instance_id.as_ref(),
        )
        .await
        .expect_err("delete isolated storage not meant to succeed");
        match err {
            ModelError::StorageError { err: StorageError::Remove { .. } } => {}
            _ => {
                panic!("unexpected error: {:?}", err);
            }
        }
    }

    #[test]
    fn generate_moniker_based_storage_path_test() {
        for (relative_moniker, expected_output) in vec![
            (
                RelativeMoniker::from_absolute(
                    &AbsoluteMoniker::from(vec![]),
                    &AbsoluteMoniker::from(vec!["a:1"]),
                ),
                "a:1/data",
            ),
            (
                RelativeMoniker::from_absolute(
                    &AbsoluteMoniker::from(vec![]),
                    &AbsoluteMoniker::from(vec!["a:1", "b:2"]),
                ),
                "a:1/children/b:2/data",
            ),
            (
                RelativeMoniker::from_absolute(
                    &AbsoluteMoniker::from(vec![]),
                    &AbsoluteMoniker::from(vec!["a:1", "b:2", "c:3"]),
                ),
                "a:1/children/b:2/children/c:3/data",
            ),
        ] {
            assert_eq!(
                generate_moniker_based_storage_path(&relative_moniker),
                PathBuf::from(expected_output)
            )
        }
    }
}
