|
| 1 | +# frozen_string_literal: true |
| 2 | + |
| 3 | +require_relative '../support/console_test_case' |
| 4 | +require 'debug/session' |
| 5 | +require 'debug/server' |
| 6 | + |
| 7 | +module DEBUGGER__ |
| 8 | + class ProcRegexInitTest < ConsoleTestCase |
| 9 | + def teardown |
| 10 | + super |
| 11 | + CONFIG[:proc_regex] = nil |
| 12 | + end |
| 13 | + |
| 14 | + def test_invalid_regex_raises_argument_error |
| 15 | + CONFIG[:proc_regex] = '[invalid' |
| 16 | + CONFIG[:port] = 0 |
| 17 | + |
| 18 | + assert_raise_message(/Invalid RUBY_DEBUG_PROC_REGEX/) do |
| 19 | + UI_TcpServer.new |
| 20 | + end |
| 21 | + end |
| 22 | + |
| 23 | + def test_valid_regex_compiles_at_initialize |
| 24 | + CONFIG[:proc_regex] = 'worker.*' |
| 25 | + server = UI_TcpServer.new(port: 0) |
| 26 | + compiled = server.instance_variable_get(:@proc_regex) |
| 27 | + |
| 28 | + assert_kind_of Regexp, compiled |
| 29 | + assert_equal(/worker.*/, compiled) |
| 30 | + end |
| 31 | + |
| 32 | + def test_no_proc_regex_leaves_attribute_nil |
| 33 | + CONFIG[:proc_regex] = nil |
| 34 | + server = UI_TcpServer.new(port: 0) |
| 35 | + assert_nil server.instance_variable_get(:@proc_regex) |
| 36 | + end |
| 37 | + end |
| 38 | + |
| 39 | + class ProcRegexRemoteTest < ConsoleTestCase |
| 40 | + def program |
| 41 | + <<~RUBY |
| 42 | + 1| a = 1 |
| 43 | + 2| b = 2 |
| 44 | + RUBY |
| 45 | + end |
| 46 | + |
| 47 | + # When $0 matches the regex, the TCP port is opened normally and the |
| 48 | + # debugger logs that the process matched. |
| 49 | + def test_port_opens_when_proc_matches |
| 50 | + omit "no remote tests" if NO_REMOTE |
| 51 | + |
| 52 | + write_temp_file(strip_line_num(program)) |
| 53 | + basename = Regexp.escape(File.basename(temp_file_path)) |
| 54 | + cmd = "#{RDBG_EXECUTABLE} -O --port=0 --proc-regex=#{basename} -- #{temp_file_path}" |
| 55 | + |
| 56 | + remote_info = setup_remote_debuggee(cmd) |
| 57 | + assert remote_info.debuggee_backlog.any? { |l| l.include?('matches') && l.include?(File.basename(temp_file_path)) }, |
| 58 | + "expected match log, got: #{remote_info.debuggee_backlog.inspect}" |
| 59 | + assert remote_info.debuggee_backlog.any? { |l| l =~ /Debugger can attach via TCP\/IP/ }, |
| 60 | + "expected port-open log, got: #{remote_info.debuggee_backlog.inspect}" |
| 61 | + ensure |
| 62 | + kill_safely(remote_info.pid, force: true) if remote_info |
| 63 | + remote_info&.reader_thread&.kill |
| 64 | + remote_info&.r&.close |
| 65 | + remote_info&.w&.close |
| 66 | + end |
| 67 | + |
| 68 | + # When $0 does not match the regex, the listener returns silently without |
| 69 | + # opening the port. With --nonstop (no initial-suspend breakpoint), the |
| 70 | + # program then runs to completion unaffected by the debugger. |
| 71 | + def test_port_skipped_when_proc_does_not_match |
| 72 | + omit "no remote tests" if NO_REMOTE |
| 73 | + |
| 74 | + program_with_print = <<~RUBY |
| 75 | + puts "PROC_REGEX_TEST_DONE" |
| 76 | + RUBY |
| 77 | + write_temp_file(program_with_print) |
| 78 | + |
| 79 | + cmd = "#{RDBG_EXECUTABLE} -O --nonstop --port=0 --proc-regex=__NEVER_MATCHES_XYZ__ -- #{temp_file_path}" |
| 80 | + backlog = [] |
| 81 | + r, _w, pid = PTY.spawn(cmd) |
| 82 | + |
| 83 | + Timeout.timeout(TIMEOUT_SEC) do |
| 84 | + while line = r.gets |
| 85 | + backlog << line |
| 86 | + break if line.include?('PROC_REGEX_TEST_DONE') |
| 87 | + end |
| 88 | + end |
| 89 | + |
| 90 | + assert backlog.any? { |l| l.include?('does not match') && l.include?('skipping port') }, |
| 91 | + "expected skip log, got: #{backlog.inspect}" |
| 92 | + assert backlog.any? { |l| l.include?('PROC_REGEX_TEST_DONE') }, |
| 93 | + "program should have run to completion, got: #{backlog.inspect}" |
| 94 | + refute backlog.any? { |l| l =~ /Debugger can attach via TCP\/IP/ }, |
| 95 | + "port should not have been opened, got: #{backlog.inspect}" |
| 96 | + rescue Errno::EIO |
| 97 | + # PTY closed: program already exited |
| 98 | + ensure |
| 99 | + Process.kill(:TERM, pid) if pid rescue nil |
| 100 | + Process.waitpid(pid) if pid rescue nil |
| 101 | + r&.close |
| 102 | + end |
| 103 | + end |
| 104 | +end |
0 commit comments