FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Add ruby/spec coverage for the code range of interpolated strings by jwils · Pull Request #9596 · jruby/jruby · GitHub

/ jruby Public

Add ruby/spec coverage for the code range of interpolated strings - #9596

Draft
jwils wants to merge 1 commit into
jruby:jruby-10.0from
jwils:spec-coderange-followup
Draft

Add ruby/spec coverage for the code range of interpolated strings#9596
jwils wants to merge 1 commit into
jruby:jruby-10.0from
jwils:spec-coderange-followup

Conversation

jwils commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #9592, per the review note about preferring these tests in the RubySpec suite.

The code range is observable from pure Ruby, so specs are possible after all:

Both are standard methods, and the new specs pass on CRuby, so they are upstreamable to ruby/spec.

What this adds

  • core/string/ascii_only_spec.rb: interpolation of a non-String object into an ASCII-only string keeps the string ASCII-only. A second spec checks that real non-ASCII text stays non-ASCII, to guard the opposite error.
  • core/string/hash_spec.rb: hash agrees with eql? for byte-identical strings, and uniq does not split them.
  • language/heredoc_spec.rb: an ASCII-only squiggly heredoc is ASCII-only.

This does not replace the test/jruby test

test/jruby/test_compound_string_coderange.rb must stay. The bug only appears in compiled code, and a spec body runs one time, so it stays interpreted. I checked this against a build without the #9592 fix:

Compile mode CI target New specs on an unfixed build
compile.mode=JIT, jit.threshold=0 spec:ruby:fast:jit pass, so the bug is missed
compile.mode=FORCE none fail, so the bug is caught

No CI target runs ruby/spec under FORCE. spec:precompiled (spec:ruby:aot) is the only FORCE rubyspec task, and it is not in the ci.yml matrix. The matrix has test:jruby:aot, which runs the test/jruby suite.

The test/jruby test forces the compiler in a child process, so it stays the guard against a regression. These specs add cross-implementation coverage of the behaviour.

Two of the four specs detect the bug under FORCE: the String#hash spec and the ascii_only? interpolation spec. The heredoc spec passes on a broken build because the fold does not happen inside a spec block, so treat it as documentation of the expected result.

Test

Built the branch and ran the three spec files in both JIT and FORCE mode, against a fixed and an unfixed build. On the fixed build the only failures are the two entries already listed in spec/tags/ruby/language/heredoc_tags.txt.

jrubyGH-9591 folded a compound string into one literal with the wrong code
range. An ASCII-only result was marked as not 7-bit, so String#hash
disagreed with String#eql? and uniq split byte-identical strings.

Add specs for the plain-Ruby behaviour:

- String#ascii_only? is true when a non-String object is interpolated
  into an ASCII-only string.
- String#ascii_only? stays false for real non-ASCII text.
- String#hash agrees with String#eql? for byte-identical strings.
- A squiggly heredoc with ASCII-only content is ASCII-only.

These specs do not replace test/jruby/test_compound_string_coderange.rb.
The bug only appears in compiled code. A spec body runs one time, so it
stays interpreted under spec:ruby:fast and spec:ruby:fast:jit. Only
jruby.compile.mode=FORCE shows the bug, and no CI target runs ruby/spec
in that mode. The test/jruby test forces the compiler in a child
process, so it is the guard against a regression.
jwils marked this pull request as draft August 17, 2026 21:42

headius commented Aug 17, 2026

Copy link
Copy Markdown
Member

A clarification: the ascii_only? method does use the code range to return a result, but all it can indicate is whether the "7-bit" bit of the code range is set. It cannot tell us about any of the other bits.

That is probably sufficient for testing the fixed behavior, but I wanted to point out that there's no way to access the raw code range directly despite what this PR claims.

jwils commented Aug 17, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the correction.

Do you even want this PR?

Since the bug only appears in compiled code these tests alone don't reproduce anything. Running the test with compile.mode=FORCE can reproduce an error without the fix and it also documents an error without the fix, but curious your thoughts or suggestions on another way to do it as it doesn't replace the other tests right now.

