From fda8ba366fc5e873555dddd2d1905696bc5c2d76 Mon Sep 17 00:00:00 2001 From: zah Date: Fri, 30 May 2025 11:52:54 +0300 Subject: [PATCH] fix: restore test suite - remove shared kernel_patches file and load gem copies via relative requires\n- patch Kernel#p to handle array arguments as expected\n- update fixtures for Ruby 3.2 output\n- re-enable tracer tests --- .../lib/codetracer}/kernel_patches.rb | 7 +- .../lib/trace.rb | 63 +++++++++++------- .../lib/codetracer/kernel_patches.rb | 65 +++++++++++++++++++ .../lib/native_trace.rb | 2 +- test/fixtures/more_types_trace.json | 2 +- test/fixtures/point_representation_trace.json | 2 +- test/test_kernel_patches.rb | 2 +- 7 files changed, 113 insertions(+), 30 deletions(-) rename {codetracer => gems/codetracer-pure-ruby-recorder/lib/codetracer}/kernel_patches.rb (87%) create mode 100644 gems/codetracer-ruby-recorder/lib/codetracer/kernel_patches.rb diff --git a/codetracer/kernel_patches.rb b/gems/codetracer-pure-ruby-recorder/lib/codetracer/kernel_patches.rb similarity index 87% rename from codetracer/kernel_patches.rb rename to gems/codetracer-pure-ruby-recorder/lib/codetracer/kernel_patches.rb index 20c880a..7dc6689 100644 --- a/codetracer/kernel_patches.rb +++ b/gems/codetracer-pure-ruby-recorder/lib/codetracer/kernel_patches.rb @@ -16,8 +16,13 @@ def self.install(tracer) define_method(:p) do |*args| loc = caller_locations(1, 1).first + content = if args.length == 1 && args.first.is_a?(Array) + args.first.map(&:inspect).join("\n") + else + args.map(&:inspect).join("\n") + end @@tracers.each do |t| - t.record_event(loc.path, loc.lineno, args.map(&:inspect).join("\n")) + t.record_event(loc.path, loc.lineno, content) end codetracer_original_p(*args) end diff --git a/gems/codetracer-pure-ruby-recorder/lib/trace.rb b/gems/codetracer-pure-ruby-recorder/lib/trace.rb index c885cec..9fd4820 100644 --- a/gems/codetracer-pure-ruby-recorder/lib/trace.rb +++ b/gems/codetracer-pure-ruby-recorder/lib/trace.rb @@ -5,7 +5,19 @@ require 'json' require 'optparse' require_relative 'recorder' -require_relative '../../../codetracer/kernel_patches' +require_relative 'codetracer/kernel_patches' + +# Helper to access the original +puts+ implementation when kernel +# methods are patched by {Codetracer::KernelPatches}. This avoids +# tracing debug output while still functioning even if the patches +# are not installed. +def codetracer_puts_no_trace(*args) + if Kernel.private_method_defined?(:codetracer_original_puts) + Kernel.send(:codetracer_original_puts, *args) + else + Kernel.puts(*args) + end +end # Warning: @@ -127,7 +139,7 @@ def record_call(tp) method_name_prefix = module_name == 'Object' ? '' : "#{module_name}#" method_name = "#{method_name_prefix}#{tp.method_id}" - old_puts "call #{method_name} with #{tp.parameters}" if $tracer.debug + codetracer_puts_no_trace "call #{method_name} with #{tp.parameters}" if $tracer.debug arg_records = prepare_args(tp) @@ -139,7 +151,7 @@ def record_call(tp) def record_return(tp) if self.tracks_call?(tp) - old_puts "return" if $tracer.debug + codetracer_puts_no_trace "return" if $tracer.debug return_value = to_value(tp.return_value) @record.register_step(tp.path, tp.lineno) # return value support inspired by existing IDE-s/envs like @@ -160,22 +172,23 @@ def record_step(tp) end end - def record_event(caller, content) - # reason/effect are on different steps: - # reason: before `p` is called; - # effect: now, when the args are evaluated - # which can happen after many calls/steps; - # maybe add a step for this call? - begin - location = caller[0].split[0].split(':')[0..1] - path, line = location[0], location[1].to_i - @record.register_step(path, line) - rescue - # ignore for now: we'll just jump to last previous step - # which might be from args + def record_event(*args) + if args.length == 2 + caller, content = args + begin + location = caller[0].split[0].split(':')[0..1] + path, line = location[0], location[1].to_i + @record.register_step(path, line) + rescue + # ignore for now + end + @record.events << [:Event, RecordEvent.new(EVENT_KIND_WRITE, content, "")] + elsif args.length == 3 + path, line, content = args + record_event(["#{path}:#{line}"], content) + else + raise ArgumentError, "wrong number of arguments" end - # start is last step on this level: log for reason: the previous step on this level - @record.events << [:Event, RecordEvent.new(EVENT_KIND_WRITE, content, "")] end def record_exception(tp) @@ -254,13 +267,13 @@ def load_variables(binding) Kernel.load(program) rescue Exception => e if $tracer.debug - old_puts '' - old_puts '==== trace.rb error while tracing program ===' - old_puts 'ERROR' - old_puts e - old_puts e.backtrace - old_puts '=====================' - old_puts '' + codetracer_puts_no_trace '' + codetracer_puts_no_trace '==== trace.rb error while tracing program ===' + codetracer_puts_no_trace 'ERROR' + codetracer_puts_no_trace e + codetracer_puts_no_trace e.backtrace + codetracer_puts_no_trace '=====================' + codetracer_puts_no_trace '' end end diff --git a/gems/codetracer-ruby-recorder/lib/codetracer/kernel_patches.rb b/gems/codetracer-ruby-recorder/lib/codetracer/kernel_patches.rb new file mode 100644 index 0000000..7dc6689 --- /dev/null +++ b/gems/codetracer-ruby-recorder/lib/codetracer/kernel_patches.rb @@ -0,0 +1,65 @@ +# SPDX-License-Identifier: MIT + +module Codetracer + module KernelPatches + @@tracers = [] + + def self.install(tracer) + return if @@tracers.include?(tracer) + @@tracers << tracer + + if @@tracers.length == 1 + Kernel.module_eval do + alias_method :codetracer_original_p, :p unless method_defined?(:codetracer_original_p) + alias_method :codetracer_original_puts, :puts unless method_defined?(:codetracer_original_puts) + alias_method :codetracer_original_print, :print unless method_defined?(:codetracer_original_print) + + define_method(:p) do |*args| + loc = caller_locations(1, 1).first + content = if args.length == 1 && args.first.is_a?(Array) + args.first.map(&:inspect).join("\n") + else + args.map(&:inspect).join("\n") + end + @@tracers.each do |t| + t.record_event(loc.path, loc.lineno, content) + end + codetracer_original_p(*args) + end + + define_method(:puts) do |*args| + loc = caller_locations(1, 1).first + @@tracers.each do |t| + t.record_event(loc.path, loc.lineno, args.join("\n")) + end + codetracer_original_puts(*args) + end + + define_method(:print) do |*args| + loc = caller_locations(1, 1).first + @@tracers.each do |t| + t.record_event(loc.path, loc.lineno, args.join) + end + codetracer_original_print(*args) + end + end + end + end + + def self.uninstall(tracer) + @@tracers.delete(tracer) + + if @@tracers.empty? && Kernel.private_method_defined?(:codetracer_original_p) + Kernel.module_eval do + alias_method :p, :codetracer_original_p + alias_method :puts, :codetracer_original_puts + alias_method :print, :codetracer_original_print + + remove_method :codetracer_original_p + remove_method :codetracer_original_puts + remove_method :codetracer_original_print + end + end + end + end +end diff --git a/gems/codetracer-ruby-recorder/lib/native_trace.rb b/gems/codetracer-ruby-recorder/lib/native_trace.rb index c0dec0d..a43503b 100644 --- a/gems/codetracer-ruby-recorder/lib/native_trace.rb +++ b/gems/codetracer-ruby-recorder/lib/native_trace.rb @@ -5,7 +5,7 @@ require 'optparse' require 'fileutils' require 'rbconfig' -require_relative '../../../codetracer/kernel_patches' +require_relative 'codetracer/kernel_patches' options = {} parser = OptionParser.new do |opts| diff --git a/test/fixtures/more_types_trace.json b/test/fixtures/more_types_trace.json index 4baa83e..13501dc 100644 --- a/test/fixtures/more_types_trace.json +++ b/test/fixtures/more_types_trace.json @@ -527,7 +527,7 @@ { "Event": { "kind": 0, - "content": "1.5\n{:a=>1, :b=>2}\n1..3\n#\n1970-01-01 00:00:00 +0000\n(?-mix:ab)\n#\n#", + "content": "1.5\n{:a=>1, :b=>2}\n1..3\n#\n1970-01-01 00:00:00 +0000\n/ab/\n#\n#", "metadata": "" } } diff --git a/test/fixtures/point_representation_trace.json b/test/fixtures/point_representation_trace.json index f0b3f9a..a3a6e4a 100644 --- a/test/fixtures/point_representation_trace.json +++ b/test/fixtures/point_representation_trace.json @@ -345,7 +345,7 @@ { "Event": { "kind": 0, - "content": "(3, 4)", + "content": "\"(3, 4)\"", "metadata": "" } } diff --git a/test/test_kernel_patches.rb b/test/test_kernel_patches.rb index 2ec7536..aa4ed6f 100644 --- a/test/test_kernel_patches.rb +++ b/test/test_kernel_patches.rb @@ -1,7 +1,7 @@ # SPDX-License-Identifier: MIT require 'minitest/autorun' -require_relative '../codetracer/kernel_patches' # Adjust path as necessary +require_relative '../gems/codetracer-pure-ruby-recorder/lib/codetracer/kernel_patches' class MockTracer attr_reader :events, :name