Skip to content

Commit

Permalink
Add test helpers
Browse files Browse the repository at this point in the history
commit-id:cec863be
  • Loading branch information
Draggu committed Nov 6, 2024
1 parent 897fb6d commit 2e52a80
Showing 1 changed file with 159 additions and 0 deletions.
159 changes: 159 additions & 0 deletions scarb/tests/proc_macro_server_helpers/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
use scarb_proc_macro_server_types::jsonrpc::RequestId;
use scarb_proc_macro_server_types::jsonrpc::ResponseError;
use scarb_proc_macro_server_types::jsonrpc::RpcRequest;
use scarb_proc_macro_server_types::jsonrpc::RpcResponse;
use scarb_proc_macro_server_types::methods::Method;
use scarb_test_support::command::Scarb;
use std::collections::HashMap;
use std::io::BufRead;
use std::io::BufReader;
use std::io::Lines;
use std::io::Write;
use std::marker::PhantomData;
use std::path::Path;
use std::process::Child;
use std::process::ChildStdin;
use std::process::ChildStdout;
use std::process::Stdio;

pub const SIMPLE_MACROS: &str = r#"
use cairo_lang_macro::{
ProcMacroResult,
TokenStream,
attribute_macro,
inline_macro,
derive_macro,
executable_attribute
};
executable_attribute!("some_executable");
#[attribute_macro]
pub fn some(_attr: TokenStream, token_stream: TokenStream) -> ProcMacroResult {
ProcMacroResult::new(token_stream)
}
#[inline_macro]
pub fn inline_some(token_stream: TokenStream) -> ProcMacroResult {
ProcMacroResult::new(token_stream)
}
#[derive_macro]
fn some_derive(_token_stream: TokenStream)-> ProcMacroResult {
ProcMacroResult::new(TokenStream::new("impl SomeImpl of SomeTrait {}".to_string()))
}
"#;

pub struct PendingRequest<M: Method> {
id: RequestId,
_data: PhantomData<M>,
}

impl<M: Method> PendingRequest<M> {
fn new(id: RequestId) -> Self {
Self {
id,
_data: Default::default(),
}
}
}

pub struct Response<M: Method> {
raw: RpcResponse,
_data: PhantomData<M>,
}

impl<M: Method> Response<M> {
fn new(raw: RpcResponse) -> Self {
Self {
raw,
_data: Default::default(),
}
}

pub fn ok(self) -> M::Response {
serde_json::from_value(self.raw.result.unwrap()).unwrap()
}

#[allow(dead_code)]
pub fn error(self) -> ResponseError {
self.raw.error.unwrap()
}
}

pub struct TestProcMacroServer {
requester: ChildStdin,
responder: Lines<BufReader<ChildStdout>>,
inner: Child,
id_counter: RequestId,
responses: HashMap<RequestId, RpcResponse>,
}

impl TestProcMacroServer {
pub fn new<P: AsRef<Path>>(path: P) -> Self {
let mut inner = Scarb::new()
.std()
.arg("--quiet")
.arg("proc-macro-server")
.stdout(Stdio::piped())
.stdin(Stdio::piped())
.stderr(Stdio::inherit())
.current_dir(path)
.spawn()
.unwrap();

let requester = inner.stdin.take().unwrap();
let responder = BufReader::new(inner.stdout.take().unwrap()).lines();

Self {
requester,
responder,
inner,
id_counter: Default::default(),
responses: Default::default(),
}
}

pub fn request<M: Method>(&mut self, params: M::Params) -> PendingRequest<M> {
let id = self.id_counter;
self.id_counter += 1;

let mut request = serde_json::to_vec(&RpcRequest {
id,
method: M::METHOD.to_string(),
value: serde_json::to_value(params).unwrap(),
})
.unwrap();
request.push(b'\n');

self.requester.write_all(&request).unwrap();
self.requester.flush().unwrap();

PendingRequest::new(id)
}

pub fn wait_for_response<M: Method>(&mut self, request: PendingRequest<M>) -> Response<M> {
// If we already readed this response return it.
if let Some(raw_response) = self.responses.remove(&request.id) {
return Response::new(raw_response);
}

// Read responses until we get requested one, keeping all others in memory.
loop {
let response = self.responder.next().unwrap().unwrap();
let raw_response: RpcResponse = serde_json::from_str(&response).unwrap();

if raw_response.id == request.id {
return Response::new(raw_response);
} else {
self.responses.insert(raw_response.id, raw_response);
}
}
}
}

impl Drop for TestProcMacroServer {
fn drop(&mut self) {
self.inner.wait().unwrap();
}
}

0 comments on commit 2e52a80

Please sign in to comment.