headius commented Aug 18, 2026

Copy link
Copy Markdown
Member

Yes, I think this spec is just fine and the other internal test can be removed since it doesn't actually check the full code range either.

jwils commented Aug 18, 2026

Copy link
Copy Markdown
Contributor Author

Just to make sure I'm not missing something, my concern is the other test would catch this regressing because it sets sub processes to force compile https://github.com/jruby/jruby/pull/9592/changes#diff-31d52ab943ab646d93c49be70e240a548c99fd4b3c4cbad1d08c36f041292993R18.

Since this one doesn't by default I don't think it would detect a regression. If still your preference though I can update to remove the other tests.

headius commented Aug 18, 2026

Copy link
Copy Markdown
Member

Your agent is basically wrong here. FORCE is only one of the ways we trigger the jit. We have CI runs that set the jit threshold to zero and additional spec runs that execute the specs repeatedly to ensure the jit has finished.

For a bonus you could ask your agent why it believes that mode is necessary and perhaps there's some old documentation it is picking up.

One thing I did realize though: these specs should go under spec/ruby/language since they are directly related to the interpretation and compilation of Ruby code, and not really a test of String behavior.

headius commented Aug 18, 2026

Copy link
Copy Markdown
Member

For reference, this is the spec:ruby:fast:jit target we use in CI. The jit.threshold option is set to zero, which disables background compilation and forces all method and block bodies to be compiled before first execution.

desc "Run fast specs that do not spawn many subprocesses"
task :'ruby:fast:jit' do
mspec :compile_mode => "JIT",
:jit_threshold => 0,
:format => MSPEC_FORMAT,
:spec_target => ":fast"
end

jwils commented Aug 18, 2026
edited
Loading

Copy link
Copy Markdown
Contributor Author

Your agent is basically wrong here. FORCE is only one of the ways we trigger the jit. We have CI runs that set the jit threshold to zero and additional spec runs that execute the specs repeatedly to ensure the jit has finished.

The agent is definitely helpful to me here as there's no way I would have had the time or ability to track down our flaky test, but that question is driven by me (and I guess my agent isn't able to answer it). My goal is to be able to run the test suite and have it fail before the PR and I haven't figured out how to do that. The agent has all kinds of ideas like running in a loop N times, but none of those satisfy me. I couldn't get spec:ruby:fast:jit to work. Let me update this pr to not have the fix PR.

headius commented Aug 18, 2026

Copy link
Copy Markdown
Member

Let me know what doesn't work. If your environment is bootstrapped according to the root docs, it should function ok:

[] jruby $ rake spec:ruby:fast:jit
MSPEC: {compile_mode: "JIT", jit_threshold: 0, format: "d", spec_target: ":fast", command: "ci", jit_max: -1, objectspace_enabled: true, thread_pooling: false, reflection: false, timeout: 120}
rm -rf rubyspec_temp
JAVA options: {dir: "/Users/headius/work/jruby", maxmemory: "1024M", resultproperty: "spec.status.JIT", fork: "true", failonerror: "true", classname: "org.jruby.main.Main"}
$ /Users/headius/work/jruby/bin/jruby -Xbacktrace.style=mri -J-ea -J-Djruby.launch.inproc=false -J-Djruby.compile.mode=JIT -J-Djruby.jit.threshold=0 -J-Djruby.jit.max=-1 -J-Djruby.objectspace.enabled=true -J-Djruby.thread.pool.enabled=false -J-Djruby.reflection=false -J-Demma.coverage.out.file=target/test-results/coverage.emma -J-Demma.coverage.out.merge=true -J-Demma.verbosity.level=silent -J-XX:MaxMetaspaceSize=768M /Users/headius/work/jruby/spec/mspec/bin/mspec-ci -f d --timeout 120 :fast
/Users/headius/work/jruby/spec/mspec/lib/mspec/commands/mspec.rb:110: warning: unsupported exec option: close_others
jruby 10.1.2.0-SNAPSHOT (4.0.0) 2026-08-17 f57d6a5468 OpenJDK 64-Bit Server VM 21.0.8+9-LTS on 21.0.8+9-LTS +indy +jit [arm64-darwin]
/Users/headius/work/jruby/spec/ruby/language/if_spec.rb:143: warning: literal in condition
/Users/headius/work/jruby/spec/ruby/language/method_spec.rb:1239: warning: empty expression
/Users/headius/work/jruby/spec/ruby/language/method_spec.rb:1289: warning: empty expression
/Users/headius/work/jruby/spec/ruby/language/method_spec.rb:1297: warning: empty expression
...etc

