-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
179 additions
and
0 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ resolver = "2" | |
members = [ | ||
"transport", | ||
"debugger", | ||
"server", | ||
] | ||
|
||
[profile.release] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
[package] | ||
name = "server" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[dependencies] | ||
anyhow.workspace = true | ||
tracing.workspace = true | ||
transport = { path = "../transport" } | ||
|
||
[dev-dependencies] | ||
tracing-subscriber = { version = "0.3.18", features = ["json", "env-filter"] } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
use std::{ | ||
io::{BufRead, BufReader}, | ||
process::{Child, Stdio}, | ||
sync::mpsc, | ||
thread, | ||
}; | ||
|
||
use anyhow::Context; | ||
|
||
use crate::Server; | ||
|
||
pub struct DebugpyServer { | ||
child: Child, | ||
} | ||
|
||
impl Server for DebugpyServer { | ||
fn on_port(port: impl Into<u16>) -> anyhow::Result<Self> { | ||
let port = port.into(); | ||
|
||
tracing::debug!(port = ?port, "starting server process"); | ||
let cwd = std::env::current_dir().unwrap(); | ||
let mut child = std::process::Command::new("python") | ||
.args([ | ||
"-m", | ||
"debugpy.adapter", | ||
"--host", | ||
"127.0.0.1", | ||
"--port", | ||
&format!("{port}"), | ||
"--log-stderr", | ||
]) | ||
.stderr(Stdio::piped()) | ||
.current_dir(cwd.join("..").canonicalize().unwrap()) | ||
.spawn() | ||
.context("spawning background process")?; | ||
|
||
// wait until server is ready | ||
tracing::debug!("waiting until server is ready"); | ||
let stderr = child.stderr.take().unwrap(); | ||
let reader = BufReader::new(stderr); | ||
|
||
let (tx, rx) = mpsc::channel(); | ||
thread::spawn(move || { | ||
let mut should_signal = true; | ||
for line in reader.lines() { | ||
let line = line.unwrap(); | ||
if should_signal && line.contains("Listening for incoming Client connections") { | ||
should_signal = false; | ||
let _ = tx.send(()); | ||
} | ||
} | ||
}); | ||
let _ = rx.recv(); | ||
|
||
tracing::debug!("server ready"); | ||
Ok(Self { child }) | ||
} | ||
} | ||
|
||
impl Drop for DebugpyServer { | ||
fn drop(&mut self) { | ||
tracing::debug!("terminating server"); | ||
match self.child.kill() { | ||
Ok(_) => { | ||
tracing::debug!("server terminated"); | ||
let _ = self.child.wait(); | ||
} | ||
Err(e) => tracing::warn!(error = %e, "could not terminate server process"), | ||
} | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use std::{io::IsTerminal, net::TcpStream}; | ||
|
||
use anyhow::Context; | ||
use tracing_subscriber::EnvFilter; | ||
use transport::bindings::get_random_tcp_port; | ||
|
||
use crate::{for_implementation_on_port, Implementation}; | ||
|
||
fn init_test_logger() { | ||
let in_ci = std::env::var("CI") | ||
.map(|val| val == "true") | ||
.unwrap_or(false); | ||
|
||
if std::io::stderr().is_terminal() || in_ci { | ||
tracing_subscriber::fmt() | ||
.with_env_filter(EnvFilter::from_default_env()) | ||
.init(); | ||
} else { | ||
tracing_subscriber::fmt() | ||
.with_env_filter(EnvFilter::from_default_env()) | ||
.json() | ||
.init(); | ||
} | ||
} | ||
|
||
#[test] | ||
fn test_create() -> anyhow::Result<()> { | ||
init_test_logger(); | ||
|
||
let port = get_random_tcp_port().context("reserving custom port")?; | ||
let _server = | ||
for_implementation_on_port(Implementation::Debugpy, port).context("creating server")?; | ||
|
||
// server should be running | ||
tracing::info!("making connection"); | ||
let _conn = | ||
TcpStream::connect(&format!("127.0.0.1:{port}")).context("connecting to server")?; | ||
Ok(()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
use anyhow::Context; | ||
use transport::DEFAULT_DAP_PORT; | ||
|
||
pub mod debugpy; | ||
|
||
pub enum Implementation { | ||
Debugpy, | ||
} | ||
|
||
pub trait Server { | ||
fn on_port(port: impl Into<u16>) -> anyhow::Result<Self> | ||
where | ||
Self: Sized; | ||
|
||
fn new() -> anyhow::Result<Self> | ||
where | ||
Self: Sized, | ||
{ | ||
Self::on_port(DEFAULT_DAP_PORT) | ||
} | ||
} | ||
|
||
pub fn for_implementation(implementation: Implementation) -> anyhow::Result<Box<dyn Server>> { | ||
for_implementation_on_port(implementation, DEFAULT_DAP_PORT) | ||
} | ||
|
||
pub fn for_implementation_on_port( | ||
implementation: Implementation, | ||
port: impl Into<u16>, | ||
) -> anyhow::Result<Box<dyn Server>> { | ||
match implementation { | ||
Implementation::Debugpy => { | ||
let server = crate::debugpy::DebugpyServer::on_port(port).context("creating server")?; | ||
Ok(Box::new(server)) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters