Add random delays in FakeFs
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
parent
2b8685c1a2
commit
0cfb9ff1ae
6 changed files with 30 additions and 21 deletions
|
@ -181,11 +181,12 @@ impl FakeFsState {
|
||||||
pub struct FakeFs {
|
pub struct FakeFs {
|
||||||
// Use an unfair lock to ensure tests are deterministic.
|
// Use an unfair lock to ensure tests are deterministic.
|
||||||
state: futures::lock::Mutex<FakeFsState>,
|
state: futures::lock::Mutex<FakeFsState>,
|
||||||
|
executor: std::sync::Arc<gpui::executor::Background>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(test, feature = "test-support"))]
|
#[cfg(any(test, feature = "test-support"))]
|
||||||
impl FakeFs {
|
impl FakeFs {
|
||||||
pub fn new() -> Self {
|
pub fn new(executor: std::sync::Arc<gpui::executor::Background>) -> Self {
|
||||||
let (events_tx, _) = postage::broadcast::channel(2048);
|
let (events_tx, _) = postage::broadcast::channel(2048);
|
||||||
let mut entries = std::collections::BTreeMap::new();
|
let mut entries = std::collections::BTreeMap::new();
|
||||||
entries.insert(
|
entries.insert(
|
||||||
|
@ -201,6 +202,7 @@ impl FakeFs {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
Self {
|
Self {
|
||||||
|
executor,
|
||||||
state: futures::lock::Mutex::new(FakeFsState {
|
state: futures::lock::Mutex::new(FakeFsState {
|
||||||
entries,
|
entries,
|
||||||
next_inode: 1,
|
next_inode: 1,
|
||||||
|
@ -330,6 +332,7 @@ impl FakeFs {
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl Fs for FakeFs {
|
impl Fs for FakeFs {
|
||||||
async fn load(&self, path: &Path) -> Result<String> {
|
async fn load(&self, path: &Path) -> Result<String> {
|
||||||
|
self.executor.simulate_random_delay().await;
|
||||||
let state = self.state.lock().await;
|
let state = self.state.lock().await;
|
||||||
let text = state
|
let text = state
|
||||||
.entries
|
.entries
|
||||||
|
@ -340,6 +343,7 @@ impl Fs for FakeFs {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn save(&self, path: &Path, text: &Rope) -> Result<()> {
|
async fn save(&self, path: &Path, text: &Rope) -> Result<()> {
|
||||||
|
self.executor.simulate_random_delay().await;
|
||||||
let mut state = self.state.lock().await;
|
let mut state = self.state.lock().await;
|
||||||
state.validate_path(path)?;
|
state.validate_path(path)?;
|
||||||
if let Some(entry) = state.entries.get_mut(path) {
|
if let Some(entry) = state.entries.get_mut(path) {
|
||||||
|
@ -370,10 +374,12 @@ impl Fs for FakeFs {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn canonicalize(&self, path: &Path) -> Result<PathBuf> {
|
async fn canonicalize(&self, path: &Path) -> Result<PathBuf> {
|
||||||
|
self.executor.simulate_random_delay().await;
|
||||||
Ok(path.to_path_buf())
|
Ok(path.to_path_buf())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn is_file(&self, path: &Path) -> bool {
|
async fn is_file(&self, path: &Path) -> bool {
|
||||||
|
self.executor.simulate_random_delay().await;
|
||||||
let state = self.state.lock().await;
|
let state = self.state.lock().await;
|
||||||
state
|
state
|
||||||
.entries
|
.entries
|
||||||
|
@ -382,6 +388,7 @@ impl Fs for FakeFs {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn metadata(&self, path: &Path) -> Result<Option<Metadata>> {
|
async fn metadata(&self, path: &Path) -> Result<Option<Metadata>> {
|
||||||
|
self.executor.simulate_random_delay().await;
|
||||||
let state = self.state.lock().await;
|
let state = self.state.lock().await;
|
||||||
Ok(state.entries.get(path).map(|entry| entry.metadata.clone()))
|
Ok(state.entries.get(path).map(|entry| entry.metadata.clone()))
|
||||||
}
|
}
|
||||||
|
@ -391,6 +398,7 @@ impl Fs for FakeFs {
|
||||||
abs_path: &Path,
|
abs_path: &Path,
|
||||||
) -> Result<Pin<Box<dyn Send + Stream<Item = Result<PathBuf>>>>> {
|
) -> Result<Pin<Box<dyn Send + Stream<Item = Result<PathBuf>>>>> {
|
||||||
use futures::{future, stream};
|
use futures::{future, stream};
|
||||||
|
self.executor.simulate_random_delay().await;
|
||||||
let state = self.state.lock().await;
|
let state = self.state.lock().await;
|
||||||
let abs_path = abs_path.to_path_buf();
|
let abs_path = abs_path.to_path_buf();
|
||||||
Ok(Box::pin(stream::iter(state.entries.clone()).filter_map(
|
Ok(Box::pin(stream::iter(state.entries.clone()).filter_map(
|
||||||
|
@ -410,6 +418,7 @@ impl Fs for FakeFs {
|
||||||
_: Duration,
|
_: Duration,
|
||||||
) -> Pin<Box<dyn Send + Stream<Item = Vec<fsevent::Event>>>> {
|
) -> Pin<Box<dyn Send + Stream<Item = Vec<fsevent::Event>>>> {
|
||||||
let state = self.state.lock().await;
|
let state = self.state.lock().await;
|
||||||
|
self.executor.simulate_random_delay().await;
|
||||||
let rx = state.events_tx.subscribe();
|
let rx = state.events_tx.subscribe();
|
||||||
let path = path.to_path_buf();
|
let path = path.to_path_buf();
|
||||||
Box::pin(futures::StreamExt::filter(rx, move |events| {
|
Box::pin(futures::StreamExt::filter(rx, move |events| {
|
||||||
|
|
|
@ -2439,7 +2439,7 @@ mod tests {
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_save_file(mut cx: gpui::TestAppContext) {
|
async fn test_save_file(mut cx: gpui::TestAppContext) {
|
||||||
let fs = Arc::new(FakeFs::new());
|
let fs = Arc::new(FakeFs::new(cx.background()));
|
||||||
fs.insert_tree(
|
fs.insert_tree(
|
||||||
"/dir",
|
"/dir",
|
||||||
json!({
|
json!({
|
||||||
|
@ -2477,7 +2477,7 @@ mod tests {
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_save_in_single_file_worktree(mut cx: gpui::TestAppContext) {
|
async fn test_save_in_single_file_worktree(mut cx: gpui::TestAppContext) {
|
||||||
let fs = Arc::new(FakeFs::new());
|
let fs = Arc::new(FakeFs::new(cx.background()));
|
||||||
fs.insert_tree(
|
fs.insert_tree(
|
||||||
"/dir",
|
"/dir",
|
||||||
json!({
|
json!({
|
||||||
|
@ -2664,7 +2664,7 @@ mod tests {
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_buffer_deduping(mut cx: gpui::TestAppContext) {
|
async fn test_buffer_deduping(mut cx: gpui::TestAppContext) {
|
||||||
let fs = Arc::new(FakeFs::new());
|
let fs = Arc::new(FakeFs::new(cx.background()));
|
||||||
fs.insert_tree(
|
fs.insert_tree(
|
||||||
"/the-dir",
|
"/the-dir",
|
||||||
json!({
|
json!({
|
||||||
|
@ -2953,7 +2953,7 @@ mod tests {
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_grouped_diagnostics(mut cx: gpui::TestAppContext) {
|
async fn test_grouped_diagnostics(mut cx: gpui::TestAppContext) {
|
||||||
let fs = Arc::new(FakeFs::new());
|
let fs = Arc::new(FakeFs::new(cx.background()));
|
||||||
fs.insert_tree(
|
fs.insert_tree(
|
||||||
"/the-dir",
|
"/the-dir",
|
||||||
json!({
|
json!({
|
||||||
|
|
|
@ -2432,7 +2432,7 @@ mod tests {
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_traversal(cx: gpui::TestAppContext) {
|
async fn test_traversal(cx: gpui::TestAppContext) {
|
||||||
let fs = FakeFs::new();
|
let fs = FakeFs::new(cx.background());
|
||||||
fs.insert_tree(
|
fs.insert_tree(
|
||||||
"/root",
|
"/root",
|
||||||
json!({
|
json!({
|
||||||
|
|
|
@ -1201,7 +1201,7 @@ mod tests {
|
||||||
async fn test_share_project(mut cx_a: TestAppContext, mut cx_b: TestAppContext) {
|
async fn test_share_project(mut cx_a: TestAppContext, mut cx_b: TestAppContext) {
|
||||||
let (window_b, _) = cx_b.add_window(|_| EmptyView);
|
let (window_b, _) = cx_b.add_window(|_| EmptyView);
|
||||||
let lang_registry = Arc::new(LanguageRegistry::new());
|
let lang_registry = Arc::new(LanguageRegistry::new());
|
||||||
let fs = Arc::new(FakeFs::new());
|
let fs = Arc::new(FakeFs::new(cx_a.background()));
|
||||||
cx_a.foreground().forbid_parking();
|
cx_a.foreground().forbid_parking();
|
||||||
|
|
||||||
// Connect to a server as 2 clients.
|
// Connect to a server as 2 clients.
|
||||||
|
@ -1339,7 +1339,7 @@ mod tests {
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_unshare_project(mut cx_a: TestAppContext, mut cx_b: TestAppContext) {
|
async fn test_unshare_project(mut cx_a: TestAppContext, mut cx_b: TestAppContext) {
|
||||||
let lang_registry = Arc::new(LanguageRegistry::new());
|
let lang_registry = Arc::new(LanguageRegistry::new());
|
||||||
let fs = Arc::new(FakeFs::new());
|
let fs = Arc::new(FakeFs::new(cx_a.background()));
|
||||||
cx_a.foreground().forbid_parking();
|
cx_a.foreground().forbid_parking();
|
||||||
|
|
||||||
// Connect to a server as 2 clients.
|
// Connect to a server as 2 clients.
|
||||||
|
@ -1440,7 +1440,7 @@ mod tests {
|
||||||
mut cx_c: TestAppContext,
|
mut cx_c: TestAppContext,
|
||||||
) {
|
) {
|
||||||
let lang_registry = Arc::new(LanguageRegistry::new());
|
let lang_registry = Arc::new(LanguageRegistry::new());
|
||||||
let fs = Arc::new(FakeFs::new());
|
let fs = Arc::new(FakeFs::new(cx_a.background()));
|
||||||
cx_a.foreground().forbid_parking();
|
cx_a.foreground().forbid_parking();
|
||||||
|
|
||||||
// Connect to a server as 3 clients.
|
// Connect to a server as 3 clients.
|
||||||
|
@ -1623,7 +1623,7 @@ mod tests {
|
||||||
async fn test_buffer_conflict_after_save(mut cx_a: TestAppContext, mut cx_b: TestAppContext) {
|
async fn test_buffer_conflict_after_save(mut cx_a: TestAppContext, mut cx_b: TestAppContext) {
|
||||||
cx_a.foreground().forbid_parking();
|
cx_a.foreground().forbid_parking();
|
||||||
let lang_registry = Arc::new(LanguageRegistry::new());
|
let lang_registry = Arc::new(LanguageRegistry::new());
|
||||||
let fs = Arc::new(FakeFs::new());
|
let fs = Arc::new(FakeFs::new(cx_a.background()));
|
||||||
|
|
||||||
// Connect to a server as 2 clients.
|
// Connect to a server as 2 clients.
|
||||||
let mut server = TestServer::start(cx_a.foreground()).await;
|
let mut server = TestServer::start(cx_a.foreground()).await;
|
||||||
|
@ -1716,7 +1716,7 @@ mod tests {
|
||||||
async fn test_buffer_reloading(mut cx_a: TestAppContext, mut cx_b: TestAppContext) {
|
async fn test_buffer_reloading(mut cx_a: TestAppContext, mut cx_b: TestAppContext) {
|
||||||
cx_a.foreground().forbid_parking();
|
cx_a.foreground().forbid_parking();
|
||||||
let lang_registry = Arc::new(LanguageRegistry::new());
|
let lang_registry = Arc::new(LanguageRegistry::new());
|
||||||
let fs = Arc::new(FakeFs::new());
|
let fs = Arc::new(FakeFs::new(cx_a.background()));
|
||||||
|
|
||||||
// Connect to a server as 2 clients.
|
// Connect to a server as 2 clients.
|
||||||
let mut server = TestServer::start(cx_a.foreground()).await;
|
let mut server = TestServer::start(cx_a.foreground()).await;
|
||||||
|
@ -1801,7 +1801,7 @@ mod tests {
|
||||||
) {
|
) {
|
||||||
cx_a.foreground().forbid_parking();
|
cx_a.foreground().forbid_parking();
|
||||||
let lang_registry = Arc::new(LanguageRegistry::new());
|
let lang_registry = Arc::new(LanguageRegistry::new());
|
||||||
let fs = Arc::new(FakeFs::new());
|
let fs = Arc::new(FakeFs::new(cx_a.background()));
|
||||||
|
|
||||||
// Connect to a server as 2 clients.
|
// Connect to a server as 2 clients.
|
||||||
let mut server = TestServer::start(cx_a.foreground()).await;
|
let mut server = TestServer::start(cx_a.foreground()).await;
|
||||||
|
@ -1881,7 +1881,7 @@ mod tests {
|
||||||
) {
|
) {
|
||||||
cx_a.foreground().forbid_parking();
|
cx_a.foreground().forbid_parking();
|
||||||
let lang_registry = Arc::new(LanguageRegistry::new());
|
let lang_registry = Arc::new(LanguageRegistry::new());
|
||||||
let fs = Arc::new(FakeFs::new());
|
let fs = Arc::new(FakeFs::new(cx_a.background()));
|
||||||
|
|
||||||
// Connect to a server as 2 clients.
|
// Connect to a server as 2 clients.
|
||||||
let mut server = TestServer::start(cx_a.foreground()).await;
|
let mut server = TestServer::start(cx_a.foreground()).await;
|
||||||
|
@ -1956,7 +1956,7 @@ mod tests {
|
||||||
async fn test_peer_disconnection(mut cx_a: TestAppContext, mut cx_b: TestAppContext) {
|
async fn test_peer_disconnection(mut cx_a: TestAppContext, mut cx_b: TestAppContext) {
|
||||||
cx_a.foreground().forbid_parking();
|
cx_a.foreground().forbid_parking();
|
||||||
let lang_registry = Arc::new(LanguageRegistry::new());
|
let lang_registry = Arc::new(LanguageRegistry::new());
|
||||||
let fs = Arc::new(FakeFs::new());
|
let fs = Arc::new(FakeFs::new(cx_a.background()));
|
||||||
|
|
||||||
// Connect to a server as 2 clients.
|
// Connect to a server as 2 clients.
|
||||||
let mut server = TestServer::start(cx_a.foreground()).await;
|
let mut server = TestServer::start(cx_a.foreground()).await;
|
||||||
|
@ -2030,7 +2030,7 @@ mod tests {
|
||||||
) {
|
) {
|
||||||
cx_a.foreground().forbid_parking();
|
cx_a.foreground().forbid_parking();
|
||||||
let mut lang_registry = Arc::new(LanguageRegistry::new());
|
let mut lang_registry = Arc::new(LanguageRegistry::new());
|
||||||
let fs = Arc::new(FakeFs::new());
|
let fs = Arc::new(FakeFs::new(cx_a.background()));
|
||||||
|
|
||||||
// Set up a fake language server.
|
// Set up a fake language server.
|
||||||
let (language_server_config, mut fake_language_server) =
|
let (language_server_config, mut fake_language_server) =
|
||||||
|
@ -2251,7 +2251,7 @@ mod tests {
|
||||||
async fn test_formatting_buffer(mut cx_a: TestAppContext, mut cx_b: TestAppContext) {
|
async fn test_formatting_buffer(mut cx_a: TestAppContext, mut cx_b: TestAppContext) {
|
||||||
cx_a.foreground().forbid_parking();
|
cx_a.foreground().forbid_parking();
|
||||||
let mut lang_registry = Arc::new(LanguageRegistry::new());
|
let mut lang_registry = Arc::new(LanguageRegistry::new());
|
||||||
let fs = Arc::new(FakeFs::new());
|
let fs = Arc::new(FakeFs::new(cx_a.background()));
|
||||||
|
|
||||||
// Set up a fake language server.
|
// Set up a fake language server.
|
||||||
let (language_server_config, mut fake_language_server) =
|
let (language_server_config, mut fake_language_server) =
|
||||||
|
@ -2355,7 +2355,7 @@ mod tests {
|
||||||
async fn test_definition(mut cx_a: TestAppContext, mut cx_b: TestAppContext) {
|
async fn test_definition(mut cx_a: TestAppContext, mut cx_b: TestAppContext) {
|
||||||
cx_a.foreground().forbid_parking();
|
cx_a.foreground().forbid_parking();
|
||||||
let mut lang_registry = Arc::new(LanguageRegistry::new());
|
let mut lang_registry = Arc::new(LanguageRegistry::new());
|
||||||
let fs = Arc::new(FakeFs::new());
|
let fs = Arc::new(FakeFs::new(cx_a.background()));
|
||||||
fs.insert_tree(
|
fs.insert_tree(
|
||||||
"/root-1",
|
"/root-1",
|
||||||
json!({
|
json!({
|
||||||
|
@ -2516,7 +2516,7 @@ mod tests {
|
||||||
) {
|
) {
|
||||||
cx_a.foreground().forbid_parking();
|
cx_a.foreground().forbid_parking();
|
||||||
let mut lang_registry = Arc::new(LanguageRegistry::new());
|
let mut lang_registry = Arc::new(LanguageRegistry::new());
|
||||||
let fs = Arc::new(FakeFs::new());
|
let fs = Arc::new(FakeFs::new(cx_a.background()));
|
||||||
fs.insert_tree(
|
fs.insert_tree(
|
||||||
"/root",
|
"/root",
|
||||||
json!({
|
json!({
|
||||||
|
@ -3042,7 +3042,7 @@ mod tests {
|
||||||
) {
|
) {
|
||||||
cx_a.foreground().forbid_parking();
|
cx_a.foreground().forbid_parking();
|
||||||
let lang_registry = Arc::new(LanguageRegistry::new());
|
let lang_registry = Arc::new(LanguageRegistry::new());
|
||||||
let fs = Arc::new(FakeFs::new());
|
let fs = Arc::new(FakeFs::new(cx_a.background()));
|
||||||
|
|
||||||
// Connect to a server as 3 clients.
|
// Connect to a server as 3 clients.
|
||||||
let mut server = TestServer::start(cx_a.foreground()).await;
|
let mut server = TestServer::start(cx_a.foreground()).await;
|
||||||
|
|
|
@ -490,7 +490,7 @@ pub struct WorkspaceParams {
|
||||||
impl WorkspaceParams {
|
impl WorkspaceParams {
|
||||||
#[cfg(any(test, feature = "test-support"))]
|
#[cfg(any(test, feature = "test-support"))]
|
||||||
pub fn test(cx: &mut MutableAppContext) -> Self {
|
pub fn test(cx: &mut MutableAppContext) -> Self {
|
||||||
let fs = Arc::new(project::FakeFs::new());
|
let fs = Arc::new(project::FakeFs::new(cx.background().clone()));
|
||||||
let languages = Arc::new(LanguageRegistry::new());
|
let languages = Arc::new(LanguageRegistry::new());
|
||||||
let http_client = client::test::FakeHttpClient::new(|_| async move {
|
let http_client = client::test::FakeHttpClient::new(|_| async move {
|
||||||
Ok(client::http::ServerResponse::new(404))
|
Ok(client::http::ServerResponse::new(404))
|
||||||
|
|
|
@ -40,7 +40,7 @@ pub fn test_app_state(cx: &mut MutableAppContext) -> Arc<AppState> {
|
||||||
channel_list: cx.add_model(|cx| ChannelList::new(user_store.clone(), client.clone(), cx)),
|
channel_list: cx.add_model(|cx| ChannelList::new(user_store.clone(), client.clone(), cx)),
|
||||||
client,
|
client,
|
||||||
user_store,
|
user_store,
|
||||||
fs: Arc::new(FakeFs::new()),
|
fs: Arc::new(FakeFs::new(cx.background().clone())),
|
||||||
path_openers: Arc::from(path_openers),
|
path_openers: Arc::from(path_openers),
|
||||||
build_window_options: &build_window_options,
|
build_window_options: &build_window_options,
|
||||||
build_workspace: &build_workspace,
|
build_workspace: &build_workspace,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue