Skip to content

mruby-test: regenerate the per-gem test wrapper when a mrbgem.rake it is generated from changes - #7160

Merged
matz merged 1 commit into
mruby:masterfrom
takumin:mrbtest-wrapper-gem-rake-dep
Aug 14, 2026
Merged

mruby-test: regenerate the per-gem test wrapper when a mrbgem.rake it is generated from changes#7160
matz merged 1 commit into
mruby:masterfrom
takumin:mrbtest-wrapper-gem-rake-dep

Conversation

@takumin

@takumin takumin commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Problem

The per-gem test wrapper build/<target>/mrbgems/<gem>/gem_test.c is generated from mrbgem.rake, not only from the test files it embeds. Its body follows the gem's spec.test_rbfiles, spec.test_preload, spec.test_args and spec.test_objs (via custom_test_init?), and it declares and calls the init/final function of every gem returned by tsort_dependencies.

The file task that generates it, however, listed only the test .rb files and mrbc as prerequisites:

file g.test_rbireps => [g.test_rbfiles, build.mrbcfile].flatten do |t|

So editing a mrbgem.rake does not invalidate the wrapper. An incremental rake test keeps running the previously generated test set and reporting the previous result, until a test file happens to be touched or the build directory is cleaned. This is easy to mistake for a test that legitimately still passes (or still fails), which makes it an actively misleading failure mode when adding, removing or re-scoping a gem's tests.

Reproduction

On a fully built tree (rake test:build), narrow one gem's test set without touching any test file. Append to mrbgems/mruby-string-ext/mrbgem.rake:

spec.test_rbfiles = ["#{MRUBY_ROOT}/mrbgems/mruby-string-ext/test/string.rb"]

Then rebuild:

$ rake test:build
$ ./build/host/bin/mrbtest | grep Total:
  Total: 2049

gem_test.c is byte-identical to before the edit and still embeds all three ireps; the count is unchanged. touch mrbgems/mruby-string-ext/test/string.rb && rake test:build then produces the expected single-irep wrapper and Total: 2044, confirming the stale artifact is the wrapper itself.

(Note that plain rake will not show this: the mruby-test gem is only loaded under the test:build task.)

Fix

Add to the wrapper's prerequisites the mrbgem.rake of the gem and of each gem in its dependency list, plus mruby-test/mrbgem.rake itself, which holds the generator.

Tracking the dependency list is not defensive; it is load-bearing. Adding spec.add_dependency 'mruby-math', core: 'mruby-math' to mrbgems/mruby-string-ext/mrbgem.rake changes the wrapper of mruby-regexp, which depends on it, because mruby-math's init/final calls are emitted there too. Tracking only the gem's own rakefile leaves that wrapper stale.

Both dependencies follow existing convention in the tree: MRuby::Command::Compiler#define_rules already records mrbgem.rake for a gem's C objects, and the sibling mrbtest.c rule already records __FILE__ for its own generator. The per-gem test wrapper was simply missing both. The change is in mrbtest's rake rules only. No gem or core source is touched, and nothing is specific to any one gem.

The File.exist? filter keeps the rule safe for a MRuby::Gem::Specification that is not backed by an on-disk mrbgem.rake: a prerequisite that neither exists nor has a rule would abort the build. define_rules guards the same way.

One input remains untracked and is left for a separate change: the contents of the file named by spec.test_preload are embedded in the wrapper, but only its path is covered here. No in-tree gem currently sets test_preload.

Verification

  • Narrowing a gem's test set via mrbgem.rake alone, with no test file touched and test/string.rb older than the existing gem_test.c, now regenerates the wrapper and moves the count from Total: 2049 to Total: 2044; reverting the edit restores Total: 2049.
  • The cross-gem case above regenerates mruby-regexp's wrapper from bb189b91… to 4c6a7f5f…, with grep -c GENERATED_TMP_mrb_mruby_math_gem_init going from 0 to 2, the same content reached by force-touching that gem's own rakefile.
  • touch mrbgems/mruby-test/mrbgem.rake && rake test:build regenerates all 50 wrappers, where previously it regenerated none.
  • A cold build (rake clean, then full build) generates all wrappers and yields the same totals as before.

