oracle / truffleruby

A high performance implementation of the Ruby programming language, built on GraalVM.
https://www.graalvm.org/ruby/
Other
2.98k stars 180 forks source link

TracePoint doesn't trigger the :class event within a `sus` test case #3095

Open andrykonchin opened 1 year ago

andrykonchin commented 1 year ago

The console gem CI fails on TruffleRuby because in a :class event isn't triggered when a new class is declared in a test case.

The simplified example looks like so:

describe Console::Resolver do

  it "tests TracePoint in sus" do
    resolved = false

    trace_point = TracePoint.new(:class) do |event|
      resolved = true
    end

    trace_point.enable

    class Foobar
    end

    puts "resolved -> true " + (resolved ? "[OK]" : "[FAIL]")
  end
end

Expected result is:

resolved -> true [OK]

But actual is:

resolved -> true [FAIL]

If run this code as a plain Ruby script then result is expected:

resolved = false

trace_point = TracePoint.new(:class) do |event|
  resolved = true
end

trace_point.enable

class Foobar
end

puts "resolved -> true " + (resolved ? "[OK]" : "[FAIL]")

The console gem CI job output:

🤔 Failed assertions:
describe Console::Resolver it triggers when class is defined test/console/resolver.rb:14
    expect #<Console::Resolver:0x3238 @names={"Console::Resolver::Foobar"=>#<Proc:0x3258 test/console/resolver.rb:17>}, @trace_point=#<TracePoint:enabled>> to
        be waiting? 
    expect #<Console::Resolver:0x3238 @names={"Console::Resolver::Foobar"=>#<Proc:0x3258 test/console/resolver.rb:17>}, @trace_point=#<TracePoint:enabled>> to not
        be waiting? 
            ✗ assertion passed /home/runner/work/console/console/vendor/bundle/truffleruby/3.1.3.23.0.0/gems/sus-0.20.3/lib/sus/assertions.rb:[18](https://github.com/socketry/console/actions/runs/5176976466/jobs/9326492884#step:4:19)3
    expect false to
        be == true
            ✗ assertion failed /home/runner/work/console/console/vendor/bundle/truffleruby/3.1.3.23.0.0/gems/sus-0.20.3/lib/sus/assertions.rb:183

https://github.com/socketry/console/actions/runs/5176976466/jobs/9326492884

eregon commented 1 year ago

FYI @ioquatix

From a quick look the sus gem doesn't use TracePoints itself: https://github.com/search?q=repo%3Aioquatix%2Fsus%20TracePoint&type=code

I'll try to investigate this when I have some time.

eregon commented 1 year ago

Related: https://github.com/oracle/truffleruby/issues/2371 Which might solve this, but we should understand why it doesn't work currently first.

ioquatix commented 1 year ago

sus does not use trace points, but console does to enable logging for classes.

It works like this:

# script.rb

class Foo
  def do_something
    Console.logger.debug(self, "Do something.")
  end
end

Executed as so:

CONSOLE_DEBUG=Foo ruby ./script.rb

The mapping of class names to classes does not exist, so there is a "resolver" which attempts to resolve those strings to actual classes as they are loaded. This avoids using string comparisons of class names.

In any case, the 2nd example in the original report above is completely divorced from both console and sus.

If you think there is a better, more compatible way we could do this, I'd be totally fine to reimplement it.