summaryrefslogtreecommitdiff
path: root/cli/tests/integration/inspector_tests.rs
diff options
context:
space:
mode:
Diffstat (limited to 'cli/tests/integration/inspector_tests.rs')
-rw-r--r--cli/tests/integration/inspector_tests.rs469
1 files changed, 307 insertions, 162 deletions
diff --git a/cli/tests/integration/inspector_tests.rs b/cli/tests/integration/inspector_tests.rs
index f5365ac99..f6b95c1b4 100644
--- a/cli/tests/integration/inspector_tests.rs
+++ b/cli/tests/integration/inspector_tests.rs
@@ -2,12 +2,16 @@
use deno_core::futures;
use deno_core::futures::prelude::*;
+use deno_core::futures::stream::SplitSink;
use deno_core::serde_json;
use deno_core::url;
use deno_runtime::deno_fetch::reqwest;
use deno_runtime::deno_websocket::tokio_tungstenite;
+use deno_runtime::deno_websocket::tokio_tungstenite::tungstenite;
use std::io::BufRead;
+use std::pin::Pin;
use test_util as util;
+use tokio::net::TcpStream;
fn inspect_flag_with_unique_port(flag_prefix: &str) -> String {
use std::sync::atomic::{AtomicU16, Ordering};
@@ -28,6 +32,71 @@ fn extract_ws_url_from_stderr(
url::Url::parse(ws_url).unwrap()
}
+fn assert_stderr_for_inspect(
+ stderr_lines: &mut impl std::iter::Iterator<Item = String>,
+) {
+ assert_eq!(
+ &stderr_lines.next().unwrap(),
+ "Visit chrome://inspect to connect to the debugger."
+ );
+}
+
+fn assert_stderr_for_inspect_brk(
+ stderr_lines: &mut impl std::iter::Iterator<Item = String>,
+) {
+ assert_eq!(
+ &stderr_lines.next().unwrap(),
+ "Visit chrome://inspect to connect to the debugger."
+ );
+ assert_eq!(
+ &stderr_lines.next().unwrap(),
+ "Deno is waiting for debugger to connect."
+ );
+}
+
+async fn assert_inspector_messages(
+ socket_tx: &mut SplitSink<
+ tokio_tungstenite::WebSocketStream<
+ tokio_tungstenite::MaybeTlsStream<TcpStream>,
+ >,
+ tungstenite::Message,
+ >,
+ messages: &[&str],
+ socket_rx: &mut Pin<Box<dyn Stream<Item = String>>>,
+ responses: &[&str],
+ notifications: &[&str],
+) {
+ for msg in messages {
+ socket_tx.send(msg.to_string().into()).await.unwrap();
+ }
+
+ let expected_messages = responses.len() + notifications.len();
+ let mut responses_idx = 0;
+ let mut notifications_idx = 0;
+
+ for _ in 0..expected_messages {
+ let msg = socket_rx.next().await.unwrap();
+
+ if msg.starts_with(r#"{"id":"#) {
+ assert!(
+ msg.starts_with(responses[responses_idx]),
+ "Doesn't start with {}, instead received {}",
+ responses[responses_idx],
+ msg
+ );
+ responses_idx += 1;
+ } else {
+ assert!(
+ msg.starts_with(notifications[notifications_idx]),
+ "Doesn't start with {}, instead received {}",
+ notifications[notifications_idx],
+ msg
+ );
+ notifications_idx += 1;
+ }
+ }
+}
+
#[tokio::test]
async fn inspector_connect() {
let script = util::testdata_path().join("inspector1.js");
@@ -54,14 +123,6 @@ async fn inspector_connect() {
child.wait().unwrap();
}
-#[derive(Debug)]
-enum TestStep {
- StdOut(&'static str),
- StdErr(&'static str),
- WsRecv(&'static str),
- WsSend(&'static str),
-}
-
#[tokio::test]
async fn inspector_break_on_first_line() {
let script = util::testdata_path().join("inspector2.js");
@@ -85,48 +146,69 @@ async fn inspector_break_on_first_line() {
assert_eq!(response.status(), 101); // Switching protocols.
let (mut socket_tx, socket_rx) = socket.split();
- let mut socket_rx =
- socket_rx.map(|msg| msg.unwrap().to_string()).filter(|msg| {
+ let mut socket_rx = socket_rx
+ .map(|msg| msg.unwrap().to_string())
+ .filter(|msg| {
let pass = !msg.starts_with(r#"{"method":"Debugger.scriptParsed","#);
futures::future::ready(pass)
- });
+ })
+ .boxed_local();
let stdout = child.stdout.as_mut().unwrap();
let mut stdout_lines =
std::io::BufReader::new(stdout).lines().map(|r| r.unwrap());
- use TestStep::*;
- let test_steps = vec![
- StdErr("Visit chrome://inspect to connect to the debugger."),
- StdErr("Deno is waiting for debugger to connect."),
- WsSend(r#"{"id":1,"method":"Runtime.enable"}"#),
- WsSend(r#"{"id":2,"method":"Debugger.enable"}"#),
- WsRecv(
+ assert_stderr_for_inspect_brk(&mut stderr_lines);
+
+ assert_inspector_messages(
+ &mut socket_tx,
+ &[
+ r#"{"id":1,"method":"Runtime.enable"}"#,
+ r#"{"id":2,"method":"Debugger.enable"}"#,
+ ],
+ &mut socket_rx,
+ &[
+ r#"{"id":1,"result":{}}"#,
+ r#"{"id":2,"result":{"debuggerId":"#,
+ ],
+ &[
r#"{"method":"Runtime.executionContextCreated","params":{"context":{"id":1,"#,
- ),
- WsRecv(r#"{"id":1,"result":{}}"#),
- WsRecv(r#"{"id":2,"result":{"debuggerId":"#),
- WsSend(r#"{"id":3,"method":"Runtime.runIfWaitingForDebugger"}"#),
- WsRecv(r#"{"id":3,"result":{}}"#),
- WsRecv(r#"{"method":"Debugger.paused","#),
- WsSend(
+ ],
+ )
+ .await;
+
+ assert_inspector_messages(
+ &mut socket_tx,
+ &[r#"{"id":3,"method":"Runtime.runIfWaitingForDebugger"}"#],
+ &mut socket_rx,
+ &[r#"{"id":3,"result":{}}"#],
+ &[r#"{"method":"Debugger.paused","#],
+ )
+ .await;
+
+ assert_inspector_messages(
+ &mut socket_tx,
+ &[
r#"{"id":4,"method":"Runtime.evaluate","params":{"expression":"Deno.core.print(\"hello from the inspector\\n\")","contextId":1,"includeCommandLineAPI":true,"silent":false,"returnByValue":true}}"#,
- ),
- WsRecv(r#"{"id":4,"result":{"result":{"type":"undefined"}}}"#),
- StdOut("hello from the inspector"),
- WsSend(r#"{"id":5,"method":"Debugger.resume"}"#),
- WsRecv(r#"{"id":5,"result":{}}"#),
- StdOut("hello from the script"),
- ];
-
- for step in test_steps {
- match step {
- StdErr(s) => assert_eq!(&stderr_lines.next().unwrap(), s),
- StdOut(s) => assert_eq!(&stdout_lines.next().unwrap(), s),
- WsRecv(s) => assert!(socket_rx.next().await.unwrap().starts_with(s)),
- WsSend(s) => socket_tx.send(s.into()).await.unwrap(),
- }
- }
+ ],
+ &mut socket_rx,
+ &[r#"{"id":4,"result":{"result":{"type":"undefined"}}}"#],
+ &[],
+ )
+ .await;
+
+ assert_eq!(&stdout_lines.next().unwrap(), "hello from the inspector");
+
+ assert_inspector_messages(
+ &mut socket_tx,
+ &[r#"{"id":5,"method":"Debugger.resume"}"#],
+ &mut socket_rx,
+ &[r#"{"id":5,"result":{}}"#],
+ &[],
+ )
+ .await;
+
+ assert_eq!(&stdout_lines.next().unwrap(), "hello from the script");
child.kill().unwrap();
child.wait().unwrap();
@@ -266,63 +348,84 @@ async fn inspector_does_not_hang() {
assert_eq!(response.status(), 101); // Switching protocols.
let (mut socket_tx, socket_rx) = socket.split();
- let mut socket_rx =
- socket_rx.map(|msg| msg.unwrap().to_string()).filter(|msg| {
+ let mut socket_rx = socket_rx
+ .map(|msg| msg.unwrap().to_string())
+ .filter(|msg| {
let pass = !msg.starts_with(r#"{"method":"Debugger.scriptParsed","#);
futures::future::ready(pass)
- });
+ })
+ .boxed_local();
let stdout = child.stdout.as_mut().unwrap();
let mut stdout_lines =
std::io::BufReader::new(stdout).lines().map(|r| r.unwrap());
- use TestStep::*;
- let test_steps = vec![
- StdErr("Visit chrome://inspect to connect to the debugger."),
- StdErr("Deno is waiting for debugger to connect."),
- WsSend(r#"{"id":1,"method":"Runtime.enable"}"#),
- WsSend(r#"{"id":2,"method":"Debugger.enable"}"#),
- WsRecv(
- r#"{"method":"Runtime.executionContextCreated","params":{"context":{"id":1,"#,
- ),
- WsRecv(r#"{"id":1,"result":{}}"#),
- WsRecv(r#"{"id":2,"result":{"debuggerId":"#),
- WsSend(r#"{"id":3,"method":"Runtime.runIfWaitingForDebugger"}"#),
- WsRecv(r#"{"id":3,"result":{}}"#),
- WsRecv(r#"{"method":"Debugger.paused","#),
- WsSend(r#"{"id":4,"method":"Debugger.resume"}"#),
- WsRecv(r#"{"id":4,"result":{}}"#),
- WsRecv(r#"{"method":"Debugger.resumed","params":{}}"#),
- ];
-
- for step in test_steps {
- match step {
- StdErr(s) => assert_eq!(&stderr_lines.next().unwrap(), s),
- WsRecv(s) => assert!(socket_rx.next().await.unwrap().starts_with(s)),
- WsSend(s) => socket_tx.send(s.into()).await.unwrap(),
- _ => unreachable!(),
- }
- }
+ assert_stderr_for_inspect_brk(&mut stderr_lines);
+
+ assert_inspector_messages(
+ &mut socket_tx,
+ &[
+ r#"{"id":1,"method":"Runtime.enable"}"#,
+ r#"{"id":2,"method":"Debugger.enable"}"#,
+ ],
+ &mut socket_rx,
+ &[
+ r#"{"id":1,"result":{}}"#,
+ r#"{"id":2,"result":{"debuggerId":"#
+ ],
+ &[
+ r#"{"method":"Runtime.executionContextCreated","params":{"context":{"id":1,"#
+ ],
+ )
+ .await;
+
+ assert_inspector_messages(
+ &mut socket_tx,
+ &[r#"{"id":3,"method":"Runtime.runIfWaitingForDebugger"}"#],
+ &mut socket_rx,
+ &[r#"{"id":3,"result":{}}"#],
+ &[r#"{"method":"Debugger.paused","#],
+ )
+ .await;
+
+ assert_inspector_messages(
+ &mut socket_tx,
+ &[r#"{"id":4,"method":"Debugger.resume"}"#],
+ &mut socket_rx,
+ &[r#"{"id":4,"result":{}}"#],
+ &[r#"{"method":"Debugger.resumed","params":{}}"#],
+ )
+ .await;
for i in 0..128u32 {
let request_id = i + 10;
// Expect the number {i} on stdout.
let s = i.to_string();
assert_eq!(stdout_lines.next().unwrap(), s);
- // Expect console.log
- let s = r#"{"method":"Runtime.consoleAPICalled","#;
- assert!(socket_rx.next().await.unwrap().starts_with(s));
- // Expect hitting the `debugger` statement.
- let s = r#"{"method":"Debugger.paused","#;
- assert!(socket_rx.next().await.unwrap().starts_with(s));
- // Send the 'Debugger.resume' request.
- let s = format!(r#"{{"id":{},"method":"Debugger.resume"}}"#, request_id);
- socket_tx.send(s.into()).await.unwrap();
- // Expect confirmation of the 'Debugger.resume' request.
- let s = format!(r#"{{"id":{},"result":{{}}}}"#, request_id);
- assert_eq!(socket_rx.next().await.unwrap(), s);
- let s = r#"{"method":"Debugger.resumed","params":{}}"#;
- assert_eq!(socket_rx.next().await.unwrap(), s);
+
+ assert_inspector_messages(
+ &mut socket_tx,
+ &[],
+ &mut socket_rx,
+ &[],
+ &[
+ r#"{"method":"Runtime.consoleAPICalled","#,
+ r#"{"method":"Debugger.paused","#,
+ ],
+ )
+ .await;
+
+ assert_inspector_messages(
+ &mut socket_tx,
+ &[&format!(
+ r#"{{"id":{},"method":"Debugger.resume"}}"#,
+ request_id
+ )],
+ &mut socket_rx,
+ &[&format!(r#"{{"id":{},"result":{{}}}}"#, request_id)],
+ &[r#"{"method":"Debugger.resumed","params":{}}"#],
+ )
+ .await;
}
// Check that we can gracefully close the websocket connection.
@@ -386,11 +489,13 @@ async fn inspector_runtime_evaluate_does_not_crash() {
assert_eq!(response.status(), 101); // Switching protocols.
let (mut socket_tx, socket_rx) = socket.split();
- let mut socket_rx =
- socket_rx.map(|msg| msg.unwrap().to_string()).filter(|msg| {
+ let mut socket_rx = socket_rx
+ .map(|msg| msg.unwrap().to_string())
+ .filter(|msg| {
let pass = !msg.starts_with(r#"{"method":"Debugger.scriptParsed","#);
futures::future::ready(pass)
- });
+ })
+ .boxed_local();
let stdin = child.stdin.take().unwrap();
@@ -400,43 +505,60 @@ async fn inspector_runtime_evaluate_does_not_crash() {
.map(|r| r.unwrap())
.filter(|s| !s.starts_with("Deno "));
- use TestStep::*;
- let test_steps = vec![
- StdErr("Visit chrome://inspect to connect to the debugger."),
- WsSend(r#"{"id":1,"method":"Runtime.enable"}"#),
- WsSend(r#"{"id":2,"method":"Debugger.enable"}"#),
- WsRecv(
+ assert_stderr_for_inspect(&mut stderr_lines);
+
+ assert_inspector_messages(
+ &mut socket_tx,
+ &[
+ r#"{"id":1,"method":"Runtime.enable"}"#,
+ r#"{"id":2,"method":"Debugger.enable"}"#,
+ ],
+ &mut socket_rx,
+ &[
+ r#"{"id":1,"result":{}}"#,
+ r#"{"id":2,"result":{"debuggerId":"#,
+ ],
+ &[
r#"{"method":"Runtime.executionContextCreated","params":{"context":{"id":1,"#,
- ),
- WsRecv(r#"{"id":1,"result":{}}"#),
- WsRecv(r#"{"id":2,"result":{"debuggerId":"#),
- WsSend(r#"{"id":3,"method":"Runtime.runIfWaitingForDebugger"}"#),
- WsRecv(r#"{"id":3,"result":{}}"#),
- StdOut("exit using ctrl+d or close()"),
- WsSend(
- r#"{"id":4,"method":"Runtime.compileScript","params":{"expression":"Deno.cwd()","sourceURL":"","persistScript":false,"executionContextId":1}}"#,
- ),
- WsRecv(r#"{"id":4,"result":{}}"#),
- WsSend(
- r#"{"id":5,"method":"Runtime.evaluate","params":{"expression":"Deno.cwd()","objectGroup":"console","includeCommandLineAPI":true,"silent":false,"contextId":1,"returnByValue":true,"generatePreview":true,"userGesture":true,"awaitPromise":false,"replMode":true}}"#,
- ),
- WsRecv(r#"{"id":5,"result":{"result":{"type":"string","value":""#),
- WsSend(
- r#"{"id":6,"method":"Runtime.evaluate","params":{"expression":"console.error('done');","objectGroup":"console","includeCommandLineAPI":true,"silent":false,"contextId":1,"returnByValue":true,"generatePreview":true,"userGesture":true,"awaitPromise":false,"replMode":true}}"#,
- ),
- WsRecv(r#"{"method":"Runtime.consoleAPICalled"#),
- WsRecv(r#"{"id":6,"result":{"result":{"type":"undefined"}}}"#),
- StdErr("done"),
- ];
-
- for step in test_steps {
- match step {
- StdOut(s) => assert_eq!(&stdout_lines.next().unwrap(), s),
- StdErr(s) => assert_eq!(&stderr_lines.next().unwrap(), s),
- WsRecv(s) => assert!(socket_rx.next().await.unwrap().starts_with(s)),
- WsSend(s) => socket_tx.send(s.into()).await.unwrap(),
- }
- }
+ ],
+ )
+ .await;
+
+ assert_eq!(
+ &stdout_lines.next().unwrap(),
+ "exit using ctrl+d or close()"
+ );
+
+ assert_inspector_messages(
+ &mut socket_tx,
+ &[
+ r#"{"id":3,"method":"Runtime.compileScript","params":{"expression":"Deno.cwd()","sourceURL":"","persistScript":false,"executionContextId":1}}"#,
+ ],
+ &mut socket_rx,
+ &[r#"{"id":3,"result":{}}"#], &[]
+ ).await;
+
+ assert_inspector_messages(
+ &mut socket_tx,
+ &[
+ r#"{"id":4,"method":"Runtime.evaluate","params":{"expression":"Deno.cwd()","objectGroup":"console","includeCommandLineAPI":true,"silent":false,"contextId":1,"returnByValue":true,"generatePreview":true,"userGesture":true,"awaitPromise":false,"replMode":true}}"#,
+ ],
+ &mut socket_rx,
+ &[r#"{"id":4,"result":{"result":{"type":"string","value":""#],
+ &[],
+ ).await;
+
+ assert_inspector_messages(
+ &mut socket_tx,
+ &[
+ r#"{"id":5,"method":"Runtime.evaluate","params":{"expression":"console.error('done');","objectGroup":"console","includeCommandLineAPI":true,"silent":false,"contextId":1,"returnByValue":true,"generatePreview":true,"userGesture":true,"awaitPromise":false,"replMode":true}}"#,
+ ],
+ &mut socket_rx,
+ &[r#"{"id":5,"result":{"result":{"type":"undefined"}}}"#],
+ &[r#"{"method":"Runtime.consoleAPICalled"#],
+ ).await;
+
+ assert_eq!(&stderr_lines.next().unwrap(), "done");
drop(stdin);
child.wait().unwrap();
@@ -549,53 +671,76 @@ async fn inspector_break_on_first_line_in_test() {
assert_eq!(response.status(), 101); // Switching protocols.
let (mut socket_tx, socket_rx) = socket.split();
- let mut socket_rx =
- socket_rx.map(|msg| msg.unwrap().to_string()).filter(|msg| {
+ let mut socket_rx = socket_rx
+ .map(|msg| msg.unwrap().to_string())
+ .filter(|msg| {
let pass = !msg.starts_with(r#"{"method":"Debugger.scriptParsed","#);
futures::future::ready(pass)
- });
+ })
+ .boxed_local();
let stdout = child.stdout.as_mut().unwrap();
let mut stdout_lines =
std::io::BufReader::new(stdout).lines().map(|r| r.unwrap());
- use TestStep::*;
- let test_steps = vec![
- StdErr("Visit chrome://inspect to connect to the debugger."),
- StdErr("Deno is waiting for debugger to connect."),
- WsSend(r#"{"id":1,"method":"Runtime.enable"}"#),
- WsSend(r#"{"id":2,"method":"Debugger.enable"}"#),
- WsRecv(
+ assert_stderr_for_inspect_brk(&mut stderr_lines);
+
+ assert_inspector_messages(
+ &mut socket_tx,
+ &[
+ r#"{"id":1,"method":"Runtime.enable"}"#,
+ r#"{"id":2,"method":"Debugger.enable"}"#,
+ ],
+ &mut socket_rx,
+ &[
+ r#"{"id":1,"result":{}}"#,
+ r#"{"id":2,"result":{"debuggerId":"#,
+ ],
+ &[
r#"{"method":"Runtime.executionContextCreated","params":{"context":{"id":1,"#,
- ),
- WsRecv(r#"{"id":1,"result":{}}"#),
- WsRecv(r#"{"id":2,"result":{"debuggerId":"#),
- WsSend(r#"{"id":3,"method":"Runtime.runIfWaitingForDebugger"}"#),
- WsRecv(r#"{"id":3,"result":{}}"#),
- WsRecv(r#"{"method":"Debugger.paused","#),
- WsSend(
+ ],
+ )
+ .await;
+
+ assert_inspector_messages(
+ &mut socket_tx,
+ &[r#"{"id":3,"method":"Runtime.runIfWaitingForDebugger"}"#],
+ &mut socket_rx,
+ &[r#"{"id":3,"result":{}}"#],
+ &[r#"{"method":"Debugger.paused","#],
+ )
+ .await;
+
+ assert_inspector_messages(
+ &mut socket_tx,
+ &[
r#"{"id":4,"method":"Runtime.evaluate","params":{"expression":"Deno.core.print(\"hello from the inspector\\n\")","contextId":1,"includeCommandLineAPI":true,"silent":false,"returnByValue":true}}"#,
- ),
- WsRecv(r#"{"id":4,"result":{"result":{"type":"undefined"}}}"#),
- StdOut("hello from the inspector"),
- WsSend(r#"{"id":5,"method":"Debugger.resume"}"#),
- WsRecv(r#"{"id":5,"result":{}}"#),
- StdOut("running 1 test from"),
- StdOut("test has finished running"),
- ];
-
- for step in test_steps {
- match step {
- StdOut(s) => assert!(
- &stdout_lines.next().unwrap().contains(s),
- "Doesn't contain {}",
- s
- ),
- StdErr(s) => assert_eq!(&stderr_lines.next().unwrap(), s),
- WsRecv(s) => assert!(socket_rx.next().await.unwrap().starts_with(s)),
- WsSend(s) => socket_tx.send(s.into()).await.unwrap(),
- }
- }
+ ],
+ &mut socket_rx,
+ &[r#"{"id":4,"result":{"result":{"type":"undefined"}}}"#],
+ &[],
+ )
+ .await;
+
+ assert_eq!(&stdout_lines.next().unwrap(), "hello from the inspector");
+
+ assert_inspector_messages(
+ &mut socket_tx,
+ &[r#"{"id":5,"method":"Debugger.resume"}"#],
+ &mut socket_rx,
+ &[r#"{"id":5,"result":{}}"#],
+ &[],
+ )
+ .await;
+
+ assert!(&stdout_lines
+ .next()
+ .unwrap()
+ .starts_with("running 1 test from"));
+ assert!(&stdout_lines
+ .next()
+ .unwrap()
+ .contains("test has finished running"));
child.kill().unwrap();
child.wait().unwrap();