Merge pull request #1304 from zed-industries/deploy-panic

Fixed working directory issues, added tests.
This commit is contained in:
Mikayla Maki 2022-07-07 12:14:57 -07:00 committed by GitHub
commit 1cfe8688ca
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 119 additions and 8 deletions

2
Cargo.lock generated
View file

@ -4878,6 +4878,8 @@ name = "terminal"
version = "0.1.0"
dependencies = [
"alacritty_terminal",
"client",
"dirs 4.0.0",
"editor",
"futures",
"gpui",

View file

@ -151,6 +151,7 @@ pub struct AsyncAppContext(Rc<RefCell<MutableAppContext>>);
pub struct TestAppContext {
cx: Rc<RefCell<MutableAppContext>>,
foreground_platform: Rc<platform::test::ForegroundPlatform>,
condition_duration: Option<Duration>,
}
impl App {
@ -337,6 +338,7 @@ impl TestAppContext {
let cx = TestAppContext {
cx: Rc::new(RefCell::new(cx)),
foreground_platform,
condition_duration: None,
};
cx.cx.borrow_mut().weak_self = Some(Rc::downgrade(&cx.cx));
cx
@ -612,6 +614,19 @@ impl TestAppContext {
test_window
})
}
pub fn set_condition_duration(&mut self, duration: Duration) {
self.condition_duration = Some(duration);
}
pub fn condition_duration(&self) -> Duration {
self.condition_duration.unwrap_or_else(|| {
if std::env::var("CI").is_ok() {
Duration::from_secs(2)
} else {
Duration::from_millis(500)
}
})
}
}
impl AsyncAppContext {
@ -4424,6 +4439,7 @@ impl<T: View> ViewHandle<T> {
use postage::prelude::{Sink as _, Stream as _};
let (tx, mut rx) = postage::mpsc::channel(1024);
let timeout_duration = cx.condition_duration();
let mut cx = cx.cx.borrow_mut();
let subscriptions = self.update(&mut *cx, |_, cx| {
@ -4445,14 +4461,9 @@ impl<T: View> ViewHandle<T> {
let cx = cx.weak_self.as_ref().unwrap().upgrade().unwrap();
let handle = self.downgrade();
let duration = if std::env::var("CI").is_ok() {
Duration::from_secs(2)
} else {
Duration::from_millis(500)
};
async move {
crate::util::timeout(duration, async move {
crate::util::timeout(timeout_duration, async move {
loop {
{
let cx = cx.borrow();

View file

@ -21,7 +21,11 @@ mio-extras = "2.0.6"
futures = "0.3"
ordered-float = "2.1.1"
itertools = "0.10"
dirs = "4.0.0"
[dev-dependencies]
gpui = { path = "../gpui", features = ["test-support"] }
client = { path = "../client", features = ["test-support"]}
project = { path = "../project", features = ["test-support"]}

View file

@ -9,6 +9,7 @@ use alacritty_terminal::{
Term,
};
use dirs::home_dir;
use futures::{
channel::mpsc::{unbounded, UnboundedSender},
StreamExt,
@ -17,7 +18,7 @@ use gpui::{
actions, color::Color, elements::*, impl_internal_actions, platform::CursorStyle,
ClipboardItem, Entity, MutableAppContext, View, ViewContext,
};
use project::{Project, ProjectPath};
use project::{LocalWorktree, Project, ProjectPath};
use settings::Settings;
use smallvec::SmallVec;
use std::{collections::HashMap, path::PathBuf, sync::Arc};
@ -268,11 +269,12 @@ impl Terminal {
///Create a new Terminal in the current working directory or the user's home directory
fn deploy(workspace: &mut Workspace, _: &Deploy, cx: &mut ViewContext<Workspace>) {
let project = workspace.project().read(cx);
let abs_path = project
.active_entry()
.and_then(|entry_id| project.worktree_for_entry(entry_id, cx))
.and_then(|worktree_handle| worktree_handle.read(cx).as_local())
.map(|wt| wt.abs_path().to_path_buf());
.and_then(get_working_directory);
workspace.add_item(Box::new(cx.add_view(|cx| Terminal::new(cx, abs_path))), cx);
}
@ -477,18 +479,29 @@ fn to_alac_rgb(color: Color) -> AlacRgb {
}
}
fn get_working_directory(wt: &LocalWorktree) -> Option<PathBuf> {
Some(wt.abs_path().to_path_buf())
.filter(|path| path.is_dir())
.or_else(|| home_dir())
}
#[cfg(test)]
mod tests {
use std::{path::Path, sync::atomic::AtomicUsize, time::Duration};
use super::*;
use alacritty_terminal::{grid::GridIterator, term::cell::Cell};
use gpui::TestAppContext;
use itertools::Itertools;
use project::{FakeFs, Fs, RealFs, RemoveOptions, Worktree};
///Basic integration test, can we get the terminal to show up, execute a command,
//and produce noticable output?
#[gpui::test]
async fn test_terminal(cx: &mut TestAppContext) {
let terminal = cx.add_view(Default::default(), |cx| Terminal::new(cx, None));
cx.set_condition_duration(Duration::from_secs(2));
terminal.update(cx, |terminal, cx| {
terminal.write_to_pty(&Input(("expr 3 + 4".to_string()).to_string()), cx);
@ -512,4 +525,85 @@ mod tests {
.collect::<Vec<String>>()
.join("\n")
}
#[gpui::test]
async fn single_file_worktree(cx: &mut TestAppContext) {
let mut async_cx = cx.to_async();
let http_client = client::test::FakeHttpClient::with_404_response();
let client = client::Client::new(http_client.clone());
let fake_fs = FakeFs::new(cx.background().clone());
let path = Path::new("/file/");
fake_fs.insert_file(path, "a".to_string()).await;
let worktree_handle = Worktree::local(
client,
path,
true,
fake_fs,
Arc::new(AtomicUsize::new(0)),
&mut async_cx,
)
.await
.ok()
.unwrap();
async_cx.update(|cx| {
let wt = worktree_handle.read(cx).as_local().unwrap();
let wd = get_working_directory(wt);
assert!(wd.is_some());
let path = wd.unwrap();
//This should be the system's working directory, so querying the real file system is probably ok.
assert!(path.is_dir());
assert_eq!(path, home_dir().unwrap());
});
}
#[gpui::test]
async fn test_worktree_directory(cx: &mut TestAppContext) {
let mut async_cx = cx.to_async();
let http_client = client::test::FakeHttpClient::with_404_response();
let client = client::Client::new(http_client.clone());
let fs = RealFs;
let mut test_wd = home_dir().unwrap();
test_wd.push("dir");
fs.create_dir(test_wd.as_path())
.await
.expect("File could not be created");
let worktree_handle = Worktree::local(
client,
test_wd.clone(),
true,
Arc::new(RealFs),
Arc::new(AtomicUsize::new(0)),
&mut async_cx,
)
.await
.ok()
.unwrap();
async_cx.update(|cx| {
let wt = worktree_handle.read(cx).as_local().unwrap();
let wd = get_working_directory(wt);
assert!(wd.is_some());
let path = wd.unwrap();
assert!(path.is_dir());
assert_eq!(path, test_wd);
});
//Clean up after ourselves.
fs.remove_dir(
test_wd.as_path(),
RemoveOptions {
recursive: false,
ignore_if_not_exists: true,
},
)
.await
.ok()
.expect("Could not remove test directory");
}
}