mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-28 21:32:39 +00:00
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
This commit is contained in:
parent
5d17cfab31
commit
d177a1d4e5
6 changed files with 106 additions and 88 deletions
11
Cargo.lock
generated
11
Cargo.lock
generated
|
@ -4189,6 +4189,7 @@ dependencies = [
|
||||||
"serde_json_lenient",
|
"serde_json_lenient",
|
||||||
"settings",
|
"settings",
|
||||||
"task",
|
"task",
|
||||||
|
"theme",
|
||||||
"toml 0.8.19",
|
"toml 0.8.19",
|
||||||
"url",
|
"url",
|
||||||
"util",
|
"util",
|
||||||
|
@ -4203,36 +4204,26 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"assistant_slash_command",
|
"assistant_slash_command",
|
||||||
"async-compression",
|
|
||||||
"async-tar",
|
|
||||||
"client",
|
"client",
|
||||||
"collections",
|
"collections",
|
||||||
"context_servers",
|
"context_servers",
|
||||||
"ctor",
|
|
||||||
"db",
|
"db",
|
||||||
"editor",
|
"editor",
|
||||||
"env_logger 0.11.5",
|
|
||||||
"extension",
|
"extension",
|
||||||
"extension_host",
|
"extension_host",
|
||||||
"fs",
|
"fs",
|
||||||
"futures 0.3.30",
|
|
||||||
"fuzzy",
|
"fuzzy",
|
||||||
"gpui",
|
"gpui",
|
||||||
"http_client",
|
|
||||||
"indexed_docs",
|
"indexed_docs",
|
||||||
"language",
|
"language",
|
||||||
"log",
|
"log",
|
||||||
"lsp",
|
"lsp",
|
||||||
"node_runtime",
|
|
||||||
"num-format",
|
"num-format",
|
||||||
"parking_lot",
|
|
||||||
"picker",
|
"picker",
|
||||||
"project",
|
"project",
|
||||||
"release_channel",
|
"release_channel",
|
||||||
"reqwest_client",
|
|
||||||
"semantic_version",
|
"semantic_version",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
|
||||||
"settings",
|
"settings",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"snippet_provider",
|
"snippet_provider",
|
||||||
|
|
|
@ -58,3 +58,4 @@ language = { workspace = true, features = ["test-support"] }
|
||||||
parking_lot.workspace = true
|
parking_lot.workspace = true
|
||||||
project = { workspace = true, features = ["test-support"] }
|
project = { workspace = true, features = ["test-support"] }
|
||||||
reqwest_client.workspace = true
|
reqwest_client.workspace = true
|
||||||
|
theme = { workspace = true, features = ["test-support"] }
|
||||||
|
|
|
@ -2,6 +2,9 @@ pub mod extension_lsp_adapter;
|
||||||
pub mod extension_settings;
|
pub mod extension_settings;
|
||||||
pub mod wasm_host;
|
pub mod wasm_host;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod extension_store_test;
|
||||||
|
|
||||||
use crate::{extension_lsp_adapter::ExtensionLspAdapter, wasm_host::wit};
|
use crate::{extension_lsp_adapter::ExtensionLspAdapter, wasm_host::wit};
|
||||||
use anyhow::{anyhow, bail, Context as _, Result};
|
use anyhow::{anyhow, bail, Context as _, Result};
|
||||||
use async_compression::futures::bufread::GzipDecoder;
|
use async_compression::futures::bufread::GzipDecoder;
|
||||||
|
|
|
@ -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 async_compression::futures::bufread::GzipEncoder;
|
||||||
use collections::BTreeMap;
|
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 fs::{FakeFs, Fs, RealFs};
|
||||||
use futures::{io::BufReader, AsyncReadExt, StreamExt};
|
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 http_client::{FakeHttpClient, Response};
|
||||||
use indexed_docs::IndexedDocsRegistry;
|
use language::{LanguageMatcher, LanguageRegistry, LanguageServerBinaryStatus, LoadedLanguage};
|
||||||
use language::{LanguageMatcher, LanguageRegistry, LanguageServerBinaryStatus};
|
|
||||||
use lsp::LanguageServerName;
|
use lsp::LanguageServerName;
|
||||||
use node_runtime::NodeRuntime;
|
use node_runtime::NodeRuntime;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
@ -23,7 +20,6 @@ use release_channel::AppVersion;
|
||||||
use reqwest_client::ReqwestClient;
|
use reqwest_client::ReqwestClient;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use settings::{Settings as _, SettingsStore};
|
use settings::{Settings as _, SettingsStore};
|
||||||
use snippet_provider::SnippetRegistry;
|
|
||||||
use std::{
|
use std::{
|
||||||
ffi::OsString,
|
ffi::OsString,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
|
@ -32,6 +28,84 @@ use std::{
|
||||||
use theme::ThemeRegistry;
|
use theme::ThemeRegistry;
|
||||||
use util::test::temp_tree;
|
use util::test::temp_tree;
|
||||||
|
|
||||||
|
use crate::ExtensionRegistrationHooks;
|
||||||
|
|
||||||
|
struct TestExtensionRegistrationHooks {
|
||||||
|
executor: BackgroundExecutor,
|
||||||
|
language_registry: Arc<LanguageRegistry>,
|
||||||
|
theme_registry: Arc<ThemeRegistry>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExtensionRegistrationHooks for TestExtensionRegistrationHooks {
|
||||||
|
fn list_theme_names(&self, path: PathBuf, fs: Arc<dyn Fs>) -> Task<Result<Vec<String>>> {
|
||||||
|
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<dyn fs::Fs>) -> Task<Result<()>> {
|
||||||
|
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<SharedString>) {
|
||||||
|
self.theme_registry.remove_user_themes(&themes);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn register_language(
|
||||||
|
&self,
|
||||||
|
language: language::LanguageName,
|
||||||
|
grammar: Option<Arc<str>>,
|
||||||
|
matcher: language::LanguageMatcher,
|
||||||
|
load: Arc<dyn Fn() -> Result<LoadedLanguage> + '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<str>],
|
||||||
|
) {
|
||||||
|
self.language_registry
|
||||||
|
.remove_languages(&languages_to_remove, &grammars_to_remove);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn register_wasm_grammars(&self, grammars: Vec<(Arc<str>, 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)]
|
#[cfg(test)]
|
||||||
#[ctor::ctor]
|
#[ctor::ctor]
|
||||||
fn init_logger() {
|
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 language_registry = Arc::new(LanguageRegistry::test(cx.executor()));
|
||||||
let theme_registry = Arc::new(ThemeRegistry::new(Box::new(())));
|
let theme_registry = Arc::new(ThemeRegistry::new(Box::new(())));
|
||||||
let slash_command_registry = SlashCommandRegistry::new();
|
let registration_hooks = Arc::new(TestExtensionRegistrationHooks {
|
||||||
let indexed_docs_registry = Arc::new(IndexedDocsRegistry::new(cx.executor()));
|
executor: cx.executor(),
|
||||||
let snippet_registry = Arc::new(SnippetRegistry::new());
|
language_registry: language_registry.clone(),
|
||||||
let context_server_factory_registry = cx.new_model(|_| ContextServerFactoryRegistry::new());
|
theme_registry: theme_registry.clone(),
|
||||||
|
});
|
||||||
let node_runtime = NodeRuntime::unavailable();
|
let node_runtime = NodeRuntime::unavailable();
|
||||||
|
|
||||||
let store = cx.new_model(|cx| {
|
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(
|
ExtensionStore::new(
|
||||||
PathBuf::from("/the-extension-dir"),
|
PathBuf::from("/the-extension-dir"),
|
||||||
None,
|
None,
|
||||||
extension_registration_hooks,
|
registration_hooks.clone(),
|
||||||
fs.clone(),
|
fs.clone(),
|
||||||
http_client.clone(),
|
http_client.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.
|
// Create new extension store, as if Zed were restarting.
|
||||||
drop(store);
|
drop(store);
|
||||||
let store = cx.new_model(|cx| {
|
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(
|
ExtensionStore::new(
|
||||||
PathBuf::from("/the-extension-dir"),
|
PathBuf::from("/the-extension-dir"),
|
||||||
None,
|
None,
|
||||||
extension_api,
|
registration_hooks,
|
||||||
fs.clone(),
|
fs.clone(),
|
||||||
http_client.clone(),
|
http_client.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 language_registry = project.read_with(cx, |project, _cx| project.languages().clone());
|
||||||
let theme_registry = Arc::new(ThemeRegistry::new(Box::new(())));
|
let theme_registry = Arc::new(ThemeRegistry::new(Box::new(())));
|
||||||
let slash_command_registry = SlashCommandRegistry::new();
|
let registration_hooks = Arc::new(TestExtensionRegistrationHooks {
|
||||||
let indexed_docs_registry = Arc::new(IndexedDocsRegistry::new(cx.executor()));
|
executor: cx.executor(),
|
||||||
let snippet_registry = Arc::new(SnippetRegistry::new());
|
language_registry: language_registry.clone(),
|
||||||
let context_server_factory_registry = cx.new_model(|_| ContextServerFactoryRegistry::new());
|
theme_registry: theme_registry.clone(),
|
||||||
|
});
|
||||||
let node_runtime = NodeRuntime::unavailable();
|
let node_runtime = NodeRuntime::unavailable();
|
||||||
|
|
||||||
let mut status_updates = language_registry.language_server_binary_statuses();
|
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"));
|
Arc::new(ReqwestClient::user_agent(&user_agent).expect("Could not create HTTP client"));
|
||||||
|
|
||||||
let extension_store = cx.new_model(|cx| {
|
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(
|
ExtensionStore::new(
|
||||||
extensions_dir.clone(),
|
extensions_dir.clone(),
|
||||||
Some(cache_dir),
|
Some(cache_dir),
|
||||||
extension_api,
|
registration_hooks,
|
||||||
fs.clone(),
|
fs.clone(),
|
||||||
extension_client.clone(),
|
extension_client.clone(),
|
||||||
builder_client,
|
builder_client,
|
||||||
|
@ -626,7 +673,7 @@ async fn test_extension_store_with_test_extension(cx: &mut TestAppContext) {
|
||||||
let executor = cx.executor();
|
let executor = cx.executor();
|
||||||
let _task = cx.executor().spawn(async move {
|
let _task = cx.executor().spawn(async move {
|
||||||
while let Some(event) = events.next().await {
|
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);
|
executor.advance_clock(RELOAD_DEBOUNCE_DURATION);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -11,9 +11,6 @@ workspace = true
|
||||||
[lib]
|
[lib]
|
||||||
path = "src/extensions_ui.rs"
|
path = "src/extensions_ui.rs"
|
||||||
|
|
||||||
[features]
|
|
||||||
test-support = []
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
assistant_slash_command.workspace = true
|
assistant_slash_command.workspace = true
|
||||||
|
@ -25,7 +22,6 @@ editor.workspace = true
|
||||||
extension.workspace = true
|
extension.workspace = true
|
||||||
extension_host.workspace = true
|
extension_host.workspace = true
|
||||||
fs.workspace = true
|
fs.workspace = true
|
||||||
futures.workspace = true
|
|
||||||
fuzzy.workspace = true
|
fuzzy.workspace = true
|
||||||
gpui.workspace = true
|
gpui.workspace = true
|
||||||
indexed_docs.workspace = true
|
indexed_docs.workspace = true
|
||||||
|
@ -50,21 +46,4 @@ wasmtime-wasi.workspace = true
|
||||||
workspace.workspace = true
|
workspace.workspace = true
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
async-compression.workspace = true
|
|
||||||
async-tar.workspace = true
|
|
||||||
ctor.workspace = true
|
|
||||||
editor = { workspace = true, features = ["test-support"] }
|
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"] }
|
|
||||||
|
|
|
@ -3,9 +3,6 @@ mod extension_registration_hooks;
|
||||||
mod extension_suggest;
|
mod extension_suggest;
|
||||||
mod extension_version_selector;
|
mod extension_version_selector;
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod extension_store_test;
|
|
||||||
|
|
||||||
pub use extension_registration_hooks::ConcreteExtensionRegistrationHooks;
|
pub use extension_registration_hooks::ConcreteExtensionRegistrationHooks;
|
||||||
|
|
||||||
use std::ops::DerefMut;
|
use std::ops::DerefMut;
|
||||||
|
|
Loading…
Reference in a new issue