diff --git a/gems/codetracer-pure-ruby-recorder/lib/trace.rb b/gems/codetracer-pure-ruby-recorder/lib/trace.rb index 88fb13f..60330bb 100644 --- a/gems/codetracer-pure-ruby-recorder/lib/trace.rb +++ b/gems/codetracer-pure-ruby-recorder/lib/trace.rb @@ -61,13 +61,23 @@ def self.trace_ruby_file(program, out_dir, program_args = []) Kernel.load(program) rescue Exception => e if tracer.debug - codetracer_original_puts '' - codetracer_original_puts '==== trace.rb error while tracing program ===' - codetracer_original_puts 'ERROR' - codetracer_original_puts e - codetracer_original_puts e.backtrace - codetracer_original_puts '=====================' - codetracer_original_puts '' + if Kernel.respond_to?(:codetracer_original_puts, true) + Kernel.codetracer_original_puts '' + Kernel.codetracer_original_puts '==== trace.rb error while tracing program ===' + Kernel.codetracer_original_puts 'ERROR' + Kernel.codetracer_original_puts e + Kernel.codetracer_original_puts e.backtrace + Kernel.codetracer_original_puts '=====================' + Kernel.codetracer_original_puts '' + else + puts '' + puts '==== trace.rb error while tracing program ===' + puts 'ERROR' + puts e + puts e.backtrace + puts '=====================' + puts '' + end end ensure # Restore original ARGV @@ -163,7 +173,11 @@ def record_call(tp) method_name_prefix = module_name == 'Object' ? '' : "#{module_name}#" method_name = "#{method_name_prefix}#{tp.method_id}" - codetracer_original_puts "call #{method_name} with #{tp.parameters}" if $tracer.debug + if @debug && Kernel.respond_to?(:codetracer_original_puts, true) + Kernel.codetracer_original_puts "call #{method_name} with #{tp.parameters}" + elsif @debug + puts "call #{method_name} with #{tp.parameters}" + end arg_records = prepare_args(tp) @@ -175,7 +189,11 @@ def record_call(tp) def record_return(tp) if self.tracks_call?(tp) - codetracer_original_puts "return" if $tracer.debug + if @debug && Kernel.respond_to?(:codetracer_original_puts, true) + Kernel.codetracer_original_puts 'return' + elsif @debug + puts 'return' + end return_value = to_value(tp.return_value) @record.register_step(tp.path, tp.lineno) # return value support inspired by existing IDE-s/envs like diff --git a/gems/codetracer-ruby-recorder/lib/native_trace.rb b/gems/codetracer-ruby-recorder/lib/native_trace.rb index 08c002f..59e0e16 100644 --- a/gems/codetracer-ruby-recorder/lib/native_trace.rb +++ b/gems/codetracer-ruby-recorder/lib/native_trace.rb @@ -120,7 +120,7 @@ def load_native_recorder .find { |path| File.exist?(path) } if alt_path begin - File.symlink(alt_path, target_path)path, target_path) + File.symlink(alt_path, target_path) rescue StandardError FileUtils.cp(alt_path, target_path) end @@ -128,7 +128,7 @@ def load_native_recorder end require target_path - @recorder = RubyRecorder.new + @recorder = CodeTracerNativeRecorder.new rescue Exception => e warn "native tracer unavailable: #{e}" @recorder = nil diff --git a/test/test_tracer.rb b/test/test_tracer.rb index f3bc7db..1b8d578 100644 --- a/test/test_tracer.rb +++ b/test/test_tracer.rb @@ -32,6 +32,24 @@ def run_trace(tracer_script, program_name, *args) end end + def run_trace_with_separator(tracer_script, program_name, *args) + base = File.basename(program_name, '.rb') + tracer_name = tracer_script.include?('native') ? 'native' : 'pure' + Dir.chdir(File.expand_path('..', __dir__)) do + program = File.join('test', 'programs', program_name) + out_dir = File.join('test', 'tmp', "#{base}_dashdash", tracer_name) + FileUtils.mkdir_p(out_dir) + stdout, stderr, status = Open3.capture3( + RbConfig.ruby, tracer_script, '--out-dir', out_dir, '--', program, *args + ) + raise "trace failed: #{stderr}" unless status.success? + trace_file = File.join(out_dir, 'trace.json') + trace = JSON.parse(File.read(trace_file)) if File.exist?(trace_file) + program_out = stdout.lines.reject { |l| l.start_with?('call ') || l.start_with?('return') }.join + [trace, program_out] + end + end + def expected_output(program_name) base = File.basename(program_name, '.rb') fixture = File.join(FIXTURE_DIR, "#{base}_output.txt") @@ -63,6 +81,19 @@ def program_args(base) end end + def test_args_sum_with_separator + base = 'args_sum' + pure_trace, pure_out = run_trace_with_separator('gems/codetracer-pure-ruby-recorder/bin/codetracer-pure-ruby-recorder', "#{base}.rb", *program_args(base)) + native_trace, native_out = run_trace_with_separator('gems/codetracer-ruby-recorder/bin/codetracer-ruby-recorder', "#{base}.rb", *program_args(base)) + + expected = expected_trace("#{base}.rb") + assert_equal expected, pure_trace + assert_equal expected, native_trace + expected = expected_output("#{base}.rb") + assert_equal expected, pure_out + assert_equal expected, native_out + end + def run_gem_installation_test(gem_bin, gem_module) Dir.chdir(File.expand_path('..', __dir__)) do gem_dir = File.join('gems', gem_bin) @@ -92,15 +123,22 @@ def run_gem_installation_test(gem_bin, gem_module) out_dir_lib = File.join('test', 'tmp', "gem_install_#{gem_bin.tr('-', '_')}_lib") FileUtils.rm_rf(out_dir_lib) + if gem_bin == 'codetracer-ruby-recorder' + class_name = 'CodeTracer::RubyRecorder' + init_args = '' + else + class_name = 'Codetracer::PureRubyRecorder' + init_args = '$codetracer_record' + end script = <<~RUBY require '#{gem_module}' - recorder = RubyRecorder.new + recorder = Object.const_get("#{class_name}").new(#{init_args}) puts 'start trace' - recorder.disable_tracing + recorder.deactivate puts 'this will not be traced' - recorder.enable_tracing + recorder.activate puts 'this will be traced' - recorder.disable_tracing + recorder.deactivate puts 'tracing disabled' recorder.flush_trace('#{out_dir_lib}') RUBY @@ -121,11 +159,11 @@ def run_gem_installation_test(gem_bin, gem_module) end def test_gem_installation - run_gem_installation_test('codetracer-ruby-recorder', 'codetracer_ruby_recorder') + run_gem_installation_test('codetracer-ruby-recorder', 'native_trace') end def test_pure_gem_installation - run_gem_installation_test('codetracer-pure-ruby-recorder', 'codetracer_pure_ruby_recorder') + run_gem_installation_test('codetracer-pure-ruby-recorder', 'trace') end def test_pure_debug_smoke