Project

General

Profile

Actions

Misc #22296

open

Ruby::Box: method stubs on core classes are invisible to internal builtins

Misc #22296: Ruby::Box: method stubs on core classes are invisible to internal builtins

Added by hsbt (Hiroshi SHIBATA) about 15 hours ago.

Status:
Open
Assignee:
-

Description

Under RUBY_BOX=1, redefining a core class method affects only the box where the definition happens. Code loaded with require runs in the main box and observes the redefinition, but methods implemented as internal builtins do not. This breaks the way test frameworks install doubles, and the breakage is partial rather than total, which makes it hard to diagnose.

require "pathname"
require "rspec/mocks/standalone"

allow(File).to receive(:expand_path).and_return("/stubbed")

puts File.expand_path("x")            # => "/stubbed" in both modes
puts Pathname.new("x").expand_path    # => "/stubbed" normally, real path under RUBY_BOX=1

The same divergence appears without any gem by defining def File.expand_path(*) = "/stubbed" directly. A pure Ruby library that I require and that calls File.expand_path does observe the stub, so this is not general box isolation of stdlib. It is specific to builtins, and Pathname#expand_path reports <internal:pathname_builtin> as its source location. Defining the method through Ruby::Box.root.eval does not help either, because the builtin still does not see it.

I hit this in the RubyGems test suite while making it green under RUBY_BOX=1. A blanket File.expand_path stub was honored by our own code but bypassed by Pathname, so an unrelated path resolved for real and the example failed far from the stub. I worked around it in ruby/rubygems#9826 by scoping the stub to the exact arguments under test.

My question is about the intended design rather than this one case. Blanket stubs on File, Time and other core classes are extremely common in existing test suites. Do we treat this as a breaking change and ask test authors to write box-aware stubs, or should Box make such redefinitions visible to builtins? If the former, the behavior needs to be documented before Box becomes the default, and rspec-mocks and similar libraries probably need a way to detect it. If the latter, we need to decide how far the visibility extends without giving up the isolation Box is meant to provide.


Related issues 1 (1 open0 closed)

Related to Ruby - Misc #22275: Ruby::Box support plan for RubyGems and BundlerOpenActions
Actions

Also available in: PDF Atom