You can also run the specs directly, with jit threshold zero, using something like this command line:

$ spec/mspec/bin/mspec ci -T-Xjit.threshold=0 spec/ruby/language/some_spec.rb

headius commented Aug 18, 2026

Copy link
Copy Markdown
Member

I must also mention...in case we haven't discussed this already...

If you are running JRuby in a production setting, I'd love to partner with you to support that use. Fully 100% of my development time is funded through support arrangements from https://headius.com/services. The Expert level means I'm virtually on your team, answering questions and ensure bugs get fixed and released, but if every JRuby user in the world signed up for the basic Professional level, we'd be fully funded.

Partnering in this way also helps JRuby improve based on your needs. I can't guess what to prioritize for real-world JRuby apps unless I know about those apps. It's a win for both of us.

Please consider partnering with us to keep JRuby healthy and moving forward!

jwils commented Aug 18, 2026

Copy link
Copy Markdown
Contributor Author

Let me know what doesn't work.

It doesn't seem to work. Let me know if I am totally missing something here. I believe jwils@6449e75 fixes it, but surfaces some other failed tests. Let me know if you think that fix looks correct. I can attempt to make that first and see what other work is needed to get the test suite to pass.

If you are running JRuby in a production setting, I'd love to partner with you to support that use.

I wasn't aware of this, our JRuby usage is limited, but we've recently added JRuby to elasticgraph (one of our opensource projects). I'll look into support partnerships internally

headius commented Aug 18, 2026

Copy link
Copy Markdown
Member

The agent may be right about JRUBY_OPTS not getting passed through from the original command-line rake call. I do see where the rake tasks set up a new JRUBY_OPTS env var, without including anything passed in.

Honestly I'm unsure if this is wrong. If you have a JRUBY_OPTS environment that tweaks JIT settings, you may not want the rake target you call to behave differently. It is a valid concern that our non-indy jobs may not be running without indy, but I'll look into that separately now that I see it might be a problem.

At the very least we do have jobs eagerly running the JIT, which is the key requirement for this PR.

headius commented Aug 18, 2026

Copy link
Copy Markdown
Member

FWIW it does look like the other suites avoid clobbering JRUBY_OPTS if they need to add something:

jruby/rakelib/test.rake

Lines 108 to 124 in fba7771

mri_suites.each do |suite, extra_jruby_opts|
files = File.readlines("test/mri.#{suite}.index").grep(/^[^#]\w+/).map(&:chomp).join(' ')
namespace suite do
jruby_opts.each do |task, opts|
task task do
ENV['JRUBY_OPTS'] = "#{ENV['JRUBY_OPTS']} #{extra_jruby_opts} #{opts}"
ruby "test/mri/runner.rb #{ADDITIONAL_TEST_OPTIONS} --excludes=test/mri/excludes -q -- #{files}"
end
task "#{task}:prism" do
ENV['JRUBY_OPTS'] = "#{ENV['JRUBY_OPTS']} #{extra_jruby_opts} -Xparser.prism #{opts}"
ruby "test/mri/runner.rb #{ADDITIONAL_TEST_OPTIONS} --excludes=test/mri/excludes -q -- #{files}"
end
end
end

I'm going to contemplate whether there might be a cleaner way to allow both runtime configuration from the rake command line AND pre-defined targets with specific configs.

headius commented Aug 18, 2026

Copy link
Copy Markdown
Member

I've opened #9597 to track improvements to how we tweak the runtime configuration for rake targets.

This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants


Back | FazBrowse Home | New Git URL