Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

initial testing of fsm #14

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions crates/analyzer-host/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,7 @@ serde = "1.0.143"
serde_json = "1.0.83"
thiserror = "1.0.37"
tracing-subscriber = "0.3.16"

[dev-dependencies]
async-io = "1.13.0"
tester = { path = "../tester" }
6 changes: 5 additions & 1 deletion crates/analyzer-host/src/fsm.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use analyzer_abstractions::{fs::AnyEnumerableFileSystem, tracing::info};
use async_rwlock::RwLock as AsyncRwLock;
use serde_json::Value;
use std::{
collections::HashMap,
sync::{Arc, RwLock},
};

use crate::{
json_rpc::{message::Message, ErrorCode},
json_rpc::{message::{Message, Request, self, Notification}, ErrorCode},
lsp::{dispatch::Dispatch, request::RequestManager, state::LspServerState, DispatchBuilder, LspProtocolError},
lsp_impl::{
active_initialized::create_dispatcher as create_dispatcher_active_initialized,
Expand Down Expand Up @@ -52,6 +53,9 @@ impl LspProtocolMachine {
/// Returns `true` if the current [`LspProtocolMachine`] is in an active state; otherwise `false`.
pub fn is_active(&self) -> bool { self.current_state != LspServerState::Stopped }

/// Returns the current_state that the [`LspProtocolMachine`] is in.
pub fn current_state(&self) -> LspServerState { self.current_state }

/// Processes a [`Message`] for the current [`LspProtocolMachine`], and returns an optional [`Message`] that represents
/// its response.
pub async fn process_message(&mut self, message: Arc<Message>) -> Result<Option<Message>, LspProtocolError> {
Expand Down
4 changes: 4 additions & 0 deletions crates/analyzer-host/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,3 +161,7 @@ impl AnalyzerHost {
Ok(())
}
}

// Unit test fixtures.
#[cfg(test)]
mod tests;
1 change: 1 addition & 0 deletions crates/analyzer-host/src/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub(crate) mod unit_tests;
70 changes: 70 additions & 0 deletions crates/analyzer-host/src/tests/unit_tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
use std::sync::Arc;

use analyzer_abstractions::lsp_types::{
Position, TextDocumentIdentifier, TextDocumentPositionParams, Url, WorkDoneProgressParams,
};
use serde_json::Value;

use crate::{
fs::LspEnumerableFileSystem,
fsm::LspProtocolMachine,
json_rpc::message::{Message, Notification, Request},
lsp::{request::RequestManager, state::LspServerState},
};

#[test]
fn test_lsp_states() {
let rm = RequestManager::new(async_channel::unbounded::<Message>());
let mut lsp =
LspProtocolMachine::new(None, rm.clone(), Arc::new(Box::new(LspEnumerableFileSystem::new(rm.clone()))));
assert_eq!(lsp.current_state(), LspServerState::ActiveUninitialized);
assert_eq!(lsp.is_active(), true);

let mut params = serde_json::json!(analyzer_abstractions::lsp_types::InitializeParams { ..Default::default() });
let mut message = Message::Request(Request { id: 0.into(), method: String::from("initialize"), params: params });
let mut output = async_io::block_on(lsp.process_message(Arc::new(message)));
assert!(output.is_ok());
assert_eq!(lsp.current_state(), LspServerState::Initializing);
assert_eq!(lsp.is_active(), true);

let url = Url::parse("https://example.net").unwrap();
let hover_params = analyzer_abstractions::lsp_types::HoverParams {
text_document_position_params: TextDocumentPositionParams {
text_document: TextDocumentIdentifier { uri: url },
position: Position { line: 0, character: 0 },
},
work_done_progress_params: WorkDoneProgressParams { work_done_token: None },
};
params = serde_json::json!(hover_params);
message = Message::Request(Request { id: 0.into(), method: String::from("textDocument/hover"), params: params });
output = async_io::block_on(lsp.process_message(Arc::new(message)));
assert!(output.is_ok());
assert_eq!(lsp.current_state(), LspServerState::Initializing);
assert_eq!(lsp.is_active(), true);

params = serde_json::json!(analyzer_abstractions::lsp_types::InitializedParams {});
message = Message::Notification(Notification { method: String::from("initialized"), params: params });
output = async_io::block_on(lsp.process_message(Arc::new(message)));
assert!(output.is_ok());
assert_eq!(lsp.current_state(), LspServerState::ActiveInitialized);
assert_eq!(lsp.is_active(), true);

params = serde_json::json!(hover_params);
message = Message::Notification(Notification { method: String::from("textDocument/hover"), params: params });
output = async_io::block_on(lsp.process_message(Arc::new(message)));
assert!(output.is_err());
assert_eq!(lsp.current_state(), LspServerState::ActiveInitialized);
assert_eq!(lsp.is_active(), true);

message = Message::Request(Request { id: 0.into(), method: String::from("shutdown"), params: Value::Null });
output = async_io::block_on(lsp.process_message(Arc::new(message)));
assert!(output.is_ok());
assert_eq!(lsp.current_state(), LspServerState::ShuttingDown);
assert_eq!(lsp.is_active(), true);

message = Message::Notification(Notification { method: String::from("exit"), params: Value::Null });
output = async_io::block_on(lsp.process_message(Arc::new(message)));
assert!(output.is_ok());
assert_eq!(lsp.current_state(), LspServerState::Stopped);
assert_eq!(lsp.is_active(), false);
}