blob: 0a1d6696af86d95205914eb2020d0fc4f4dd2711 [file] [log] [blame]
// Copyright 2023 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.
use {
fidl::endpoints::create_proxy,
fidl_fuchsia_io as fio,
fuchsia_fs::directory::{WatchEvent, WatchMessage, Watcher},
fuchsia_zircon as zx,
futures::StreamExt,
io_conformance_util::{test_harness::TestHarness, *},
std::path::PathBuf,
};
#[fuchsia::test]
async fn watch_dir_existing() {
let harness = TestHarness::new().await;
if !harness.config.supports_directory_watchers {
return;
}
let root = root_directory(vec![file("foo", b"test".to_vec())]);
let root_dir = harness.get_directory(root, harness.dir_rights.all());
let mut watcher = Watcher::new(&root_dir).await.expect("making watcher");
assert_eq!(
watcher.next().await.expect("watcher stream empty").expect("watch message error"),
WatchMessage { event: WatchEvent::EXISTING, filename: PathBuf::from(".") },
);
assert_eq!(
watcher.next().await.expect("watcher stream empty").expect("watch message error"),
WatchMessage { event: WatchEvent::EXISTING, filename: PathBuf::from("foo") },
);
assert_eq!(
watcher.next().await.expect("watcher stream empty").expect("watch message error"),
WatchMessage { event: WatchEvent::IDLE, filename: PathBuf::new() },
);
}
#[fuchsia::test]
async fn watch_dir_added_removed() {
let harness = TestHarness::new().await;
if !harness.config.supports_directory_watchers {
return;
}
if !harness.config.supports_create {
return;
}
let root = root_directory(vec![]);
let root_dir = harness.get_directory(root, harness.dir_rights.all());
let mut watcher = Watcher::new(&root_dir).await.expect("making watcher");
assert_eq!(
watcher.next().await.expect("watcher stream empty").expect("watch message error"),
WatchMessage { event: WatchEvent::EXISTING, filename: PathBuf::from(".") },
);
assert_eq!(
watcher.next().await.expect("watcher stream empty").expect("watch message error"),
WatchMessage { event: WatchEvent::IDLE, filename: PathBuf::new() },
);
let _ = open_dir_with_flags(
&root_dir,
fio::OpenFlags::RIGHT_WRITABLE | fio::OpenFlags::CREATE,
"foo",
)
.await;
assert_eq!(
watcher.next().await.expect("watcher stream empty").expect("watch message error"),
WatchMessage { event: WatchEvent::ADD_FILE, filename: PathBuf::from("foo") },
);
let _ = open_dir_with_flags(
&root_dir,
fio::OpenFlags::RIGHT_WRITABLE | fio::OpenFlags::CREATE | fio::OpenFlags::DIRECTORY,
"dir",
)
.await;
assert_eq!(
watcher.next().await.expect("watcher stream empty").expect("watch message error"),
WatchMessage { event: WatchEvent::ADD_FILE, filename: PathBuf::from("dir") },
);
root_dir
.unlink("foo", &fio::UnlinkOptions::default())
.await
.expect("fidl error")
.expect("unlink error");
assert_eq!(
watcher.next().await.expect("watcher stream empty").expect("watch message error"),
WatchMessage { event: WatchEvent::REMOVE_FILE, filename: PathBuf::from("foo") },
);
}
#[fuchsia::test]
async fn watch_dir_existing_file_create_does_not_generate_new_event() {
let harness = TestHarness::new().await;
if !harness.config.supports_directory_watchers {
return;
}
if !harness.config.supports_create {
return;
}
let root = root_directory(vec![]);
let root_dir = harness.get_directory(root, harness.dir_rights.all());
let mut watcher = Watcher::new(&root_dir).await.expect("making watcher");
assert_eq!(
watcher.next().await.expect("watcher stream empty").expect("watch message error"),
WatchMessage { event: WatchEvent::EXISTING, filename: PathBuf::from(".") },
);
assert_eq!(
watcher.next().await.expect("watcher stream empty").expect("watch message error"),
WatchMessage { event: WatchEvent::IDLE, filename: PathBuf::new() },
);
let _ = open_dir_with_flags(
&root_dir,
fio::OpenFlags::RIGHT_WRITABLE | fio::OpenFlags::CREATE,
"foo",
)
.await;
assert_eq!(
watcher.next().await.expect("watcher stream empty").expect("watch message error"),
WatchMessage { event: WatchEvent::ADD_FILE, filename: PathBuf::from("foo") },
);
{
let (client, server) = create_proxy::<fio::NodeMarker>().expect("Cannot create proxy.");
root_dir
.open(
fio::OpenFlags::RIGHT_WRITABLE | fio::OpenFlags::CREATE | fio::OpenFlags::DESCRIBE,
fio::ModeType::empty(),
"foo",
server,
)
.expect("Cannot open file");
// Open should succeed - CREATE is fine if the file already exists.
assert_eq!(get_open_status(&client).await, zx::Status::OK);
}
// Since we are testing that the previous open does _not_ generate an event, do something else
// that will generate a different event and make sure that is the next event.
root_dir
.unlink("foo", &fio::UnlinkOptions::default())
.await
.expect("fidl error")
.expect("unlink error");
assert_eq!(
watcher.next().await.expect("watcher stream empty").expect("watch message error"),
WatchMessage { event: WatchEvent::REMOVE_FILE, filename: PathBuf::from("foo") },
);
}
#[fuchsia::test]
async fn watch_dir_rename() {
let harness = TestHarness::new().await;
if !harness.config.supports_directory_watchers {
return;
}
if !harness.config.supports_create {
return;
}
if !harness.config.supports_rename {
return;
}
let root = root_directory(vec![]);
let root_dir = harness.get_directory(root, harness.dir_rights.all());
let mut watcher = Watcher::new(&root_dir).await.expect("making watcher");
assert_eq!(
watcher.next().await.expect("watcher stream empty").expect("watch message error"),
WatchMessage { event: WatchEvent::EXISTING, filename: PathBuf::from(".") },
);
assert_eq!(
watcher.next().await.expect("watcher stream empty").expect("watch message error"),
WatchMessage { event: WatchEvent::IDLE, filename: PathBuf::new() },
);
let _ = open_dir_with_flags(
&root_dir,
fio::OpenFlags::RIGHT_WRITABLE | fio::OpenFlags::CREATE,
"foo",
)
.await;
assert_eq!(
watcher.next().await.expect("watcher stream empty").expect("watch message error"),
WatchMessage { event: WatchEvent::ADD_FILE, filename: PathBuf::from("foo") },
);
let (status, token) = root_dir.get_token().await.unwrap();
assert_eq!(zx::Status::from_raw(status), zx::Status::OK);
let token = token.unwrap();
root_dir.rename("foo", token.into(), "bar").await.expect("fidl error").expect("rename error");
assert_eq!(
watcher.next().await.expect("watcher stream empty").expect("watch message error"),
WatchMessage { event: WatchEvent::REMOVE_FILE, filename: PathBuf::from("foo") },
);
assert_eq!(
watcher.next().await.expect("watcher stream empty").expect("watch message error"),
WatchMessage { event: WatchEvent::ADD_FILE, filename: PathBuf::from("bar") },
);
root_dir
.unlink("bar", &fio::UnlinkOptions::default())
.await
.expect("fidl error")
.expect("unlink error");
assert_eq!(
watcher.next().await.expect("watcher stream empty").expect("watch message error"),
WatchMessage { event: WatchEvent::REMOVE_FILE, filename: PathBuf::from("bar") },
);
}