mirror of
https://github.com/SilasMarvin/lsp-ai.git
synced 2024-09-11 12:25:48 +03:00
Added some more tests
This commit is contained in:
parent
11e8cf819e
commit
335188d77e
@ -371,7 +371,7 @@ impl Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This makes testing much easier.
|
// For teesting use only
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
impl Config {
|
impl Config {
|
||||||
pub fn default_with_file_store_without_models() -> Self {
|
pub fn default_with_file_store_without_models() -> Self {
|
||||||
|
@ -126,7 +126,7 @@ impl FileStore {
|
|||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
// This means it has been opened before
|
// This means it has been opened before
|
||||||
let insert_uri = format!("file://{path}");
|
let insert_uri = format!("file:///{path}");
|
||||||
if self.file_map.lock().contains_key(&insert_uri) {
|
if self.file_map.lock().contains_key(&insert_uri) {
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
@ -453,6 +453,42 @@ impl MemoryBackend for FileStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For teesting use only
|
||||||
|
#[cfg(test)]
|
||||||
|
impl FileStore {
|
||||||
|
pub fn default_with_filler_file() -> anyhow::Result<Self> {
|
||||||
|
let config = Config::default_with_file_store_without_models();
|
||||||
|
let file_store_config = if let config::ValidMemoryBackend::FileStore(file_store_config) =
|
||||||
|
config.config.memory.clone()
|
||||||
|
{
|
||||||
|
file_store_config
|
||||||
|
} else {
|
||||||
|
anyhow::bail!("requires a file_store_config")
|
||||||
|
};
|
||||||
|
let f = FileStore::new(file_store_config, config)?;
|
||||||
|
|
||||||
|
let uri = "file:///filler.py";
|
||||||
|
let text = r#"# Multiplies two numbers
|
||||||
|
def multiply_two_numbers(x, y):
|
||||||
|
return
|
||||||
|
|
||||||
|
# A singular test
|
||||||
|
assert multiply_two_numbers(2, 3) == 6
|
||||||
|
"#;
|
||||||
|
let params = lsp_types::DidOpenTextDocumentParams {
|
||||||
|
text_document: lsp_types::TextDocumentItem {
|
||||||
|
uri: reqwest::Url::parse(uri).unwrap(),
|
||||||
|
language_id: "filler".to_string(),
|
||||||
|
version: 0,
|
||||||
|
text: text.to_string(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
f.opened_text_document(params)?;
|
||||||
|
|
||||||
|
Ok(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -476,7 +512,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn generate_filler_text_document(uri: Option<&str>, text: Option<&str>) -> TextDocumentItem {
|
fn generate_filler_text_document(uri: Option<&str>, text: Option<&str>) -> TextDocumentItem {
|
||||||
let uri = uri.unwrap_or("file://filler/");
|
let uri = uri.unwrap_or("file:///filler/");
|
||||||
let text = text.unwrap_or("Here is the document body");
|
let text = text.unwrap_or("Here is the document body");
|
||||||
TextDocumentItem {
|
TextDocumentItem {
|
||||||
uri: reqwest::Url::parse(uri).unwrap(),
|
uri: reqwest::Url::parse(uri).unwrap(),
|
||||||
@ -496,7 +532,7 @@ mod tests {
|
|||||||
let file = file_store
|
let file = file_store
|
||||||
.file_map
|
.file_map
|
||||||
.lock()
|
.lock()
|
||||||
.get("file://filler/")
|
.get("file:///filler/")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.clone();
|
.clone();
|
||||||
assert_eq!(file.rope.to_string(), "Here is the document body");
|
assert_eq!(file.rope.to_string(), "Here is the document body");
|
||||||
@ -513,8 +549,8 @@ mod tests {
|
|||||||
|
|
||||||
let params = RenameFilesParams {
|
let params = RenameFilesParams {
|
||||||
files: vec![FileRename {
|
files: vec![FileRename {
|
||||||
old_uri: "file://filler/".to_string(),
|
old_uri: "file:///filler/".to_string(),
|
||||||
new_uri: "file://filler2/".to_string(),
|
new_uri: "file:///filler2/".to_string(),
|
||||||
}],
|
}],
|
||||||
};
|
};
|
||||||
file_store.renamed_files(params)?;
|
file_store.renamed_files(params)?;
|
||||||
@ -522,7 +558,7 @@ mod tests {
|
|||||||
let file = file_store
|
let file = file_store
|
||||||
.file_map
|
.file_map
|
||||||
.lock()
|
.lock()
|
||||||
.get("file://filler2/")
|
.get("file:///filler2/")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.clone();
|
.clone();
|
||||||
assert_eq!(file.rope.to_string(), "Here is the document body");
|
assert_eq!(file.rope.to_string(), "Here is the document body");
|
||||||
@ -563,7 +599,7 @@ mod tests {
|
|||||||
let file = file_store
|
let file = file_store
|
||||||
.file_map
|
.file_map
|
||||||
.lock()
|
.lock()
|
||||||
.get("file://filler/")
|
.get("file:///filler/")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.clone();
|
.clone();
|
||||||
assert_eq!(file.rope.to_string(), "Hae is the document body");
|
assert_eq!(file.rope.to_string(), "Hae is the document body");
|
||||||
@ -583,7 +619,7 @@ mod tests {
|
|||||||
let file = file_store
|
let file = file_store
|
||||||
.file_map
|
.file_map
|
||||||
.lock()
|
.lock()
|
||||||
.get("file://filler/")
|
.get("file:///filler/")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.clone();
|
.clone();
|
||||||
assert_eq!(file.rope.to_string(), "abc");
|
assert_eq!(file.rope.to_string(), "abc");
|
||||||
@ -693,7 +729,7 @@ The end with a trailing new line
|
|||||||
|
|
||||||
// Test multi-file
|
// Test multi-file
|
||||||
let text_document2 = generate_filler_text_document(
|
let text_document2 = generate_filler_text_document(
|
||||||
Some("file://filler2"),
|
Some("file:///filler2"),
|
||||||
Some(
|
Some(
|
||||||
r#"Document Top2
|
r#"Document Top2
|
||||||
Here is a more complicated document
|
Here is a more complicated document
|
||||||
@ -781,7 +817,7 @@ The end with a trailing new line
|
|||||||
let params = AdditionalFileStoreParams { build_tree: true };
|
let params = AdditionalFileStoreParams { build_tree: true };
|
||||||
let file_store = FileStore::new_with_params(file_store_config, config, params)?;
|
let file_store = FileStore::new_with_params(file_store_config, config, params)?;
|
||||||
|
|
||||||
let uri = "file://filler/test.rs";
|
let uri = "file:///filler/test.rs";
|
||||||
let text = r#"#[derive(Debug)]
|
let text = r#"#[derive(Debug)]
|
||||||
struct Rectangle {
|
struct Rectangle {
|
||||||
width: u32,
|
width: u32,
|
||||||
|
@ -69,8 +69,7 @@ async fn do_build_prompt(
|
|||||||
params
|
params
|
||||||
.tx
|
.tx
|
||||||
.send(prompt)
|
.send(prompt)
|
||||||
.map_err(|_| anyhow::anyhow!("sending on channel failed"))?;
|
.map_err(|_| anyhow::anyhow!("sending on channel failed"))
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_task(
|
fn do_task(
|
||||||
|
@ -173,7 +173,7 @@ pub fn run(
|
|||||||
connection,
|
connection,
|
||||||
config,
|
config,
|
||||||
) {
|
) {
|
||||||
error!("error in transformer worker: {e}")
|
error!("error in transformer worker: {e:?}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,7 +256,7 @@ async fn dispatch_request(
|
|||||||
{
|
{
|
||||||
Ok(response) => response,
|
Ok(response) => response,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("generating response: {e}");
|
error!("generating response: {e:?}");
|
||||||
Response {
|
Response {
|
||||||
id: request.get_id(),
|
id: request.get_id(),
|
||||||
result: None,
|
result: None,
|
||||||
@ -266,7 +266,7 @@ async fn dispatch_request(
|
|||||||
};
|
};
|
||||||
|
|
||||||
if let Err(e) = connection.sender.send(Message::Response(response)) {
|
if let Err(e) = connection.sender.send(Message::Response(response)) {
|
||||||
error!("sending response: {e}");
|
error!("sending response: {e:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -412,7 +412,103 @@ async fn do_generate(
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::memory_backends::{ContextAndCodePrompt, FIMPrompt};
|
use crate::memory_backends::{
|
||||||
|
file_store::FileStore, ContextAndCodePrompt, FIMPrompt, MemoryBackend,
|
||||||
|
};
|
||||||
|
use serde_json::json;
|
||||||
|
use std::{sync::mpsc, thread};
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_do_completion() -> anyhow::Result<()> {
|
||||||
|
let (memory_tx, memory_rx) = mpsc::channel();
|
||||||
|
let memory_backend: Box<dyn MemoryBackend + Send + Sync> =
|
||||||
|
Box::new(FileStore::default_with_filler_file()?);
|
||||||
|
thread::spawn(move || memory_worker::run(memory_backend, memory_rx));
|
||||||
|
|
||||||
|
let transformer_backend: Box<dyn TransformerBackend + Send + Sync> =
|
||||||
|
config::ValidModel::Ollama(serde_json::from_value(
|
||||||
|
json!({"model": "deepseek-coder:1.3b-base"}),
|
||||||
|
)?)
|
||||||
|
.try_into()?;
|
||||||
|
let completion_request = CompletionRequest::new(
|
||||||
|
serde_json::from_value(json!(0))?,
|
||||||
|
serde_json::from_value(json!({
|
||||||
|
"position": {"character":10, "line":2},
|
||||||
|
"textDocument": {
|
||||||
|
"uri": "file:///filler.py"
|
||||||
|
}
|
||||||
|
}))?,
|
||||||
|
);
|
||||||
|
let mut config = config::Config::default_with_file_store_without_models();
|
||||||
|
config.config.completion = Some(serde_json::from_value(json!({
|
||||||
|
"model": "model1",
|
||||||
|
"parameters": {
|
||||||
|
"options": {
|
||||||
|
"temperature": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}))?);
|
||||||
|
|
||||||
|
let result = do_completion(
|
||||||
|
&transformer_backend,
|
||||||
|
memory_tx,
|
||||||
|
&completion_request,
|
||||||
|
&config,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
" x * y",
|
||||||
|
result.result.clone().unwrap()["items"][0]["textEdit"]["newText"]
|
||||||
|
.as_str()
|
||||||
|
.unwrap()
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
" return",
|
||||||
|
result.result.unwrap()["items"][0]["filterText"]
|
||||||
|
.as_str()
|
||||||
|
.unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_do_generate() -> anyhow::Result<()> {
|
||||||
|
let (memory_tx, memory_rx) = mpsc::channel();
|
||||||
|
let memory_backend: Box<dyn MemoryBackend + Send + Sync> =
|
||||||
|
Box::new(FileStore::default_with_filler_file()?);
|
||||||
|
thread::spawn(move || memory_worker::run(memory_backend, memory_rx));
|
||||||
|
|
||||||
|
let transformer_backend: Box<dyn TransformerBackend + Send + Sync> =
|
||||||
|
config::ValidModel::Ollama(serde_json::from_value(
|
||||||
|
json!({"model": "deepseek-coder:1.3b-base"}),
|
||||||
|
)?)
|
||||||
|
.try_into()?;
|
||||||
|
let generation_request = GenerationRequest::new(
|
||||||
|
serde_json::from_value(json!(0))?,
|
||||||
|
serde_json::from_value(json!({
|
||||||
|
"position": {"character":10, "line":2},
|
||||||
|
"textDocument": {
|
||||||
|
"uri": "file:///filler.py"
|
||||||
|
},
|
||||||
|
"model": "model1",
|
||||||
|
"parameters": {
|
||||||
|
"options": {
|
||||||
|
"temperature": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}))?,
|
||||||
|
);
|
||||||
|
let result = do_generate(&transformer_backend, memory_tx, &generation_request).await?;
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
" x * y",
|
||||||
|
result.result.unwrap()["generatedText"].as_str().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_post_process_fim() {
|
fn test_post_process_fim() {
|
||||||
|
Loading…
Reference in New Issue
Block a user