rake -m test on the current master with this change: Total: 2075, OK: 2046, KO: 0, Crash: 0, Warning: 0, Skip: 29, plus bintest Total: 105, KO: 0, Crash: 0. No behavioural change to the tests themselves is expected; this only makes an incremental build notice inputs it was already using.

Summary by CodeRabbit

  • Bug Fixes

    • Improved test build reliability by ensuring generated test artifacts are refreshed when gem configuration or test dependencies change.
    • Preserved existing dependency-based test wrapper generation behavior.
  • Chores

    • Updated test generation dependency tracking to reduce stale or outdated test results.

The per-gem test wrapper (build/.../mrbgems/<gem>/gem_test.c) is generated
from mrbgem.rake, not only from the test files it embeds: its body follows
the gem's test_rbfiles, test_preload and test_args, and it declares and
calls the init/final function of every gem returned by tsort_dependencies.
Its file task, however, listed only the gem's test .rb files and mrbc as
prerequisites, so editing a mrbgem.rake left a stale wrapper in place and an
incremental build kept reporting the previous test result until a test file
happened to be touched or the build directory was cleaned.

Reproduced on a fully built tree by narrowing one gem's test set:

    $ rake test:build                  # wrapper embeds 3 ireps, Total: 2049
    $ # add to mrbgems/mruby-string-ext/mrbgem.rake:
    $ #   spec.test_rbfiles = ["#{MRUBY_ROOT}/mrbgems/mruby-string-ext/test/string.rb"]
    $ rake test:build
    $ ./build/host/bin/mrbtest | grep Total
      Total: 2049                      # unchanged, wrapper byte-identical

Touching mrbgems/mruby-string-ext/test/string.rb and rebuilding then drops
the wrapper to 1 irep and the count to 2044, confirming the stale wrapper
rather than a stale binary.

Track the rakefile of the gem and of each gem in its dependency list. The
dependency list matters on its own: adding a dependency to mruby-string-ext
changes the wrapper of mruby-regexp, which depends on it, so tracking only
the gem's own rakefile would still leave mruby-regexp stale. Also track this
file, which holds the generator, as the mrbtest.c rule in it already does.
Depending on a gem's mrbgem.rake mirrors what MRuby::Command::Compiler
#define_rules does for a gem's C objects. The existence check keeps the rule
safe for specifications not backed by an on-disk mrbgem.rake, since a
non-existent prerequisite with no rule would abort the build.

Only the test_preload path is covered this way; the contents of that file
are still not a prerequisite. No in-tree gem sets test_preload.
@coderabbitai

coderabbitai Bot commented Aug 14, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 55703ded-3b35-4f56-86ae-83318525e311

📥 Commits

Reviewing files that changed from the base of the PR and between 783e3b2 and 22fedb7.

📒 Files selected for processing (1)
  • mrbgems/mruby-test/mrbgem.rake

📝 Walkthrough

Walkthrough

The test irep generation rule now depends on the gem’s mrbgem.rake and the mrbgem.rake files of its test gem dependencies. Existing dependencies on test files, mrbc, and the generator remain.

Changes

Test irep generation

Layer / File(s) Summary
Track gem build definitions
mrbgems/mruby-test/mrbgem.rake
The generation rule collects existing, unique mrbgem.rake files for the gem and its test dependencies and adds them as prerequisites.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: ⚪ Minimal · up to 22fed

This change makes per-gem test wrappers regenerate when their rakefile inputs change; no actionable merge-blocking risk remains beyond normal checks and review.

Suggested reviewers: matz

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes regenerating per-gem test wrappers when their source mrbgem.rake files change.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@matz
matz merged commit 93e842c into mruby:master Aug 14, 2026
21 checks passed
@takumin
takumin deleted the mrbtest-wrapper-gem-rake-dep branch August 14, 2026 09:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants