From d177a1d4e5217d7335f3494f7a44be2b7b0c28af Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Thu, 14 Nov 2024 12:09:41 -0500 Subject: [PATCH] Move `ExtensionStore` tests back to `extension_host` (#20682) This PR moves the tests for the `ExtensionStore` back into the `extension_host` crate. We now have a separate `TestExtensionRegistrationHooks` to use in the test that implements the minimal required functionality needed for the tests. This means that we can depend on the `theme` crate only in the tests. Release Notes: - N/A --- Cargo.lock | 11 +- crates/extension_host/Cargo.toml | 1 + crates/extension_host/src/extension_host.rs | 3 + .../src/extension_store_test.rs | 155 ++++++++++++------ crates/extensions_ui/Cargo.toml | 21 --- crates/extensions_ui/src/extensions_ui.rs | 3 - 6 files changed, 106 insertions(+), 88 deletions(-) rename crates/{extensions_ui => extension_host}/src/extension_store_test.rs (89%) diff --git a/Cargo.lock b/Cargo.lock index fed6b6e2d4..073f7b43b9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4189,6 +4189,7 @@ dependencies = [ "serde_json_lenient", "settings", "task", + "theme", "toml 0.8.19", "url", "util", @@ -4203,36 +4204,26 @@ version = "0.1.0" dependencies = [ "anyhow", "assistant_slash_command", - "async-compression", - "async-tar", "client", "collections", "context_servers", - "ctor", "db", "editor", - "env_logger 0.11.5", "extension", "extension_host", "fs", - "futures 0.3.30", "fuzzy", "gpui", - "http_client", "indexed_docs", "language", "log", "lsp", - "node_runtime", "num-format", - "parking_lot", "picker", "project", "release_channel", - "reqwest_client", "semantic_version", "serde", - "serde_json", "settings", "smallvec", "snippet_provider", diff --git a/crates/extension_host/Cargo.toml b/crates/extension_host/Cargo.toml index b5e0047e7d..856466e1a1 100644 --- a/crates/extension_host/Cargo.toml +++ b/crates/extension_host/Cargo.toml @@ -58,3 +58,4 @@ language = { workspace = true, features = ["test-support"] } parking_lot.workspace = true project = { workspace = true, features = ["test-support"] } reqwest_client.workspace = true +theme = { workspace = true, features = ["test-support"] } diff --git a/crates/extension_host/src/extension_host.rs b/crates/extension_host/src/extension_host.rs index 7537734eed..db292ac6c7 100644 --- a/crates/extension_host/src/extension_host.rs +++ b/crates/extension_host/src/extension_host.rs @@ -2,6 +2,9 @@ pub mod extension_lsp_adapter; pub mod extension_settings; pub mod wasm_host; +#[cfg(test)] +mod extension_store_test; + use crate::{extension_lsp_adapter::ExtensionLspAdapter, wasm_host::wit}; use anyhow::{anyhow, bail, Context as _, Result}; use async_compression::futures::bufread::GzipDecoder; diff --git a/crates/extensions_ui/src/extension_store_test.rs b/crates/extension_host/src/extension_store_test.rs similarity index 89% rename from crates/extensions_ui/src/extension_store_test.rs rename to crates/extension_host/src/extension_store_test.rs index 90b1f7ebc7..23004e9d7f 100644 --- a/crates/extensions_ui/src/extension_store_test.rs +++ b/crates/extension_host/src/extension_store_test.rs @@ -1,20 +1,17 @@ -use assistant_slash_command::SlashCommandRegistry; +use crate::extension_lsp_adapter::ExtensionLspAdapter; +use crate::{ + Event, ExtensionIndex, ExtensionIndexEntry, ExtensionIndexLanguageEntry, + ExtensionIndexThemeEntry, ExtensionManifest, ExtensionSettings, ExtensionStore, + GrammarManifestEntry, SchemaVersion, RELOAD_DEBOUNCE_DURATION, +}; +use anyhow::Result; use async_compression::futures::bufread::GzipEncoder; use collections::BTreeMap; -use context_servers::ContextServerFactoryRegistry; -use extension_host::ExtensionSettings; -use extension_host::SchemaVersion; -use extension_host::{ - Event, ExtensionIndex, ExtensionIndexEntry, ExtensionIndexLanguageEntry, - ExtensionIndexThemeEntry, ExtensionManifest, ExtensionStore, GrammarManifestEntry, - RELOAD_DEBOUNCE_DURATION, -}; use fs::{FakeFs, Fs, RealFs}; use futures::{io::BufReader, AsyncReadExt, StreamExt}; -use gpui::{Context, SemanticVersion, TestAppContext}; +use gpui::{BackgroundExecutor, Context, SemanticVersion, SharedString, Task, TestAppContext}; use http_client::{FakeHttpClient, Response}; -use indexed_docs::IndexedDocsRegistry; -use language::{LanguageMatcher, LanguageRegistry, LanguageServerBinaryStatus}; +use language::{LanguageMatcher, LanguageRegistry, LanguageServerBinaryStatus, LoadedLanguage}; use lsp::LanguageServerName; use node_runtime::NodeRuntime; use parking_lot::Mutex; @@ -23,7 +20,6 @@ use release_channel::AppVersion; use reqwest_client::ReqwestClient; use serde_json::json; use settings::{Settings as _, SettingsStore}; -use snippet_provider::SnippetRegistry; use std::{ ffi::OsString, path::{Path, PathBuf}, @@ -32,6 +28,84 @@ use std::{ use theme::ThemeRegistry; use util::test::temp_tree; +use crate::ExtensionRegistrationHooks; + +struct TestExtensionRegistrationHooks { + executor: BackgroundExecutor, + language_registry: Arc, + theme_registry: Arc, +} + +impl ExtensionRegistrationHooks for TestExtensionRegistrationHooks { + fn list_theme_names(&self, path: PathBuf, fs: Arc) -> Task>> { + self.executor.spawn(async move { + let themes = theme::read_user_theme(&path, fs).await?; + Ok(themes.themes.into_iter().map(|theme| theme.name).collect()) + }) + } + + fn load_user_theme(&self, theme_path: PathBuf, fs: Arc) -> Task> { + let theme_registry = self.theme_registry.clone(); + self.executor + .spawn(async move { theme_registry.load_user_theme(&theme_path, fs).await }) + } + + fn remove_user_themes(&self, themes: Vec) { + self.theme_registry.remove_user_themes(&themes); + } + + fn register_language( + &self, + language: language::LanguageName, + grammar: Option>, + matcher: language::LanguageMatcher, + load: Arc Result + 'static + Send + Sync>, + ) { + self.language_registry + .register_language(language, grammar, matcher, load) + } + + fn remove_languages( + &self, + languages_to_remove: &[language::LanguageName], + grammars_to_remove: &[Arc], + ) { + self.language_registry + .remove_languages(&languages_to_remove, &grammars_to_remove); + } + + fn register_wasm_grammars(&self, grammars: Vec<(Arc, PathBuf)>) { + self.language_registry.register_wasm_grammars(grammars) + } + + fn register_lsp_adapter( + &self, + language_name: language::LanguageName, + adapter: ExtensionLspAdapter, + ) { + self.language_registry + .register_lsp_adapter(language_name, Arc::new(adapter)); + } + + fn update_lsp_status( + &self, + server_name: lsp::LanguageServerName, + status: LanguageServerBinaryStatus, + ) { + self.language_registry + .update_lsp_status(server_name, status); + } + + fn remove_lsp_adapter( + &self, + language_name: &language::LanguageName, + server_name: &lsp::LanguageServerName, + ) { + self.language_registry + .remove_lsp_adapter(language_name, server_name); + } +} + #[cfg(test)] #[ctor::ctor] fn init_logger() { @@ -265,27 +339,18 @@ async fn test_extension_store(cx: &mut TestAppContext) { let language_registry = Arc::new(LanguageRegistry::test(cx.executor())); let theme_registry = Arc::new(ThemeRegistry::new(Box::new(()))); - let slash_command_registry = SlashCommandRegistry::new(); - let indexed_docs_registry = Arc::new(IndexedDocsRegistry::new(cx.executor())); - let snippet_registry = Arc::new(SnippetRegistry::new()); - let context_server_factory_registry = cx.new_model(|_| ContextServerFactoryRegistry::new()); + let registration_hooks = Arc::new(TestExtensionRegistrationHooks { + executor: cx.executor(), + language_registry: language_registry.clone(), + theme_registry: theme_registry.clone(), + }); let node_runtime = NodeRuntime::unavailable(); let store = cx.new_model(|cx| { - let extension_registration_hooks = crate::ConcreteExtensionRegistrationHooks::new( - theme_registry.clone(), - slash_command_registry.clone(), - indexed_docs_registry.clone(), - snippet_registry.clone(), - language_registry.clone(), - context_server_factory_registry.clone(), - cx, - ); - ExtensionStore::new( PathBuf::from("/the-extension-dir"), None, - extension_registration_hooks, + registration_hooks.clone(), fs.clone(), http_client.clone(), http_client.clone(), @@ -407,20 +472,10 @@ async fn test_extension_store(cx: &mut TestAppContext) { // Create new extension store, as if Zed were restarting. drop(store); let store = cx.new_model(|cx| { - let extension_api = crate::ConcreteExtensionRegistrationHooks::new( - theme_registry.clone(), - slash_command_registry, - indexed_docs_registry, - snippet_registry, - language_registry.clone(), - context_server_factory_registry.clone(), - cx, - ); - ExtensionStore::new( PathBuf::from("/the-extension-dir"), None, - extension_api, + registration_hooks, fs.clone(), http_client.clone(), http_client.clone(), @@ -505,10 +560,11 @@ async fn test_extension_store_with_test_extension(cx: &mut TestAppContext) { let language_registry = project.read_with(cx, |project, _cx| project.languages().clone()); let theme_registry = Arc::new(ThemeRegistry::new(Box::new(()))); - let slash_command_registry = SlashCommandRegistry::new(); - let indexed_docs_registry = Arc::new(IndexedDocsRegistry::new(cx.executor())); - let snippet_registry = Arc::new(SnippetRegistry::new()); - let context_server_factory_registry = cx.new_model(|_| ContextServerFactoryRegistry::new()); + let registration_hooks = Arc::new(TestExtensionRegistrationHooks { + executor: cx.executor(), + language_registry: language_registry.clone(), + theme_registry: theme_registry.clone(), + }); let node_runtime = NodeRuntime::unavailable(); let mut status_updates = language_registry.language_server_binary_statuses(); @@ -599,19 +655,10 @@ async fn test_extension_store_with_test_extension(cx: &mut TestAppContext) { Arc::new(ReqwestClient::user_agent(&user_agent).expect("Could not create HTTP client")); let extension_store = cx.new_model(|cx| { - let extension_api = crate::ConcreteExtensionRegistrationHooks::new( - theme_registry.clone(), - slash_command_registry, - indexed_docs_registry, - snippet_registry, - language_registry.clone(), - context_server_factory_registry.clone(), - cx, - ); ExtensionStore::new( extensions_dir.clone(), Some(cache_dir), - extension_api, + registration_hooks, fs.clone(), extension_client.clone(), builder_client, @@ -626,7 +673,7 @@ async fn test_extension_store_with_test_extension(cx: &mut TestAppContext) { let executor = cx.executor(); let _task = cx.executor().spawn(async move { while let Some(event) = events.next().await { - if let extension_host::Event::StartedReloading = event { + if let Event::StartedReloading = event { executor.advance_clock(RELOAD_DEBOUNCE_DURATION); } } diff --git a/crates/extensions_ui/Cargo.toml b/crates/extensions_ui/Cargo.toml index 458925e87e..9709aa7a2b 100644 --- a/crates/extensions_ui/Cargo.toml +++ b/crates/extensions_ui/Cargo.toml @@ -11,9 +11,6 @@ workspace = true [lib] path = "src/extensions_ui.rs" -[features] -test-support = [] - [dependencies] anyhow.workspace = true assistant_slash_command.workspace = true @@ -25,7 +22,6 @@ editor.workspace = true extension.workspace = true extension_host.workspace = true fs.workspace = true -futures.workspace = true fuzzy.workspace = true gpui.workspace = true indexed_docs.workspace = true @@ -50,21 +46,4 @@ wasmtime-wasi.workspace = true workspace.workspace = true [dev-dependencies] -async-compression.workspace = true -async-tar.workspace = true -ctor.workspace = true editor = { workspace = true, features = ["test-support"] } -env_logger.workspace = true -extension_host = {workspace = true, features = ["test-support"] } -fs = { workspace = true, features = ["test-support"] } -gpui = { workspace = true, features = ["test-support"] } -http_client.workspace = true -indexed_docs.workspace = true -language = { workspace = true, features = ["test-support"] } -lsp.workspace = true -node_runtime.workspace = true -parking_lot.workspace = true -project = { workspace = true, features = ["test-support"] } -reqwest_client.workspace = true -serde_json.workspace = true -workspace = { workspace = true, features = ["test-support"] } diff --git a/crates/extensions_ui/src/extensions_ui.rs b/crates/extensions_ui/src/extensions_ui.rs index d91e49533f..c2ef9cf9e6 100644 --- a/crates/extensions_ui/src/extensions_ui.rs +++ b/crates/extensions_ui/src/extensions_ui.rs @@ -3,9 +3,6 @@ mod extension_registration_hooks; mod extension_suggest; mod extension_version_selector; -#[cfg(test)] -mod extension_store_test; - pub use extension_registration_hooks::ConcreteExtensionRegistrationHooks; use std::ops::DerefMut;