2021-06-27 13:27:36 -04:00
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
use deno_core ::futures ;
use deno_core ::futures ::prelude ::* ;
use deno_core ::serde_json ;
use deno_core ::url ;
use deno_runtime ::deno_fetch ::reqwest ;
use deno_runtime ::deno_websocket ::tokio_tungstenite ;
use std ::io ::BufRead ;
use test_util as util ;
fn inspect_flag_with_unique_port ( flag_prefix : & str ) -> String {
use std ::sync ::atomic ::{ AtomicU16 , Ordering } ;
static PORT : AtomicU16 = AtomicU16 ::new ( 9229 ) ;
let port = PORT . fetch_add ( 1 , Ordering ::Relaxed ) ;
format! ( " {} =127.0.0.1: {} " , flag_prefix , port )
}
fn extract_ws_url_from_stderr (
stderr_lines : & mut impl std ::iter ::Iterator < Item = String > ,
) -> url ::Url {
let stderr_first_line = stderr_lines . next ( ) . unwrap ( ) ;
assert! ( stderr_first_line . starts_with ( " Debugger listening on " ) ) ;
let v : Vec < _ > = stderr_first_line . match_indices ( " ws: " ) . collect ( ) ;
assert_eq! ( v . len ( ) , 1 ) ;
let ws_url_index = v [ 0 ] . 0 ;
let ws_url = & stderr_first_line [ ws_url_index .. ] ;
url ::Url ::parse ( ws_url ) . unwrap ( )
}
#[ tokio::test ]
async fn inspector_connect ( ) {
2021-08-11 10:20:47 -04:00
let script = util ::testdata_path ( ) . join ( " inspector1.js " ) ;
2021-06-27 13:27:36 -04:00
let mut child = util ::deno_cmd ( )
. arg ( " run " )
. arg ( inspect_flag_with_unique_port ( " --inspect " ) )
. arg ( script )
. stderr ( std ::process ::Stdio ::piped ( ) )
. spawn ( )
. unwrap ( ) ;
let stderr = child . stderr . as_mut ( ) . unwrap ( ) ;
let mut stderr_lines =
std ::io ::BufReader ::new ( stderr ) . lines ( ) . map ( | r | r . unwrap ( ) ) ;
let ws_url = extract_ws_url_from_stderr ( & mut stderr_lines ) ;
// We use tokio_tungstenite as a websocket client because warp (which is
// a dependency of Deno) uses it.
let ( _socket , response ) = tokio_tungstenite ::connect_async ( ws_url )
. await
. expect ( " Can't connect " ) ;
assert_eq! ( " 101 Switching Protocols " , response . status ( ) . to_string ( ) ) ;
child . kill ( ) . unwrap ( ) ;
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 ( ) {
2021-08-11 10:20:47 -04:00
let script = util ::testdata_path ( ) . join ( " inspector2.js " ) ;
2021-06-27 13:27:36 -04:00
let mut child = util ::deno_cmd ( )
. arg ( " run " )
. arg ( inspect_flag_with_unique_port ( " --inspect-brk " ) )
. arg ( script )
. stdout ( std ::process ::Stdio ::piped ( ) )
. stderr ( std ::process ::Stdio ::piped ( ) )
. spawn ( )
. unwrap ( ) ;
let stderr = child . stderr . as_mut ( ) . unwrap ( ) ;
let mut stderr_lines =
std ::io ::BufReader ::new ( stderr ) . lines ( ) . map ( | r | r . unwrap ( ) ) ;
let ws_url = extract_ws_url_from_stderr ( & mut stderr_lines ) ;
let ( socket , response ) = tokio_tungstenite ::connect_async ( ws_url )
. await
. expect ( " Can't connect " ) ;
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 pass = ! msg . starts_with ( r # "{"method":"Debugger.scriptParsed","# ) ;
futures ::future ::ready ( pass )
} ) ;
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! [
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":"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 {
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 ( ) ,
_ = > unreachable! ( ) ,
}
}
child . kill ( ) . unwrap ( ) ;
child . wait ( ) . unwrap ( ) ;
}
#[ tokio::test ]
async fn inspector_pause ( ) {
2021-08-11 10:20:47 -04:00
let script = util ::testdata_path ( ) . join ( " inspector1.js " ) ;
2021-06-27 13:27:36 -04:00
let mut child = util ::deno_cmd ( )
. arg ( " run " )
. arg ( inspect_flag_with_unique_port ( " --inspect " ) )
. arg ( script )
. stderr ( std ::process ::Stdio ::piped ( ) )
. spawn ( )
. unwrap ( ) ;
let stderr = child . stderr . as_mut ( ) . unwrap ( ) ;
let mut stderr_lines =
std ::io ::BufReader ::new ( stderr ) . lines ( ) . map ( | r | r . unwrap ( ) ) ;
let ws_url = extract_ws_url_from_stderr ( & mut stderr_lines ) ;
// We use tokio_tungstenite as a websocket client because warp (which is
// a dependency of Deno) uses it.
let ( mut socket , _ ) = tokio_tungstenite ::connect_async ( ws_url )
. await
. expect ( " Can't connect " ) ;
/// Returns the next websocket message as a string ignoring
/// Debugger.scriptParsed messages.
async fn ws_read_msg (
socket : & mut tokio_tungstenite ::WebSocketStream <
tokio_tungstenite ::MaybeTlsStream < tokio ::net ::TcpStream > ,
> ,
) -> String {
use deno_core ::futures ::stream ::StreamExt ;
while let Some ( msg ) = socket . next ( ) . await {
let msg = msg . unwrap ( ) . to_string ( ) ;
// FIXME(bartlomieju): fails because there's a file loaded
// called 150_errors.js
// assert!(!msg.contains("error"));
if ! msg . contains ( " Debugger.scriptParsed " ) {
return msg ;
}
}
unreachable! ( )
}
socket
. send ( r # "{"id":6,"method":"Debugger.enable"}"# . into ( ) )
. await
. unwrap ( ) ;
let msg = ws_read_msg ( & mut socket ) . await ;
println! ( " response msg 1 {} " , msg ) ;
assert! ( msg . starts_with ( r # "{"id":6,"result":{"debuggerId":"# ) ) ;
socket
. send ( r # "{"id":31,"method":"Debugger.pause"}"# . into ( ) )
. await
. unwrap ( ) ;
let msg = ws_read_msg ( & mut socket ) . await ;
println! ( " response msg 2 {} " , msg ) ;
assert_eq! ( msg , r # "{"id":31,"result":{}}"# ) ;
child . kill ( ) . unwrap ( ) ;
}
#[ tokio::test ]
async fn inspector_port_collision ( ) {
// Skip this test on WSL, which allows multiple processes to listen on the
// same port, rather than making `bind()` fail with `EADDRINUSE`.
if cfg! ( target_os = " linux " ) & & std ::env ::var_os ( " WSL_DISTRO_NAME " ) . is_some ( )
{
return ;
}
2021-08-11 10:20:47 -04:00
let script = util ::testdata_path ( ) . join ( " inspector1.js " ) ;
2021-06-27 13:27:36 -04:00
let inspect_flag = inspect_flag_with_unique_port ( " --inspect " ) ;
let mut child1 = util ::deno_cmd ( )
. arg ( " run " )
. arg ( & inspect_flag )
. arg ( script . clone ( ) )
. stderr ( std ::process ::Stdio ::piped ( ) )
. spawn ( )
. unwrap ( ) ;
let stderr_1 = child1 . stderr . as_mut ( ) . unwrap ( ) ;
let mut stderr_1_lines = std ::io ::BufReader ::new ( stderr_1 )
. lines ( )
. map ( | r | r . unwrap ( ) ) ;
let _ = extract_ws_url_from_stderr ( & mut stderr_1_lines ) ;
let mut child2 = util ::deno_cmd ( )
. arg ( " run " )
. arg ( & inspect_flag )
. arg ( script )
. stderr ( std ::process ::Stdio ::piped ( ) )
. spawn ( )
. unwrap ( ) ;
let stderr_2 = child2 . stderr . as_mut ( ) . unwrap ( ) ;
let stderr_2_error_message = std ::io ::BufReader ::new ( stderr_2 )
. lines ( )
. map ( | r | r . unwrap ( ) )
. inspect ( | line | assert! ( ! line . contains ( " Debugger listening " ) ) )
. find ( | line | line . contains ( " Cannot start inspector server " ) ) ;
assert! ( stderr_2_error_message . is_some ( ) ) ;
child1 . kill ( ) . unwrap ( ) ;
child1 . wait ( ) . unwrap ( ) ;
child2 . wait ( ) . unwrap ( ) ;
}
#[ tokio::test ]
async fn inspector_does_not_hang ( ) {
2021-08-11 10:20:47 -04:00
let script = util ::testdata_path ( ) . join ( " inspector3.js " ) ;
2021-06-27 13:27:36 -04:00
let mut child = util ::deno_cmd ( )
. arg ( " run " )
. arg ( inspect_flag_with_unique_port ( " --inspect-brk " ) )
. env ( " NO_COLOR " , " 1 " )
. arg ( script )
. stdout ( std ::process ::Stdio ::piped ( ) )
. stderr ( std ::process ::Stdio ::piped ( ) )
. spawn ( )
. unwrap ( ) ;
let stderr = child . stderr . as_mut ( ) . unwrap ( ) ;
let mut stderr_lines =
std ::io ::BufReader ::new ( stderr ) . lines ( ) . map ( | r | r . unwrap ( ) ) ;
let ws_url = extract_ws_url_from_stderr ( & mut stderr_lines ) ;
let ( socket , response ) = tokio_tungstenite ::connect_async ( ws_url )
. await
. expect ( " Can't connect " ) ;
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 pass = ! msg . starts_with ( r # "{"method":"Debugger.scriptParsed","# ) ;
futures ::future ::ready ( pass )
} ) ;
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! [
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 {
WsRecv ( s ) = > assert! ( socket_rx . next ( ) . await . unwrap ( ) . starts_with ( s ) ) ,
WsSend ( s ) = > socket_tx . send ( s . into ( ) ) . await . unwrap ( ) ,
_ = > unreachable! ( ) ,
}
}
for i in 0 .. 128 u32 {
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 ) ;
}
// Check that we can gracefully close the websocket connection.
socket_tx . close ( ) . await . unwrap ( ) ;
socket_rx . for_each ( | _ | async { } ) . await ;
assert_eq! ( & stdout_lines . next ( ) . unwrap ( ) , " done " ) ;
assert! ( child . wait ( ) . unwrap ( ) . success ( ) ) ;
}
#[ tokio::test ]
async fn inspector_without_brk_runs_code ( ) {
2021-08-11 10:20:47 -04:00
let script = util ::testdata_path ( ) . join ( " inspector4.js " ) ;
2021-06-27 13:27:36 -04:00
let mut child = util ::deno_cmd ( )
. arg ( " run " )
. arg ( inspect_flag_with_unique_port ( " --inspect " ) )
. arg ( script )
. stdout ( std ::process ::Stdio ::piped ( ) )
. stderr ( std ::process ::Stdio ::piped ( ) )
. spawn ( )
. unwrap ( ) ;
let stderr = child . stderr . as_mut ( ) . unwrap ( ) ;
let mut stderr_lines =
std ::io ::BufReader ::new ( stderr ) . lines ( ) . map ( | r | r . unwrap ( ) ) ;
let _ = extract_ws_url_from_stderr ( & mut stderr_lines ) ;
// Check that inspector actually runs code without waiting for inspector
// connection.
let stdout = child . stdout . as_mut ( ) . unwrap ( ) ;
let mut stdout_lines =
std ::io ::BufReader ::new ( stdout ) . lines ( ) . map ( | r | r . unwrap ( ) ) ;
let stdout_first_line = stdout_lines . next ( ) . unwrap ( ) ;
assert_eq! ( stdout_first_line , " hello " ) ;
child . kill ( ) . unwrap ( ) ;
child . wait ( ) . unwrap ( ) ;
}
#[ tokio::test ]
async fn inspector_runtime_evaluate_does_not_crash ( ) {
let mut child = util ::deno_cmd ( )
. arg ( " repl " )
. arg ( inspect_flag_with_unique_port ( " --inspect " ) )
. stdin ( std ::process ::Stdio ::piped ( ) )
. stdout ( std ::process ::Stdio ::piped ( ) )
. stderr ( std ::process ::Stdio ::piped ( ) )
. spawn ( )
. unwrap ( ) ;
let stderr = child . stderr . as_mut ( ) . unwrap ( ) ;
let mut stderr_lines = std ::io ::BufReader ::new ( stderr )
. lines ( )
. map ( | r | r . unwrap ( ) )
. filter ( | s | s . as_str ( ) ! = " Debugger session started. " ) ;
let ws_url = extract_ws_url_from_stderr ( & mut stderr_lines ) ;
let ( socket , response ) = tokio_tungstenite ::connect_async ( ws_url )
. await
. expect ( " Can't connect " ) ;
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 pass = ! msg . starts_with ( r # "{"method":"Debugger.scriptParsed","# ) ;
futures ::future ::ready ( pass )
} ) ;
let stdin = child . stdin . take ( ) . unwrap ( ) ;
let stdout = child . stdout . as_mut ( ) . unwrap ( ) ;
let mut stdout_lines = std ::io ::BufReader ::new ( stdout )
. lines ( )
. map ( | r | r . unwrap ( ) )
. filter ( | s | ! s . starts_with ( " Deno " ) ) ;
use TestStep ::* ;
let test_steps = vec! [
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":{}}"# ) ,
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 ( ) ,
}
}
drop ( stdin ) ;
child . wait ( ) . unwrap ( ) ;
}
#[ tokio::test ]
async fn inspector_json ( ) {
2021-08-11 10:20:47 -04:00
let script = util ::testdata_path ( ) . join ( " inspector1.js " ) ;
2021-06-27 13:27:36 -04:00
let mut child = util ::deno_cmd ( )
. arg ( " run " )
. arg ( inspect_flag_with_unique_port ( " --inspect " ) )
. arg ( script )
. stderr ( std ::process ::Stdio ::piped ( ) )
. spawn ( )
. unwrap ( ) ;
let stderr = child . stderr . as_mut ( ) . unwrap ( ) ;
let mut stderr_lines =
std ::io ::BufReader ::new ( stderr ) . lines ( ) . map ( | r | r . unwrap ( ) ) ;
let ws_url = extract_ws_url_from_stderr ( & mut stderr_lines ) ;
let mut url = ws_url . clone ( ) ;
let _ = url . set_scheme ( " http " ) ;
url . set_path ( " /json " ) ;
let resp = reqwest ::get ( url ) . await . unwrap ( ) ;
assert_eq! ( resp . status ( ) , reqwest ::StatusCode ::OK ) ;
let endpoint_list : Vec < deno_core ::serde_json ::Value > =
serde_json ::from_str ( & resp . text ( ) . await . unwrap ( ) ) . unwrap ( ) ;
let matching_endpoint = endpoint_list
. iter ( )
. find ( | e | e [ " webSocketDebuggerUrl " ] = = ws_url . as_str ( ) ) ;
assert! ( matching_endpoint . is_some ( ) ) ;
child . kill ( ) . unwrap ( ) ;
}
#[ tokio::test ]
async fn inspector_json_list ( ) {
2021-08-11 10:20:47 -04:00
let script = util ::testdata_path ( ) . join ( " inspector1.js " ) ;
2021-06-27 13:27:36 -04:00
let mut child = util ::deno_cmd ( )
. arg ( " run " )
. arg ( inspect_flag_with_unique_port ( " --inspect " ) )
. arg ( script )
. stderr ( std ::process ::Stdio ::piped ( ) )
. spawn ( )
. unwrap ( ) ;
let stderr = child . stderr . as_mut ( ) . unwrap ( ) ;
let mut stderr_lines =
std ::io ::BufReader ::new ( stderr ) . lines ( ) . map ( | r | r . unwrap ( ) ) ;
let ws_url = extract_ws_url_from_stderr ( & mut stderr_lines ) ;
let mut url = ws_url . clone ( ) ;
let _ = url . set_scheme ( " http " ) ;
url . set_path ( " /json/list " ) ;
let resp = reqwest ::get ( url ) . await . unwrap ( ) ;
assert_eq! ( resp . status ( ) , reqwest ::StatusCode ::OK ) ;
let endpoint_list : Vec < deno_core ::serde_json ::Value > =
serde_json ::from_str ( & resp . text ( ) . await . unwrap ( ) ) . unwrap ( ) ;
let matching_endpoint = endpoint_list
. iter ( )
. find ( | e | e [ " webSocketDebuggerUrl " ] = = ws_url . as_str ( ) ) ;
assert! ( matching_endpoint . is_some ( ) ) ;
child . kill ( ) . unwrap ( ) ;
}
2021-07-20 09:41:36 -04:00
#[ tokio::test ]
async fn inspector_connect_non_ws ( ) {
// https://github.com/denoland/deno/issues/11449
// Verify we don't panic if non-WS connection is being established
2021-08-11 10:20:47 -04:00
let script = util ::testdata_path ( ) . join ( " inspector1.js " ) ;
2021-07-20 09:41:36 -04:00
let mut child = util ::deno_cmd ( )
. arg ( " run " )
. arg ( inspect_flag_with_unique_port ( " --inspect " ) )
. arg ( script )
. stderr ( std ::process ::Stdio ::piped ( ) )
. spawn ( )
. unwrap ( ) ;
let stderr = child . stderr . as_mut ( ) . unwrap ( ) ;
let mut stderr_lines =
std ::io ::BufReader ::new ( stderr ) . lines ( ) . map ( | r | r . unwrap ( ) ) ;
let mut ws_url = extract_ws_url_from_stderr ( & mut stderr_lines ) ;
// Change scheme to URL and try send a request. We're not interested
// in the request result, just that the process doesn't panic.
ws_url . set_scheme ( " http " ) . unwrap ( ) ;
let resp = reqwest ::get ( ws_url ) . await . unwrap ( ) ;
assert_eq! ( " 400 Bad Request " , resp . status ( ) . to_string ( ) ) ;
child . kill ( ) . unwrap ( ) ;
child . wait ( ) . unwrap ( ) ;
}
2021-12-15 18:38:27 -05:00
#[ tokio::test ]
async fn inspector_break_on_first_line_in_test ( ) {
let script = util ::testdata_path ( ) . join ( " inspector_test.js " ) ;
let mut child = util ::deno_cmd ( )
. arg ( " test " )
. arg ( inspect_flag_with_unique_port ( " --inspect-brk " ) )
. arg ( script )
. stdout ( std ::process ::Stdio ::piped ( ) )
. stderr ( std ::process ::Stdio ::piped ( ) )
. spawn ( )
. unwrap ( ) ;
let stderr = child . stderr . as_mut ( ) . unwrap ( ) ;
let mut stderr_lines =
std ::io ::BufReader ::new ( stderr ) . lines ( ) . map ( | r | r . unwrap ( ) ) ;
let ws_url = extract_ws_url_from_stderr ( & mut stderr_lines ) ;
let ( socket , response ) = tokio_tungstenite ::connect_async ( ws_url )
. await
. expect ( " Can't connect " ) ;
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 pass = ! msg . starts_with ( r # "{"method":"Debugger.scriptParsed","# ) ;
futures ::future ::ready ( pass )
} ) ;
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! [
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":"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
) ,
WsRecv ( s ) = > assert! ( socket_rx . next ( ) . await . unwrap ( ) . starts_with ( s ) ) ,
WsSend ( s ) = > socket_tx . send ( s . into ( ) ) . await . unwrap ( ) ,
_ = > unreachable! ( ) ,
}
}
child . kill ( ) . unwrap ( ) ;
child . wait ( ) . unwrap ( ) ;
}