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 ::* ;
2021-12-30 10:47:58 -05:00
use deno_core ::futures ::stream ::SplitSink ;
2021-06-27 13:27:36 -04:00
use deno_core ::serde_json ;
use deno_core ::url ;
use deno_runtime ::deno_fetch ::reqwest ;
use deno_runtime ::deno_websocket ::tokio_tungstenite ;
2021-12-30 10:47:58 -05:00
use deno_runtime ::deno_websocket ::tokio_tungstenite ::tungstenite ;
2021-06-27 13:27:36 -04:00
use std ::io ::BufRead ;
2021-12-30 10:47:58 -05:00
use std ::pin ::Pin ;
2021-06-27 13:27:36 -04:00
use test_util as util ;
2021-12-30 10:47:58 -05:00
use tokio ::net ::TcpStream ;
2021-06-27 13:27:36 -04:00
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 ( )
}
2021-12-30 10:47:58 -05:00
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 ;
}
}
}
2021-06-27 13:27:36 -04:00
#[ 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 ( ) ;
}
#[ 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 ( ) ;
2021-12-30 10:47:58 -05:00
let mut socket_rx = socket_rx
. map ( | msg | msg . unwrap ( ) . to_string ( ) )
. filter ( | msg | {
2021-06-27 13:27:36 -04:00
let pass = ! msg . starts_with ( r # "{"method":"Debugger.scriptParsed","# ) ;
futures ::future ::ready ( pass )
2021-12-30 10:47:58 -05:00
} )
. boxed_local ( ) ;
2021-06-27 13:27:36 -04:00
let stdout = child . stdout . as_mut ( ) . unwrap ( ) ;
let mut stdout_lines =
std ::io ::BufReader ::new ( stdout ) . lines ( ) . map ( | r | r . unwrap ( ) ) ;
2021-12-30 10:47:58 -05:00
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":"# ,
] ,
& [
2021-06-27 13:27:36 -04:00
r # "{"method":"Runtime.executionContextCreated","params":{"context":{"id":1,"# ,
2021-12-30 10:47:58 -05:00
] ,
)
. 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 ,
& [
2021-06-27 13:27:36 -04:00
r # "{"id":4,"method":"Runtime.evaluate","params":{"expression":"Deno.core.print(\"hello from the inspector\\n\")","contextId":1,"includeCommandLineAPI":true,"silent":false,"returnByValue":true}}"# ,
2021-12-30 10:47:58 -05:00
] ,
& 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 " ) ;
2021-06-27 13:27:36 -04:00
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 ( ) ;
2021-12-30 10:47:58 -05:00
let mut socket_rx = socket_rx
. map ( | msg | msg . unwrap ( ) . to_string ( ) )
. filter ( | msg | {
2021-06-27 13:27:36 -04:00
let pass = ! msg . starts_with ( r # "{"method":"Debugger.scriptParsed","# ) ;
futures ::future ::ready ( pass )
2021-12-30 10:47:58 -05:00
} )
. boxed_local ( ) ;
2021-06-27 13:27:36 -04:00
let stdout = child . stdout . as_mut ( ) . unwrap ( ) ;
let mut stdout_lines =
std ::io ::BufReader ::new ( stdout ) . lines ( ) . map ( | r | r . unwrap ( ) ) ;
2021-12-30 10:47:58 -05:00
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 ;
2021-06-27 13:27:36 -04:00
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 ) ;
2021-12-30 10:47:58 -05:00
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 ;
2021-06-27 13:27:36 -04:00
}
// 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 ( ) ;
2021-12-30 10:47:58 -05:00
let mut socket_rx = socket_rx
. map ( | msg | msg . unwrap ( ) . to_string ( ) )
. filter ( | msg | {
2021-06-27 13:27:36 -04:00
let pass = ! msg . starts_with ( r # "{"method":"Debugger.scriptParsed","# ) ;
futures ::future ::ready ( pass )
2021-12-30 10:47:58 -05:00
} )
. boxed_local ( ) ;
2021-06-27 13:27:36 -04:00
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 " ) ) ;
2021-12-30 10:47:58 -05:00
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":"# ,
] ,
& [
2021-06-27 13:27:36 -04:00
r # "{"method":"Runtime.executionContextCreated","params":{"context":{"id":1,"# ,
2021-12-30 10:47:58 -05:00
] ,
)
. 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 " ) ;
2021-06-27 13:27:36 -04:00
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 ( ) ;
2021-12-30 10:47:58 -05:00
let mut socket_rx = socket_rx
. map ( | msg | msg . unwrap ( ) . to_string ( ) )
. filter ( | msg | {
2021-12-15 18:38:27 -05:00
let pass = ! msg . starts_with ( r # "{"method":"Debugger.scriptParsed","# ) ;
futures ::future ::ready ( pass )
2021-12-30 10:47:58 -05:00
} )
. boxed_local ( ) ;
2021-12-15 18:38:27 -05:00
let stdout = child . stdout . as_mut ( ) . unwrap ( ) ;
let mut stdout_lines =
std ::io ::BufReader ::new ( stdout ) . lines ( ) . map ( | r | r . unwrap ( ) ) ;
2021-12-30 10:47:58 -05:00
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":"# ,
] ,
& [
2021-12-15 18:38:27 -05:00
r # "{"method":"Runtime.executionContextCreated","params":{"context":{"id":1,"# ,
2021-12-30 10:47:58 -05:00
] ,
)
. 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 ,
& [
2021-12-15 18:38:27 -05:00
r # "{"id":4,"method":"Runtime.evaluate","params":{"expression":"Deno.core.print(\"hello from the inspector\\n\")","contextId":1,"includeCommandLineAPI":true,"silent":false,"returnByValue":true}}"# ,
2021-12-30 10:47:58 -05:00
] ,
& 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 " ) ) ;
2021-12-15 18:38:27 -05:00
child . kill ( ) . unwrap ( ) ;
child . wait ( ) . unwrap ( ) ;
}