diff --git a/.github/workflows/check_dependencies.yml b/.github/workflows/check_dependencies.yml index 6d85cf8e9c043a..db93e90efb7c10 100644 --- a/.github/workflows/check_dependencies.yml +++ b/.github/workflows/check_dependencies.yml @@ -48,11 +48,7 @@ jobs: - name: Run configure run: ./configure -C --disable-install-doc --disable-rubygems --with-gcc 'optflags=-O0' 'debugflags=-save-temps=obj -g' - - run: make all golf - - - run: ./goruby -veh - - - run: ruby tool/update-deps --fix + - run: make fix-depends - run: git diff --no-ext-diff --ignore-submodules --exit-code diff --git a/.github/workflows/rust-warnings.yml b/.github/workflows/rust-warnings.yml index a8840c28e4c30c..8fd78ea04bc97d 100644 --- a/.github/workflows/rust-warnings.yml +++ b/.github/workflows/rust-warnings.yml @@ -42,10 +42,10 @@ jobs: run: rustup default beta - name: Rust warnings + shell: bash run: | - set -euo pipefail + set -eu cargo check --quiet --all-features --message-format=json \ - | jq -r 'select(.reason == "compiler-message" and .message.level == "warning") | .message.rendered' \ - > warnings.txt - cat warnings.txt - ! grep --quiet '[^[:space:]]' warnings.txt + | jq -r 'select(.message.level == "warning" or .message.level == "error") | .message.rendered' \ + | tee messages.txt + (exit "${PIPESTATUS[0]}") && ! grep --quiet '[^[:space:]]' messages.txt diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index 27cd43bf9cd880..8955ea91d4c558 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -191,6 +191,11 @@ jobs: if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }} continue-on-error: ${{ matrix.continue-on-skipped_tests || false }} + - name: test-pc + run: | + DESTDIR=${RUNNER_TEMP-${TMPDIR-/tmp}}/installed + $SETARCH make test-pc "DESTDIR=$DESTDIR" + - uses: ./.github/actions/slack with: label: ${{ matrix.test_task }} ${{ matrix.configure }}${{ matrix.arch }} diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 9137e5298a9b1b..0b7bf25d95ff0b 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -85,6 +85,7 @@ jobs: shell: pwsh - name: Restore vcpkg artifact + id: restore-vcpkg uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 with: path: src\vcpkg_installed @@ -94,13 +95,14 @@ jobs: run: | vcpkg install --vcpkg-root=%USERPROFILE%\scoop\apps\vcpkg\current working-directory: src + if: ${{ ! steps.restore-vcpkg.outputs.cache-hit }} - name: Save vcpkg artifact uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 with: path: src\vcpkg_installed key: windows-${{ matrix.os }}-vcpkg-${{ hashFiles('src/vcpkg.json') }} - if: ${{ github.ref_name == 'master' || startsWith(github.ref_name, 'ruby_') }} + if: ${{ ! steps.restore-vcpkg.outputs.cache-hit && (github.ref_name == 'master' || startsWith(github.ref_name, 'ruby_')) }} - name: setup env # Available Ruby versions: https://github.com/actions/runner-images/blob/main/images/windows/Windows2019-Readme.md#ruby @@ -113,8 +115,8 @@ jobs: -arch=${{ matrix.target || 'amd64' }} ^ ${{ matrix.vcvars && '-vcvars_ver=' || '' }}${{ matrix.vcvars }} nmake -f nul - set TMP=%USERPROFILE%\AppData\Local\Temp - set TEMP=%USERPROFILE%\AppData\Local\Temp + set TMP=%RUNNER_TEMP% + set TEMP=%RUNNER_TEMP% set MAKEFLAGS=l set /a TEST_JOBS=(15 * %NUMBER_OF_PROCESSORS% / 10) > nul set RUBY_OPT_DIR=%GITHUB_WORKSPACE:\=/%/src/vcpkg_installed/%VCPKG_DEFAULT_TRIPLET% diff --git a/.gitignore b/.gitignore index ddf8e9a99adae3..6cf5fb5f32d63e 100644 --- a/.gitignore +++ b/.gitignore @@ -272,6 +272,7 @@ lcov*.info /prism/prettyprint.c /prism/serialize.c /prism/token_type.c +/prism/srcs.mk # tool/update-NEWS-gemlist.rb /bundled_gems.json diff --git a/common.mk b/common.mk index 9e5098ef4b1300..f4ea06c2631449 100644 --- a/common.mk +++ b/common.mk @@ -205,82 +205,12 @@ $(PRISM_BUILD_DIR)/.time $(PRISM_BUILD_DIR)/util/.time: $(Q) $(MAKEDIRS) $(@D) @$(NULLCMD) > $@ -main: $(srcdir)/lib/prism/compiler.rb -srcs: $(srcdir)/lib/prism/compiler.rb -$(srcdir)/lib/prism/compiler.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/compiler.rb.erb - $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb lib/prism/compiler.rb $(srcdir)/lib/prism/compiler.rb - -main: $(srcdir)/lib/prism/dispatcher.rb -srcs: $(srcdir)/lib/prism/dispatcher.rb -$(srcdir)/lib/prism/dispatcher.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/dispatcher.rb.erb - $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb lib/prism/dispatcher.rb $(srcdir)/lib/prism/dispatcher.rb - -main: $(srcdir)/lib/prism/dsl.rb -srcs: $(srcdir)/lib/prism/dsl.rb -$(srcdir)/lib/prism/dsl.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/dsl.rb.erb - $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb lib/prism/dsl.rb $(srcdir)/lib/prism/dsl.rb - -main: $(srcdir)/lib/prism/inspect_visitor.rb -srcs: $(srcdir)/lib/prism/inspect_visitor.rb -$(srcdir)/lib/prism/inspect_visitor.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/inspect_visitor.rb.erb - $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb lib/prism/inspect_visitor.rb $(srcdir)/lib/prism/inspect_visitor.rb - -main: $(srcdir)/lib/prism/mutation_compiler.rb -srcs: $(srcdir)/lib/prism/mutation_compiler.rb -$(srcdir)/lib/prism/mutation_compiler.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/mutation_compiler.rb.erb - $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb lib/prism/mutation_compiler.rb $(srcdir)/lib/prism/mutation_compiler.rb - -main: $(srcdir)/lib/prism/node.rb -srcs: $(srcdir)/lib/prism/node.rb -$(srcdir)/lib/prism/node.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/node.rb.erb - $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb lib/prism/node.rb $(srcdir)/lib/prism/node.rb - -main: $(srcdir)/lib/prism/reflection.rb -srcs: $(srcdir)/lib/prism/reflection.rb -$(srcdir)/lib/prism/reflection.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/reflection.rb.erb - $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb lib/prism/reflection.rb $(srcdir)/lib/prism/reflection.rb - -main: $(srcdir)/lib/prism/serialize.rb -srcs: $(srcdir)/lib/prism/serialize.rb -$(srcdir)/lib/prism/serialize.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/serialize.rb.erb - $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb lib/prism/serialize.rb $(srcdir)/lib/prism/serialize.rb - -main: $(srcdir)/lib/prism/visitor.rb -srcs: $(srcdir)/lib/prism/visitor.rb -$(srcdir)/lib/prism/visitor.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/visitor.rb.erb - $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb lib/prism/visitor.rb $(srcdir)/lib/prism/visitor.rb - -srcs: prism/api_node.c -prism/api_node.c: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/ext/prism/api_node.c.erb - $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb ext/prism/api_node.c $@ - -srcs: prism/ast.h -prism/ast.h: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/include/prism/ast.h.erb - $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb include/prism/ast.h $@ - -srcs: prism/diagnostic.c -prism/diagnostic.c: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/src/diagnostic.c.erb - $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb src/diagnostic.c $@ - -srcs: prism/diagnostic.h -prism/diagnostic.h: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/include/prism/diagnostic.h.erb - $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb include/prism/diagnostic.h $@ - -srcs: prism/node.c -prism/node.c: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/src/node.c.erb - $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb src/node.c $@ - -srcs: prism/prettyprint.c -prism/prettyprint.c: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/src/prettyprint.c.erb - $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb src/prettyprint.c $@ - -srcs: prism/serialize.c -prism/serialize.c: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/src/serialize.c.erb - $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb src/serialize.c $@ - -srcs: prism/token_type.c -prism/token_type.c: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/src/token_type.c.erb - $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb src/token_type.c $@ +$(PRISM_SRCDIR)/srcs.mk: $(HAVE_BASERUBY:yes=$(PRISM_SRCDIR)/templates/template.rb) \ + $(HAVE_BASERUBY:yes=$(PRISM_SRCDIR)/generate-srcs.mk.rb) + $(ECHO) Updating prism/srcs.mk + $(BASERUBY) $(PRISM_SRCDIR)/generate-srcs.mk.rb > $@ + +srcs: $(PRISM_SRCDIR)/srcs.mk EXPORTOBJS = $(DLNOBJ) \ localeinit.$(OBJEXT) \ @@ -797,7 +727,8 @@ clean-srcs-local:: realclean-srcs-local:: clean-srcs-local $(Q)$(CHDIR) $(srcdir) && $(RM) \ parse.c parse.h lex.c enc/trans/newline.c $(PRELUDES) revision.h \ - id.c id.h probes.dmyh configure aclocal.m4 tool/config.guess tool/config.sub gems/*.gem \ + id.c id.h probes.dmyh configure aclocal.m4 tool/config.guess tool/config.sub \ + $(PRISM_SRCDIR)/srcs.mk gems/*.gem \ || $(NULLCMD) clean-srcs-ext:: @@ -1290,7 +1221,7 @@ incs: $(INSNS) {$(VPATH)}node_name.inc {$(VPATH)}known_errors.inc \ {$(VPATH)}vm_call_iseq_optimized.inc $(srcdir)/revision.h \ $(REVISION_H) \ $(UNICODE_DATA_HEADERS) $(ENC_HEADERS) \ - $(srcs_vpath)prism/ast.h $(srcs_vpath)prism/diagnostic.h \ + $(top_srcdir)/prism/ast.h $(top_srcdir)/prism/diagnostic.h \ {$(VPATH)}id.h {$(VPATH)}probes.dmyh insns: $(INSNS) @@ -1915,6 +1846,9 @@ clean-gems: CLEAN_CACHE = clean-extlibs +prepare-package: prereq after-update +clean-cache: $(CLEAN_CACHE) + info: info-program info-libruby_a info-libruby_so info-arch info-program: PHONY @echo PROGRAM=$(PROGRAM) @@ -2046,3 +1980,5 @@ help: PHONY $(CROSS_COMPILING:yes=)builtin.$(OBJEXT): {$(VPATH)}mini_builtin.c $(CROSS_COMPILING:yes=)builtin.$(OBJEXT): {$(VPATH)}miniprelude.c + +!include $(srcdir)/prism/srcs.mk diff --git a/configure.ac b/configure.ac index c8018cdabb490a..366ffe1e05a88c 100644 --- a/configure.ac +++ b/configure.ac @@ -4698,8 +4698,9 @@ AC_CONFIG_FILES(Makefile:template/Makefile.in, [ sed '/^MISSING/s/\$U\././g;/^VCS *=/s#@VCS@#'"$VCS"'#;/^VCSUP *=/s#@VCSUP@#'"$VCSUP"'#' Makefile echo; test x"$EXEEXT" = x || echo 'miniruby: miniruby$(EXEEXT)' AS_IF([test "$gnumake" != yes], [ - echo ['$(MKFILES): $(srcdir)/common.mk $(srcdir)/depend'] - sed ['s/{\$([^(){}]*)[^{}]*}//g'] ${srcdir}/common.mk ${srcdir}/depend + echo ['$(MKFILES): $(srcdir)/common.mk $(srcdir)/depend $(srcdir)/prism/srcs.mk'] + sed ['s/{\$([^(){}]*)[^{}]*}//g;/^!/d'] ${srcdir}/common.mk ${srcdir}/depend + cat ${srcdir}/prism/srcs.mk AS_IF([test "$YJIT_SUPPORT" = yes], [ cat ${srcdir}/yjit/not_gmake.mk echo ['$(MKFILES): ${srcdir}/yjit/not_gmake.mk'] diff --git a/constant.h b/constant.h index 90a68d447a6208..3d4982c936da0a 100644 --- a/constant.h +++ b/constant.h @@ -44,7 +44,7 @@ void rb_free_const_table(struct rb_id_table *tbl); VALUE rb_const_source_location(VALUE, ID); int rb_autoloading_value(VALUE mod, ID id, VALUE *value, rb_const_flag_t *flag); -rb_const_entry_t *rb_const_lookup(VALUE klass, ID id); +rb_const_entry_t *rb_const_lookup(VALUE klass, ID id, rb_const_entry_t *entry_out); VALUE rb_public_const_get_at(VALUE klass, ID id); VALUE rb_public_const_get_from(VALUE klass, ID id); int rb_public_const_defined_from(VALUE klass, ID id); diff --git a/defs/gmake.mk b/defs/gmake.mk index 6382e3d0031832..bd4b8b8e39f201 100644 --- a/defs/gmake.mk +++ b/defs/gmake.mk @@ -505,6 +505,9 @@ update-deps: $(GIT) --git-dir=$(GIT_DIR) merge --no-edit --ff-only $(update_deps) $(GIT) --git-dir=$(GIT_DIR) branch --delete $(update_deps) +fix-depends check-depends: all hello + $(BASERUBY) -C $(srcdir) tool/update-deps $(if $(filter fix-%,$@),--fix) + # order-only-prerequisites doesn't work for $(RUBYSPEC_CAPIEXT) # because the same named directory exists in the source tree. $(RUBYSPEC_CAPIEXT)/%.$(DLEXT): $(srcdir)/$(RUBYSPEC_CAPIEXT)/%.c $(RUBYSPEC_CAPIEXT_DEPS) \ diff --git a/depend b/depend index ea2486e9e8da1d..0fcf5ce652cd06 100644 --- a/depend +++ b/depend @@ -303,7 +303,9 @@ ast.$(OBJEXT): $(top_srcdir)/internal/symbol.h ast.$(OBJEXT): $(top_srcdir)/internal/variable.h ast.$(OBJEXT): $(top_srcdir)/internal/vm.h ast.$(OBJEXT): $(top_srcdir)/internal/warnings.h +ast.$(OBJEXT): $(top_srcdir)/prism/ast.h ast.$(OBJEXT): $(top_srcdir)/prism/defines.h +ast.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h ast.$(OBJEXT): $(top_srcdir)/prism/encoding.h ast.$(OBJEXT): $(top_srcdir)/prism/node.h ast.$(OBJEXT): $(top_srcdir)/prism/options.h @@ -323,6 +325,7 @@ ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h +ast.$(OBJEXT): $(top_srcdir)/prism/version.h ast.$(OBJEXT): {$(VPATH)}assert.h ast.$(OBJEXT): {$(VPATH)}ast.c ast.$(OBJEXT): {$(VPATH)}ast.rbinc @@ -501,9 +504,6 @@ ast.$(OBJEXT): {$(VPATH)}missing.h ast.$(OBJEXT): {$(VPATH)}node.h ast.$(OBJEXT): {$(VPATH)}onigmo.h ast.$(OBJEXT): {$(VPATH)}oniguruma.h -ast.$(OBJEXT): {$(VPATH)}prism/ast.h -ast.$(OBJEXT): {$(VPATH)}prism/diagnostic.h -ast.$(OBJEXT): {$(VPATH)}prism/version.h ast.$(OBJEXT): {$(VPATH)}prism_compile.h ast.$(OBJEXT): {$(VPATH)}ruby_assert.h ast.$(OBJEXT): {$(VPATH)}ruby_atomic.h @@ -746,7 +746,9 @@ builtin.$(OBJEXT): $(top_srcdir)/internal/static_assert.h builtin.$(OBJEXT): $(top_srcdir)/internal/variable.h builtin.$(OBJEXT): $(top_srcdir)/internal/vm.h builtin.$(OBJEXT): $(top_srcdir)/internal/warnings.h +builtin.$(OBJEXT): $(top_srcdir)/prism/ast.h builtin.$(OBJEXT): $(top_srcdir)/prism/defines.h +builtin.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h builtin.$(OBJEXT): $(top_srcdir)/prism/encoding.h builtin.$(OBJEXT): $(top_srcdir)/prism/node.h builtin.$(OBJEXT): $(top_srcdir)/prism/options.h @@ -766,6 +768,7 @@ builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h +builtin.$(OBJEXT): $(top_srcdir)/prism/version.h builtin.$(OBJEXT): {$(VPATH)}assert.h builtin.$(OBJEXT): {$(VPATH)}atomic.h builtin.$(OBJEXT): {$(VPATH)}backward/2/assume.h @@ -944,9 +947,6 @@ builtin.$(OBJEXT): {$(VPATH)}missing.h builtin.$(OBJEXT): {$(VPATH)}node.h builtin.$(OBJEXT): {$(VPATH)}onigmo.h builtin.$(OBJEXT): {$(VPATH)}oniguruma.h -builtin.$(OBJEXT): {$(VPATH)}prism/ast.h -builtin.$(OBJEXT): {$(VPATH)}prism/diagnostic.h -builtin.$(OBJEXT): {$(VPATH)}prism/version.h builtin.$(OBJEXT): {$(VPATH)}prism_compile.h builtin.$(OBJEXT): {$(VPATH)}ruby_assert.h builtin.$(OBJEXT): {$(VPATH)}ruby_atomic.h @@ -1391,7 +1391,9 @@ compile.$(OBJEXT): $(top_srcdir)/internal/thread.h compile.$(OBJEXT): $(top_srcdir)/internal/variable.h compile.$(OBJEXT): $(top_srcdir)/internal/vm.h compile.$(OBJEXT): $(top_srcdir)/internal/warnings.h +compile.$(OBJEXT): $(top_srcdir)/prism/ast.h compile.$(OBJEXT): $(top_srcdir)/prism/defines.h +compile.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h compile.$(OBJEXT): $(top_srcdir)/prism/encoding.h compile.$(OBJEXT): $(top_srcdir)/prism/node.h compile.$(OBJEXT): $(top_srcdir)/prism/options.h @@ -1399,6 +1401,7 @@ compile.$(OBJEXT): $(top_srcdir)/prism/pack.h compile.$(OBJEXT): $(top_srcdir)/prism/parser.h compile.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h compile.$(OBJEXT): $(top_srcdir)/prism/prism.h +compile.$(OBJEXT): $(top_srcdir)/prism/prism.h compile.$(OBJEXT): $(top_srcdir)/prism/regexp.h compile.$(OBJEXT): $(top_srcdir)/prism/static_literals.h compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h @@ -1411,6 +1414,7 @@ compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h +compile.$(OBJEXT): $(top_srcdir)/prism/version.h compile.$(OBJEXT): $(top_srcdir)/prism_compile.c compile.$(OBJEXT): {$(VPATH)}assert.h compile.$(OBJEXT): {$(VPATH)}atomic.h @@ -1597,10 +1601,6 @@ compile.$(OBJEXT): {$(VPATH)}node.h compile.$(OBJEXT): {$(VPATH)}onigmo.h compile.$(OBJEXT): {$(VPATH)}oniguruma.h compile.$(OBJEXT): {$(VPATH)}optinsn.inc -compile.$(OBJEXT): {$(VPATH)}prism/ast.h -compile.$(OBJEXT): {$(VPATH)}prism/diagnostic.h -compile.$(OBJEXT): {$(VPATH)}prism/prism.h -compile.$(OBJEXT): {$(VPATH)}prism/version.h compile.$(OBJEXT): {$(VPATH)}prism_compile.c compile.$(OBJEXT): {$(VPATH)}prism_compile.h compile.$(OBJEXT): {$(VPATH)}ractor.h @@ -2067,7 +2067,9 @@ cont.$(OBJEXT): $(top_srcdir)/internal/thread.h cont.$(OBJEXT): $(top_srcdir)/internal/variable.h cont.$(OBJEXT): $(top_srcdir)/internal/vm.h cont.$(OBJEXT): $(top_srcdir)/internal/warnings.h +cont.$(OBJEXT): $(top_srcdir)/prism/ast.h cont.$(OBJEXT): $(top_srcdir)/prism/defines.h +cont.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h cont.$(OBJEXT): $(top_srcdir)/prism/encoding.h cont.$(OBJEXT): $(top_srcdir)/prism/node.h cont.$(OBJEXT): $(top_srcdir)/prism/options.h @@ -2087,6 +2089,7 @@ cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h +cont.$(OBJEXT): $(top_srcdir)/prism/version.h cont.$(OBJEXT): {$(VPATH)}$(COROUTINE_H) cont.$(OBJEXT): {$(VPATH)}assert.h cont.$(OBJEXT): {$(VPATH)}atomic.h @@ -2267,9 +2270,6 @@ cont.$(OBJEXT): {$(VPATH)}missing.h cont.$(OBJEXT): {$(VPATH)}node.h cont.$(OBJEXT): {$(VPATH)}onigmo.h cont.$(OBJEXT): {$(VPATH)}oniguruma.h -cont.$(OBJEXT): {$(VPATH)}prism/ast.h -cont.$(OBJEXT): {$(VPATH)}prism/diagnostic.h -cont.$(OBJEXT): {$(VPATH)}prism/version.h cont.$(OBJEXT): {$(VPATH)}prism_compile.h cont.$(OBJEXT): {$(VPATH)}ractor.h cont.$(OBJEXT): {$(VPATH)}ractor_core.h @@ -5074,7 +5074,9 @@ eval.$(OBJEXT): $(top_srcdir)/internal/thread.h eval.$(OBJEXT): $(top_srcdir)/internal/variable.h eval.$(OBJEXT): $(top_srcdir)/internal/vm.h eval.$(OBJEXT): $(top_srcdir)/internal/warnings.h +eval.$(OBJEXT): $(top_srcdir)/prism/ast.h eval.$(OBJEXT): $(top_srcdir)/prism/defines.h +eval.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h eval.$(OBJEXT): $(top_srcdir)/prism/encoding.h eval.$(OBJEXT): $(top_srcdir)/prism/node.h eval.$(OBJEXT): $(top_srcdir)/prism/options.h @@ -5094,6 +5096,7 @@ eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h +eval.$(OBJEXT): $(top_srcdir)/prism/version.h eval.$(OBJEXT): {$(VPATH)}assert.h eval.$(OBJEXT): {$(VPATH)}atomic.h eval.$(OBJEXT): {$(VPATH)}backward/2/assume.h @@ -5276,9 +5279,6 @@ eval.$(OBJEXT): {$(VPATH)}missing.h eval.$(OBJEXT): {$(VPATH)}node.h eval.$(OBJEXT): {$(VPATH)}onigmo.h eval.$(OBJEXT): {$(VPATH)}oniguruma.h -eval.$(OBJEXT): {$(VPATH)}prism/ast.h -eval.$(OBJEXT): {$(VPATH)}prism/diagnostic.h -eval.$(OBJEXT): {$(VPATH)}prism/version.h eval.$(OBJEXT): {$(VPATH)}prism_compile.h eval.$(OBJEXT): {$(VPATH)}probes.dmyh eval.$(OBJEXT): {$(VPATH)}probes.h @@ -5563,7 +5563,9 @@ gc.$(OBJEXT): $(top_srcdir)/internal/thread.h gc.$(OBJEXT): $(top_srcdir)/internal/variable.h gc.$(OBJEXT): $(top_srcdir)/internal/vm.h gc.$(OBJEXT): $(top_srcdir)/internal/warnings.h +gc.$(OBJEXT): $(top_srcdir)/prism/ast.h gc.$(OBJEXT): $(top_srcdir)/prism/defines.h +gc.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h gc.$(OBJEXT): $(top_srcdir)/prism/encoding.h gc.$(OBJEXT): $(top_srcdir)/prism/node.h gc.$(OBJEXT): $(top_srcdir)/prism/options.h @@ -5583,6 +5585,7 @@ gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h +gc.$(OBJEXT): $(top_srcdir)/prism/version.h gc.$(OBJEXT): {$(VPATH)}assert.h gc.$(OBJEXT): {$(VPATH)}atomic.h gc.$(OBJEXT): {$(VPATH)}backward/2/assume.h @@ -5767,9 +5770,6 @@ gc.$(OBJEXT): {$(VPATH)}missing.h gc.$(OBJEXT): {$(VPATH)}node.h gc.$(OBJEXT): {$(VPATH)}onigmo.h gc.$(OBJEXT): {$(VPATH)}oniguruma.h -gc.$(OBJEXT): {$(VPATH)}prism/ast.h -gc.$(OBJEXT): {$(VPATH)}prism/diagnostic.h -gc.$(OBJEXT): {$(VPATH)}prism/version.h gc.$(OBJEXT): {$(VPATH)}prism_compile.h gc.$(OBJEXT): {$(VPATH)}probes.dmyh gc.$(OBJEXT): {$(VPATH)}probes.h @@ -5825,7 +5825,9 @@ goruby.$(OBJEXT): $(top_srcdir)/internal/static_assert.h goruby.$(OBJEXT): $(top_srcdir)/internal/variable.h goruby.$(OBJEXT): $(top_srcdir)/internal/vm.h goruby.$(OBJEXT): $(top_srcdir)/internal/warnings.h +goruby.$(OBJEXT): $(top_srcdir)/prism/ast.h goruby.$(OBJEXT): $(top_srcdir)/prism/defines.h +goruby.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h goruby.$(OBJEXT): $(top_srcdir)/prism/encoding.h goruby.$(OBJEXT): $(top_srcdir)/prism/node.h goruby.$(OBJEXT): $(top_srcdir)/prism/options.h @@ -5845,6 +5847,7 @@ goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h +goruby.$(OBJEXT): $(top_srcdir)/prism/version.h goruby.$(OBJEXT): {$(VPATH)}assert.h goruby.$(OBJEXT): {$(VPATH)}atomic.h goruby.$(OBJEXT): {$(VPATH)}backward.h @@ -6024,9 +6027,6 @@ goruby.$(OBJEXT): {$(VPATH)}missing.h goruby.$(OBJEXT): {$(VPATH)}node.h goruby.$(OBJEXT): {$(VPATH)}onigmo.h goruby.$(OBJEXT): {$(VPATH)}oniguruma.h -goruby.$(OBJEXT): {$(VPATH)}prism/ast.h -goruby.$(OBJEXT): {$(VPATH)}prism/diagnostic.h -goruby.$(OBJEXT): {$(VPATH)}prism/version.h goruby.$(OBJEXT): {$(VPATH)}prism_compile.h goruby.$(OBJEXT): {$(VPATH)}ruby_assert.h goruby.$(OBJEXT): {$(VPATH)}ruby_atomic.h @@ -6072,7 +6072,9 @@ hash.$(OBJEXT): $(top_srcdir)/internal/time.h hash.$(OBJEXT): $(top_srcdir)/internal/variable.h hash.$(OBJEXT): $(top_srcdir)/internal/vm.h hash.$(OBJEXT): $(top_srcdir)/internal/warnings.h +hash.$(OBJEXT): $(top_srcdir)/prism/ast.h hash.$(OBJEXT): $(top_srcdir)/prism/defines.h +hash.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h hash.$(OBJEXT): $(top_srcdir)/prism/encoding.h hash.$(OBJEXT): $(top_srcdir)/prism/node.h hash.$(OBJEXT): $(top_srcdir)/prism/options.h @@ -6092,6 +6094,7 @@ hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h +hash.$(OBJEXT): $(top_srcdir)/prism/version.h hash.$(OBJEXT): {$(VPATH)}assert.h hash.$(OBJEXT): {$(VPATH)}atomic.h hash.$(OBJEXT): {$(VPATH)}backward/2/assume.h @@ -6272,9 +6275,6 @@ hash.$(OBJEXT): {$(VPATH)}missing.h hash.$(OBJEXT): {$(VPATH)}node.h hash.$(OBJEXT): {$(VPATH)}onigmo.h hash.$(OBJEXT): {$(VPATH)}oniguruma.h -hash.$(OBJEXT): {$(VPATH)}prism/ast.h -hash.$(OBJEXT): {$(VPATH)}prism/diagnostic.h -hash.$(OBJEXT): {$(VPATH)}prism/version.h hash.$(OBJEXT): {$(VPATH)}prism_compile.h hash.$(OBJEXT): {$(VPATH)}probes.dmyh hash.$(OBJEXT): {$(VPATH)}probes.h @@ -7149,7 +7149,9 @@ iseq.$(OBJEXT): $(top_srcdir)/internal/thread.h iseq.$(OBJEXT): $(top_srcdir)/internal/variable.h iseq.$(OBJEXT): $(top_srcdir)/internal/vm.h iseq.$(OBJEXT): $(top_srcdir)/internal/warnings.h +iseq.$(OBJEXT): $(top_srcdir)/prism/ast.h iseq.$(OBJEXT): $(top_srcdir)/prism/defines.h +iseq.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h iseq.$(OBJEXT): $(top_srcdir)/prism/encoding.h iseq.$(OBJEXT): $(top_srcdir)/prism/node.h iseq.$(OBJEXT): $(top_srcdir)/prism/options.h @@ -7157,6 +7159,7 @@ iseq.$(OBJEXT): $(top_srcdir)/prism/pack.h iseq.$(OBJEXT): $(top_srcdir)/prism/parser.h iseq.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h iseq.$(OBJEXT): $(top_srcdir)/prism/prism.h +iseq.$(OBJEXT): $(top_srcdir)/prism/prism.h iseq.$(OBJEXT): $(top_srcdir)/prism/regexp.h iseq.$(OBJEXT): $(top_srcdir)/prism/static_literals.h iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h @@ -7169,6 +7172,7 @@ iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h +iseq.$(OBJEXT): $(top_srcdir)/prism/version.h iseq.$(OBJEXT): {$(VPATH)}assert.h iseq.$(OBJEXT): {$(VPATH)}atomic.h iseq.$(OBJEXT): {$(VPATH)}backward/2/assume.h @@ -7352,10 +7356,6 @@ iseq.$(OBJEXT): {$(VPATH)}missing.h iseq.$(OBJEXT): {$(VPATH)}node.h iseq.$(OBJEXT): {$(VPATH)}onigmo.h iseq.$(OBJEXT): {$(VPATH)}oniguruma.h -iseq.$(OBJEXT): {$(VPATH)}prism/ast.h -iseq.$(OBJEXT): {$(VPATH)}prism/diagnostic.h -iseq.$(OBJEXT): {$(VPATH)}prism/prism.h -iseq.$(OBJEXT): {$(VPATH)}prism/version.h iseq.$(OBJEXT): {$(VPATH)}prism_compile.h iseq.$(OBJEXT): {$(VPATH)}ractor.h iseq.$(OBJEXT): {$(VPATH)}ruby_assert.h @@ -7393,7 +7393,9 @@ jit.$(OBJEXT): $(top_srcdir)/internal/static_assert.h jit.$(OBJEXT): $(top_srcdir)/internal/variable.h jit.$(OBJEXT): $(top_srcdir)/internal/vm.h jit.$(OBJEXT): $(top_srcdir)/internal/warnings.h +jit.$(OBJEXT): $(top_srcdir)/prism/ast.h jit.$(OBJEXT): $(top_srcdir)/prism/defines.h +jit.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h jit.$(OBJEXT): $(top_srcdir)/prism/encoding.h jit.$(OBJEXT): $(top_srcdir)/prism/node.h jit.$(OBJEXT): $(top_srcdir)/prism/options.h @@ -7413,6 +7415,7 @@ jit.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h jit.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h jit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h jit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h +jit.$(OBJEXT): $(top_srcdir)/prism/version.h jit.$(OBJEXT): {$(VPATH)}assert.h jit.$(OBJEXT): {$(VPATH)}atomic.h jit.$(OBJEXT): {$(VPATH)}backward/2/assume.h @@ -7594,9 +7597,6 @@ jit.$(OBJEXT): {$(VPATH)}missing.h jit.$(OBJEXT): {$(VPATH)}node.h jit.$(OBJEXT): {$(VPATH)}onigmo.h jit.$(OBJEXT): {$(VPATH)}oniguruma.h -jit.$(OBJEXT): {$(VPATH)}prism/ast.h -jit.$(OBJEXT): {$(VPATH)}prism/diagnostic.h -jit.$(OBJEXT): {$(VPATH)}prism/version.h jit.$(OBJEXT): {$(VPATH)}prism_compile.h jit.$(OBJEXT): {$(VPATH)}ruby_assert.h jit.$(OBJEXT): {$(VPATH)}ruby_atomic.h @@ -7646,7 +7646,9 @@ load.$(OBJEXT): $(top_srcdir)/internal/thread.h load.$(OBJEXT): $(top_srcdir)/internal/variable.h load.$(OBJEXT): $(top_srcdir)/internal/vm.h load.$(OBJEXT): $(top_srcdir)/internal/warnings.h +load.$(OBJEXT): $(top_srcdir)/prism/ast.h load.$(OBJEXT): $(top_srcdir)/prism/defines.h +load.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h load.$(OBJEXT): $(top_srcdir)/prism/encoding.h load.$(OBJEXT): $(top_srcdir)/prism/node.h load.$(OBJEXT): $(top_srcdir)/prism/options.h @@ -7666,6 +7668,7 @@ load.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h load.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h load.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h load.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h +load.$(OBJEXT): $(top_srcdir)/prism/version.h load.$(OBJEXT): {$(VPATH)}assert.h load.$(OBJEXT): {$(VPATH)}atomic.h load.$(OBJEXT): {$(VPATH)}backward/2/assume.h @@ -7845,9 +7848,6 @@ load.$(OBJEXT): {$(VPATH)}missing.h load.$(OBJEXT): {$(VPATH)}node.h load.$(OBJEXT): {$(VPATH)}onigmo.h load.$(OBJEXT): {$(VPATH)}oniguruma.h -load.$(OBJEXT): {$(VPATH)}prism/ast.h -load.$(OBJEXT): {$(VPATH)}prism/diagnostic.h -load.$(OBJEXT): {$(VPATH)}prism/version.h load.$(OBJEXT): {$(VPATH)}prism_compile.h load.$(OBJEXT): {$(VPATH)}probes.dmyh load.$(OBJEXT): {$(VPATH)}probes.h @@ -9000,7 +9000,9 @@ miniinit.$(OBJEXT): $(top_srcdir)/internal/static_assert.h miniinit.$(OBJEXT): $(top_srcdir)/internal/variable.h miniinit.$(OBJEXT): $(top_srcdir)/internal/vm.h miniinit.$(OBJEXT): $(top_srcdir)/internal/warnings.h +miniinit.$(OBJEXT): $(top_srcdir)/prism/ast.h miniinit.$(OBJEXT): $(top_srcdir)/prism/defines.h +miniinit.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h miniinit.$(OBJEXT): $(top_srcdir)/prism/encoding.h miniinit.$(OBJEXT): $(top_srcdir)/prism/node.h miniinit.$(OBJEXT): $(top_srcdir)/prism/options.h @@ -9020,6 +9022,7 @@ miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h +miniinit.$(OBJEXT): $(top_srcdir)/prism/version.h miniinit.$(OBJEXT): {$(VPATH)}array.rb miniinit.$(OBJEXT): {$(VPATH)}assert.h miniinit.$(OBJEXT): {$(VPATH)}ast.rb @@ -9215,9 +9218,6 @@ miniinit.$(OBJEXT): {$(VPATH)}oniguruma.h miniinit.$(OBJEXT): {$(VPATH)}pack.rb miniinit.$(OBJEXT): {$(VPATH)}pathname_builtin.rb miniinit.$(OBJEXT): {$(VPATH)}prelude.rb -miniinit.$(OBJEXT): {$(VPATH)}prism/ast.h -miniinit.$(OBJEXT): {$(VPATH)}prism/diagnostic.h -miniinit.$(OBJEXT): {$(VPATH)}prism/version.h miniinit.$(OBJEXT): {$(VPATH)}prism_compile.h miniinit.$(OBJEXT): {$(VPATH)}ractor.rb miniinit.$(OBJEXT): {$(VPATH)}ruby_assert.h @@ -11008,7 +11008,10 @@ pathname.$(OBJEXT): {$(VPATH)}st.h pathname.$(OBJEXT): {$(VPATH)}subst.h prism/api_node.$(OBJEXT): $(hdrdir)/ruby.h prism/api_node.$(OBJEXT): $(hdrdir)/ruby/ruby.h +prism/api_node.$(OBJEXT): $(top_srcdir)/prism/api_node.c +prism/api_node.$(OBJEXT): $(top_srcdir)/prism/ast.h prism/api_node.$(OBJEXT): $(top_srcdir)/prism/defines.h +prism/api_node.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h prism/api_node.$(OBJEXT): $(top_srcdir)/prism/encoding.h prism/api_node.$(OBJEXT): $(top_srcdir)/prism/extension.h prism/api_node.$(OBJEXT): $(top_srcdir)/prism/node.h @@ -11029,6 +11032,7 @@ prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h +prism/api_node.$(OBJEXT): $(top_srcdir)/prism/version.h prism/api_node.$(OBJEXT): {$(VPATH)}assert.h prism/api_node.$(OBJEXT): {$(VPATH)}backward/2/assume.h prism/api_node.$(OBJEXT): {$(VPATH)}backward/2/attributes.h @@ -11195,16 +11199,14 @@ prism/api_node.$(OBJEXT): {$(VPATH)}internal/xmalloc.h prism/api_node.$(OBJEXT): {$(VPATH)}missing.h prism/api_node.$(OBJEXT): {$(VPATH)}onigmo.h prism/api_node.$(OBJEXT): {$(VPATH)}oniguruma.h -prism/api_node.$(OBJEXT): {$(VPATH)}prism/api_node.c -prism/api_node.$(OBJEXT): {$(VPATH)}prism/ast.h -prism/api_node.$(OBJEXT): {$(VPATH)}prism/diagnostic.h -prism/api_node.$(OBJEXT): {$(VPATH)}prism/version.h prism/api_node.$(OBJEXT): {$(VPATH)}st.h prism/api_node.$(OBJEXT): {$(VPATH)}subst.h prism/api_pack.$(OBJEXT): $(hdrdir)/ruby.h prism/api_pack.$(OBJEXT): $(hdrdir)/ruby/ruby.h prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/api_pack.c +prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/ast.h prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/defines.h +prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/encoding.h prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/extension.h prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/node.h @@ -11225,6 +11227,7 @@ prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h +prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/version.h prism/api_pack.$(OBJEXT): {$(VPATH)}assert.h prism/api_pack.$(OBJEXT): {$(VPATH)}backward/2/assume.h prism/api_pack.$(OBJEXT): {$(VPATH)}backward/2/attributes.h @@ -11391,12 +11394,12 @@ prism/api_pack.$(OBJEXT): {$(VPATH)}internal/xmalloc.h prism/api_pack.$(OBJEXT): {$(VPATH)}missing.h prism/api_pack.$(OBJEXT): {$(VPATH)}onigmo.h prism/api_pack.$(OBJEXT): {$(VPATH)}oniguruma.h -prism/api_pack.$(OBJEXT): {$(VPATH)}prism/ast.h -prism/api_pack.$(OBJEXT): {$(VPATH)}prism/diagnostic.h -prism/api_pack.$(OBJEXT): {$(VPATH)}prism/version.h prism/api_pack.$(OBJEXT): {$(VPATH)}st.h prism/api_pack.$(OBJEXT): {$(VPATH)}subst.h +prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/ast.h prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/defines.h +prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/diagnostic.c +prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h @@ -11404,16 +11407,15 @@ prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h -prism/diagnostic.$(OBJEXT): {$(VPATH)}prism/ast.h -prism/diagnostic.$(OBJEXT): {$(VPATH)}prism/diagnostic.c -prism/diagnostic.$(OBJEXT): {$(VPATH)}prism/diagnostic.h prism/encoding.$(OBJEXT): $(top_srcdir)/prism/defines.h prism/encoding.$(OBJEXT): $(top_srcdir)/prism/encoding.c prism/encoding.$(OBJEXT): $(top_srcdir)/prism/encoding.h prism/encoding.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h prism/extension.$(OBJEXT): $(hdrdir)/ruby.h prism/extension.$(OBJEXT): $(hdrdir)/ruby/ruby.h +prism/extension.$(OBJEXT): $(top_srcdir)/prism/ast.h prism/extension.$(OBJEXT): $(top_srcdir)/prism/defines.h +prism/extension.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h prism/extension.$(OBJEXT): $(top_srcdir)/prism/encoding.h prism/extension.$(OBJEXT): $(top_srcdir)/prism/extension.c prism/extension.$(OBJEXT): $(top_srcdir)/prism/extension.h @@ -11435,6 +11437,7 @@ prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h +prism/extension.$(OBJEXT): $(top_srcdir)/prism/version.h prism/extension.$(OBJEXT): {$(VPATH)}assert.h prism/extension.$(OBJEXT): {$(VPATH)}backward/2/assume.h prism/extension.$(OBJEXT): {$(VPATH)}backward/2/attributes.h @@ -11601,13 +11604,13 @@ prism/extension.$(OBJEXT): {$(VPATH)}internal/xmalloc.h prism/extension.$(OBJEXT): {$(VPATH)}missing.h prism/extension.$(OBJEXT): {$(VPATH)}onigmo.h prism/extension.$(OBJEXT): {$(VPATH)}oniguruma.h -prism/extension.$(OBJEXT): {$(VPATH)}prism/ast.h -prism/extension.$(OBJEXT): {$(VPATH)}prism/diagnostic.h -prism/extension.$(OBJEXT): {$(VPATH)}prism/version.h prism/extension.$(OBJEXT): {$(VPATH)}st.h prism/extension.$(OBJEXT): {$(VPATH)}subst.h +prism/node.$(OBJEXT): $(top_srcdir)/prism/ast.h prism/node.$(OBJEXT): $(top_srcdir)/prism/defines.h +prism/node.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h prism/node.$(OBJEXT): $(top_srcdir)/prism/encoding.h +prism/node.$(OBJEXT): $(top_srcdir)/prism/node.c prism/node.$(OBJEXT): $(top_srcdir)/prism/node.h prism/node.$(OBJEXT): $(top_srcdir)/prism/options.h prism/node.$(OBJEXT): $(top_srcdir)/prism/pack.h @@ -11624,9 +11627,6 @@ prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h -prism/node.$(OBJEXT): {$(VPATH)}prism/ast.h -prism/node.$(OBJEXT): {$(VPATH)}prism/diagnostic.h -prism/node.$(OBJEXT): {$(VPATH)}prism/node.c prism/options.$(OBJEXT): $(top_srcdir)/prism/defines.h prism/options.$(OBJEXT): $(top_srcdir)/prism/options.c prism/options.$(OBJEXT): $(top_srcdir)/prism/options.h @@ -11636,10 +11636,12 @@ prism/options.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h prism/pack.$(OBJEXT): $(top_srcdir)/prism/defines.h prism/pack.$(OBJEXT): $(top_srcdir)/prism/pack.c prism/pack.$(OBJEXT): $(top_srcdir)/prism/pack.h +prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/ast.h prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/defines.h prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/encoding.h prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/options.h prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/parser.h +prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/prettyprint.c prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/static_literals.h prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h @@ -11650,9 +11652,9 @@ prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h -prism/prettyprint.$(OBJEXT): {$(VPATH)}prism/ast.h -prism/prettyprint.$(OBJEXT): {$(VPATH)}prism/prettyprint.c +prism/prism.$(OBJEXT): $(top_srcdir)/prism/ast.h prism/prism.$(OBJEXT): $(top_srcdir)/prism/defines.h +prism/prism.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h prism/prism.$(OBJEXT): $(top_srcdir)/prism/encoding.h prism/prism.$(OBJEXT): $(top_srcdir)/prism/node.h prism/prism.$(OBJEXT): $(top_srcdir)/prism/options.h @@ -11674,9 +11676,8 @@ prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h prism/prism.$(OBJEXT): $(top_srcdir)/prism/version.h -prism/prism.$(OBJEXT): {$(VPATH)}prism/ast.h -prism/prism.$(OBJEXT): {$(VPATH)}prism/diagnostic.h -prism/prism.$(OBJEXT): {$(VPATH)}prism/version.h +prism/prism.$(OBJEXT): $(top_srcdir)/prism/version.h +prism/regexp.$(OBJEXT): $(top_srcdir)/prism/ast.h prism/regexp.$(OBJEXT): $(top_srcdir)/prism/defines.h prism/regexp.$(OBJEXT): $(top_srcdir)/prism/encoding.h prism/regexp.$(OBJEXT): $(top_srcdir)/prism/options.h @@ -11693,8 +11694,9 @@ prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h -prism/regexp.$(OBJEXT): {$(VPATH)}prism/ast.h +prism/serialize.$(OBJEXT): $(top_srcdir)/prism/ast.h prism/serialize.$(OBJEXT): $(top_srcdir)/prism/defines.h +prism/serialize.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h prism/serialize.$(OBJEXT): $(top_srcdir)/prism/encoding.h prism/serialize.$(OBJEXT): $(top_srcdir)/prism/node.h prism/serialize.$(OBJEXT): $(top_srcdir)/prism/options.h @@ -11703,6 +11705,7 @@ prism/serialize.$(OBJEXT): $(top_srcdir)/prism/parser.h prism/serialize.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h prism/serialize.$(OBJEXT): $(top_srcdir)/prism/prism.h prism/serialize.$(OBJEXT): $(top_srcdir)/prism/regexp.h +prism/serialize.$(OBJEXT): $(top_srcdir)/prism/serialize.c prism/serialize.$(OBJEXT): $(top_srcdir)/prism/static_literals.h prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h @@ -11714,10 +11717,8 @@ prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h -prism/serialize.$(OBJEXT): {$(VPATH)}prism/ast.h -prism/serialize.$(OBJEXT): {$(VPATH)}prism/diagnostic.h -prism/serialize.$(OBJEXT): {$(VPATH)}prism/serialize.c -prism/serialize.$(OBJEXT): {$(VPATH)}prism/version.h +prism/serialize.$(OBJEXT): $(top_srcdir)/prism/version.h +prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/ast.h prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/defines.h prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/encoding.h prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/node.h @@ -11733,16 +11734,15 @@ prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h -prism/static_literals.$(OBJEXT): {$(VPATH)}prism/ast.h +prism/token_type.$(OBJEXT): $(top_srcdir)/prism/ast.h prism/token_type.$(OBJEXT): $(top_srcdir)/prism/defines.h +prism/token_type.$(OBJEXT): $(top_srcdir)/prism/token_type.c prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h -prism/token_type.$(OBJEXT): {$(VPATH)}prism/ast.h -prism/token_type.$(OBJEXT): {$(VPATH)}prism/token_type.c prism/util/pm_buffer.$(OBJEXT): $(top_srcdir)/prism/defines.h prism/util/pm_buffer.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.c prism/util/pm_buffer.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h @@ -11764,6 +11764,7 @@ prism/util/pm_integer.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h prism/util/pm_list.$(OBJEXT): $(top_srcdir)/prism/defines.h prism/util/pm_list.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.c prism/util/pm_list.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h +prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/ast.h prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/defines.h prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/encoding.h prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/parser.h @@ -11774,7 +11775,6 @@ prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h -prism/util/pm_memchr.$(OBJEXT): {$(VPATH)}prism/ast.h prism/util/pm_newline_list.$(OBJEXT): $(top_srcdir)/prism/defines.h prism/util/pm_newline_list.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.c prism/util/pm_newline_list.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h @@ -11784,7 +11784,9 @@ prism/util/pm_string.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h prism/util/pm_strncasecmp.$(OBJEXT): $(top_srcdir)/prism/defines.h prism/util/pm_strncasecmp.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.c prism/util/pm_strncasecmp.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h +prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/ast.h prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/defines.h +prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/encoding.h prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/options.h prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/parser.h @@ -11799,11 +11801,11 @@ prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.c prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h -prism/util/pm_strpbrk.$(OBJEXT): {$(VPATH)}prism/ast.h -prism/util/pm_strpbrk.$(OBJEXT): {$(VPATH)}prism/diagnostic.h prism_init.$(OBJEXT): $(hdrdir)/ruby.h prism_init.$(OBJEXT): $(hdrdir)/ruby/ruby.h +prism_init.$(OBJEXT): $(top_srcdir)/prism/ast.h prism_init.$(OBJEXT): $(top_srcdir)/prism/defines.h +prism_init.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h prism_init.$(OBJEXT): $(top_srcdir)/prism/encoding.h prism_init.$(OBJEXT): $(top_srcdir)/prism/extension.h prism_init.$(OBJEXT): $(top_srcdir)/prism/node.h @@ -11824,6 +11826,7 @@ prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h +prism_init.$(OBJEXT): $(top_srcdir)/prism/version.h prism_init.$(OBJEXT): $(top_srcdir)/prism_init.c prism_init.$(OBJEXT): {$(VPATH)}assert.h prism_init.$(OBJEXT): {$(VPATH)}backward/2/assume.h @@ -11991,9 +11994,6 @@ prism_init.$(OBJEXT): {$(VPATH)}internal/xmalloc.h prism_init.$(OBJEXT): {$(VPATH)}missing.h prism_init.$(OBJEXT): {$(VPATH)}onigmo.h prism_init.$(OBJEXT): {$(VPATH)}oniguruma.h -prism_init.$(OBJEXT): {$(VPATH)}prism/ast.h -prism_init.$(OBJEXT): {$(VPATH)}prism/diagnostic.h -prism_init.$(OBJEXT): {$(VPATH)}prism/version.h prism_init.$(OBJEXT): {$(VPATH)}prism_init.c prism_init.$(OBJEXT): {$(VPATH)}st.h prism_init.$(OBJEXT): {$(VPATH)}subst.h @@ -12024,7 +12024,9 @@ proc.$(OBJEXT): $(top_srcdir)/internal/symbol.h proc.$(OBJEXT): $(top_srcdir)/internal/variable.h proc.$(OBJEXT): $(top_srcdir)/internal/vm.h proc.$(OBJEXT): $(top_srcdir)/internal/warnings.h +proc.$(OBJEXT): $(top_srcdir)/prism/ast.h proc.$(OBJEXT): $(top_srcdir)/prism/defines.h +proc.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h proc.$(OBJEXT): $(top_srcdir)/prism/encoding.h proc.$(OBJEXT): $(top_srcdir)/prism/node.h proc.$(OBJEXT): $(top_srcdir)/prism/options.h @@ -12044,6 +12046,7 @@ proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h +proc.$(OBJEXT): $(top_srcdir)/prism/version.h proc.$(OBJEXT): {$(VPATH)}assert.h proc.$(OBJEXT): {$(VPATH)}atomic.h proc.$(OBJEXT): {$(VPATH)}backward/2/assume.h @@ -12221,9 +12224,6 @@ proc.$(OBJEXT): {$(VPATH)}missing.h proc.$(OBJEXT): {$(VPATH)}node.h proc.$(OBJEXT): {$(VPATH)}onigmo.h proc.$(OBJEXT): {$(VPATH)}oniguruma.h -proc.$(OBJEXT): {$(VPATH)}prism/ast.h -proc.$(OBJEXT): {$(VPATH)}prism/diagnostic.h -proc.$(OBJEXT): {$(VPATH)}prism/version.h proc.$(OBJEXT): {$(VPATH)}prism_compile.h proc.$(OBJEXT): {$(VPATH)}proc.c proc.$(OBJEXT): {$(VPATH)}ractor.h @@ -14578,7 +14578,9 @@ ruby.$(OBJEXT): $(top_srcdir)/internal/thread.h ruby.$(OBJEXT): $(top_srcdir)/internal/variable.h ruby.$(OBJEXT): $(top_srcdir)/internal/vm.h ruby.$(OBJEXT): $(top_srcdir)/internal/warnings.h +ruby.$(OBJEXT): $(top_srcdir)/prism/ast.h ruby.$(OBJEXT): $(top_srcdir)/prism/defines.h +ruby.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h ruby.$(OBJEXT): $(top_srcdir)/prism/encoding.h ruby.$(OBJEXT): $(top_srcdir)/prism/node.h ruby.$(OBJEXT): $(top_srcdir)/prism/options.h @@ -14598,6 +14600,7 @@ ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h +ruby.$(OBJEXT): $(top_srcdir)/prism/version.h ruby.$(OBJEXT): {$(VPATH)}assert.h ruby.$(OBJEXT): {$(VPATH)}atomic.h ruby.$(OBJEXT): {$(VPATH)}backward/2/assume.h @@ -14777,9 +14780,6 @@ ruby.$(OBJEXT): {$(VPATH)}missing.h ruby.$(OBJEXT): {$(VPATH)}node.h ruby.$(OBJEXT): {$(VPATH)}onigmo.h ruby.$(OBJEXT): {$(VPATH)}oniguruma.h -ruby.$(OBJEXT): {$(VPATH)}prism/ast.h -ruby.$(OBJEXT): {$(VPATH)}prism/diagnostic.h -ruby.$(OBJEXT): {$(VPATH)}prism/version.h ruby.$(OBJEXT): {$(VPATH)}prism_compile.h ruby.$(OBJEXT): {$(VPATH)}ruby.c ruby.$(OBJEXT): {$(VPATH)}ruby_assert.h @@ -17280,7 +17280,9 @@ thread.$(OBJEXT): $(top_srcdir)/internal/time.h thread.$(OBJEXT): $(top_srcdir)/internal/variable.h thread.$(OBJEXT): $(top_srcdir)/internal/vm.h thread.$(OBJEXT): $(top_srcdir)/internal/warnings.h +thread.$(OBJEXT): $(top_srcdir)/prism/ast.h thread.$(OBJEXT): $(top_srcdir)/prism/defines.h +thread.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h thread.$(OBJEXT): $(top_srcdir)/prism/encoding.h thread.$(OBJEXT): $(top_srcdir)/prism/node.h thread.$(OBJEXT): $(top_srcdir)/prism/options.h @@ -17300,6 +17302,7 @@ thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h +thread.$(OBJEXT): $(top_srcdir)/prism/version.h thread.$(OBJEXT): {$(VPATH)}$(COROUTINE_H) thread.$(OBJEXT): {$(VPATH)}assert.h thread.$(OBJEXT): {$(VPATH)}atomic.h @@ -17483,9 +17486,6 @@ thread.$(OBJEXT): {$(VPATH)}missing.h thread.$(OBJEXT): {$(VPATH)}node.h thread.$(OBJEXT): {$(VPATH)}onigmo.h thread.$(OBJEXT): {$(VPATH)}oniguruma.h -thread.$(OBJEXT): {$(VPATH)}prism/ast.h -thread.$(OBJEXT): {$(VPATH)}prism/diagnostic.h -thread.$(OBJEXT): {$(VPATH)}prism/version.h thread.$(OBJEXT): {$(VPATH)}prism_compile.h thread.$(OBJEXT): {$(VPATH)}ractor.h thread.$(OBJEXT): {$(VPATH)}ractor_core.h @@ -18568,7 +18568,9 @@ vm.$(OBJEXT): $(top_srcdir)/internal/transcode.h vm.$(OBJEXT): $(top_srcdir)/internal/variable.h vm.$(OBJEXT): $(top_srcdir)/internal/vm.h vm.$(OBJEXT): $(top_srcdir)/internal/warnings.h +vm.$(OBJEXT): $(top_srcdir)/prism/ast.h vm.$(OBJEXT): $(top_srcdir)/prism/defines.h +vm.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h vm.$(OBJEXT): $(top_srcdir)/prism/encoding.h vm.$(OBJEXT): $(top_srcdir)/prism/node.h vm.$(OBJEXT): $(top_srcdir)/prism/options.h @@ -18588,6 +18590,7 @@ vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h +vm.$(OBJEXT): $(top_srcdir)/prism/version.h vm.$(OBJEXT): {$(VPATH)}assert.h vm.$(OBJEXT): {$(VPATH)}atomic.h vm.$(OBJEXT): {$(VPATH)}backward/2/assume.h @@ -18772,9 +18775,6 @@ vm.$(OBJEXT): {$(VPATH)}missing.h vm.$(OBJEXT): {$(VPATH)}node.h vm.$(OBJEXT): {$(VPATH)}onigmo.h vm.$(OBJEXT): {$(VPATH)}oniguruma.h -vm.$(OBJEXT): {$(VPATH)}prism/ast.h -vm.$(OBJEXT): {$(VPATH)}prism/diagnostic.h -vm.$(OBJEXT): {$(VPATH)}prism/version.h vm.$(OBJEXT): {$(VPATH)}prism_compile.h vm.$(OBJEXT): {$(VPATH)}probes.dmyh vm.$(OBJEXT): {$(VPATH)}probes.h @@ -18832,7 +18832,9 @@ vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/string.h vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/variable.h vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/vm.h vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/warnings.h +vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/ast.h vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/defines.h +vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/encoding.h vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/node.h vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/options.h @@ -18852,6 +18854,7 @@ vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h +vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/version.h vm_backtrace.$(OBJEXT): {$(VPATH)}assert.h vm_backtrace.$(OBJEXT): {$(VPATH)}atomic.h vm_backtrace.$(OBJEXT): {$(VPATH)}backward/2/assume.h @@ -19030,9 +19033,6 @@ vm_backtrace.$(OBJEXT): {$(VPATH)}missing.h vm_backtrace.$(OBJEXT): {$(VPATH)}node.h vm_backtrace.$(OBJEXT): {$(VPATH)}onigmo.h vm_backtrace.$(OBJEXT): {$(VPATH)}oniguruma.h -vm_backtrace.$(OBJEXT): {$(VPATH)}prism/ast.h -vm_backtrace.$(OBJEXT): {$(VPATH)}prism/diagnostic.h -vm_backtrace.$(OBJEXT): {$(VPATH)}prism/version.h vm_backtrace.$(OBJEXT): {$(VPATH)}prism_compile.h vm_backtrace.$(OBJEXT): {$(VPATH)}ruby_assert.h vm_backtrace.$(OBJEXT): {$(VPATH)}ruby_atomic.h @@ -19065,7 +19065,9 @@ vm_dump.$(OBJEXT): $(top_srcdir)/internal/static_assert.h vm_dump.$(OBJEXT): $(top_srcdir)/internal/variable.h vm_dump.$(OBJEXT): $(top_srcdir)/internal/vm.h vm_dump.$(OBJEXT): $(top_srcdir)/internal/warnings.h +vm_dump.$(OBJEXT): $(top_srcdir)/prism/ast.h vm_dump.$(OBJEXT): $(top_srcdir)/prism/defines.h +vm_dump.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h vm_dump.$(OBJEXT): $(top_srcdir)/prism/encoding.h vm_dump.$(OBJEXT): $(top_srcdir)/prism/node.h vm_dump.$(OBJEXT): $(top_srcdir)/prism/options.h @@ -19085,6 +19087,7 @@ vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h +vm_dump.$(OBJEXT): $(top_srcdir)/prism/version.h vm_dump.$(OBJEXT): {$(VPATH)}addr2line.h vm_dump.$(OBJEXT): {$(VPATH)}assert.h vm_dump.$(OBJEXT): {$(VPATH)}atomic.h @@ -19262,9 +19265,6 @@ vm_dump.$(OBJEXT): {$(VPATH)}missing.h vm_dump.$(OBJEXT): {$(VPATH)}node.h vm_dump.$(OBJEXT): {$(VPATH)}onigmo.h vm_dump.$(OBJEXT): {$(VPATH)}oniguruma.h -vm_dump.$(OBJEXT): {$(VPATH)}prism/ast.h -vm_dump.$(OBJEXT): {$(VPATH)}prism/diagnostic.h -vm_dump.$(OBJEXT): {$(VPATH)}prism/version.h vm_dump.$(OBJEXT): {$(VPATH)}prism_compile.h vm_dump.$(OBJEXT): {$(VPATH)}procstat_vm.c vm_dump.$(OBJEXT): {$(VPATH)}ractor.h @@ -19514,7 +19514,9 @@ vm_trace.$(OBJEXT): $(top_srcdir)/internal/thread.h vm_trace.$(OBJEXT): $(top_srcdir)/internal/variable.h vm_trace.$(OBJEXT): $(top_srcdir)/internal/vm.h vm_trace.$(OBJEXT): $(top_srcdir)/internal/warnings.h +vm_trace.$(OBJEXT): $(top_srcdir)/prism/ast.h vm_trace.$(OBJEXT): $(top_srcdir)/prism/defines.h +vm_trace.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h vm_trace.$(OBJEXT): $(top_srcdir)/prism/encoding.h vm_trace.$(OBJEXT): $(top_srcdir)/prism/node.h vm_trace.$(OBJEXT): $(top_srcdir)/prism/options.h @@ -19534,6 +19536,7 @@ vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h +vm_trace.$(OBJEXT): $(top_srcdir)/prism/version.h vm_trace.$(OBJEXT): {$(VPATH)}assert.h vm_trace.$(OBJEXT): {$(VPATH)}atomic.h vm_trace.$(OBJEXT): {$(VPATH)}backward/2/assume.h @@ -19713,9 +19716,6 @@ vm_trace.$(OBJEXT): {$(VPATH)}missing.h vm_trace.$(OBJEXT): {$(VPATH)}node.h vm_trace.$(OBJEXT): {$(VPATH)}onigmo.h vm_trace.$(OBJEXT): {$(VPATH)}oniguruma.h -vm_trace.$(OBJEXT): {$(VPATH)}prism/ast.h -vm_trace.$(OBJEXT): {$(VPATH)}prism/diagnostic.h -vm_trace.$(OBJEXT): {$(VPATH)}prism/version.h vm_trace.$(OBJEXT): {$(VPATH)}prism_compile.h vm_trace.$(OBJEXT): {$(VPATH)}ractor.h vm_trace.$(OBJEXT): {$(VPATH)}ruby_assert.h @@ -19962,7 +19962,9 @@ yjit.$(OBJEXT): $(top_srcdir)/internal/string.h yjit.$(OBJEXT): $(top_srcdir)/internal/variable.h yjit.$(OBJEXT): $(top_srcdir)/internal/vm.h yjit.$(OBJEXT): $(top_srcdir)/internal/warnings.h +yjit.$(OBJEXT): $(top_srcdir)/prism/ast.h yjit.$(OBJEXT): $(top_srcdir)/prism/defines.h +yjit.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h yjit.$(OBJEXT): $(top_srcdir)/prism/encoding.h yjit.$(OBJEXT): $(top_srcdir)/prism/node.h yjit.$(OBJEXT): $(top_srcdir)/prism/options.h @@ -19982,6 +19984,7 @@ yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h +yjit.$(OBJEXT): $(top_srcdir)/prism/version.h yjit.$(OBJEXT): {$(VPATH)}assert.h yjit.$(OBJEXT): {$(VPATH)}atomic.h yjit.$(OBJEXT): {$(VPATH)}backward/2/assume.h @@ -20164,9 +20167,6 @@ yjit.$(OBJEXT): {$(VPATH)}missing.h yjit.$(OBJEXT): {$(VPATH)}node.h yjit.$(OBJEXT): {$(VPATH)}onigmo.h yjit.$(OBJEXT): {$(VPATH)}oniguruma.h -yjit.$(OBJEXT): {$(VPATH)}prism/ast.h -yjit.$(OBJEXT): {$(VPATH)}prism/diagnostic.h -yjit.$(OBJEXT): {$(VPATH)}prism/version.h yjit.$(OBJEXT): {$(VPATH)}prism_compile.h yjit.$(OBJEXT): {$(VPATH)}probes.dmyh yjit.$(OBJEXT): {$(VPATH)}probes.h @@ -20214,7 +20214,9 @@ zjit.$(OBJEXT): $(top_srcdir)/internal/string.h zjit.$(OBJEXT): $(top_srcdir)/internal/variable.h zjit.$(OBJEXT): $(top_srcdir)/internal/vm.h zjit.$(OBJEXT): $(top_srcdir)/internal/warnings.h +zjit.$(OBJEXT): $(top_srcdir)/prism/ast.h zjit.$(OBJEXT): $(top_srcdir)/prism/defines.h +zjit.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h zjit.$(OBJEXT): $(top_srcdir)/prism/encoding.h zjit.$(OBJEXT): $(top_srcdir)/prism/node.h zjit.$(OBJEXT): $(top_srcdir)/prism/options.h @@ -20234,6 +20236,7 @@ zjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h zjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h zjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h zjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h +zjit.$(OBJEXT): $(top_srcdir)/prism/version.h zjit.$(OBJEXT): {$(VPATH)}assert.h zjit.$(OBJEXT): {$(VPATH)}atomic.h zjit.$(OBJEXT): {$(VPATH)}backward/2/assume.h @@ -20415,9 +20418,6 @@ zjit.$(OBJEXT): {$(VPATH)}missing.h zjit.$(OBJEXT): {$(VPATH)}node.h zjit.$(OBJEXT): {$(VPATH)}onigmo.h zjit.$(OBJEXT): {$(VPATH)}oniguruma.h -zjit.$(OBJEXT): {$(VPATH)}prism/ast.h -zjit.$(OBJEXT): {$(VPATH)}prism/diagnostic.h -zjit.$(OBJEXT): {$(VPATH)}prism/version.h zjit.$(OBJEXT): {$(VPATH)}prism_compile.h zjit.$(OBJEXT): {$(VPATH)}probes.dmyh zjit.$(OBJEXT): {$(VPATH)}probes.h diff --git a/doc/string/index.rdoc b/doc/string/index.rdoc index ce09a37bdfae27..cc34bc68e6b6bd 100644 --- a/doc/string/index.rdoc +++ b/doc/string/index.rdoc @@ -1,31 +1,35 @@ -Returns the integer index of the first match for the given argument, -or +nil+ if none found; -the search of +self+ is forward, and begins at position +offset+ (in characters). +Returns the integer position of the first substring that matches the given argument +pattern+, +or +nil+ if none found. -With string argument +substring+, +When +pattern+ is a string, returns the index of the first matching substring in +self+: 'foo'.index('f') # => 0 'foo'.index('o') # => 1 'foo'.index('oo') # => 1 'foo'.index('ooo') # => nil - 'тест'.index('с') # => 2 - 'こんにちは'.index('ち') # => 3 + 'тест'.index('с') # => 2 # Characters, not bytes. + 'こんにちは'.index('ち') # => 3 -With Regexp argument +regexp+, returns the index of the first match in +self+: +When +pattern is a Regexp, returns the index of the first match in +self+: 'foo'.index(/o./) # => 1 'foo'.index(/.o/) # => 0 -With positive integer +offset+, begins the search at position +offset+: +When +offset+ is non-negative, begins the search at position +offset+; +the returned index is relative to the beginning of +self+: - 'foo'.index('o', 1) # => 1 - 'foo'.index('o', 2) # => 2 - 'foo'.index('o', 3) # => nil + 'bar'.index('r', 0) # => 2 + 'bar'.index('r', 1) # => 2 + 'bar'.index('r', 2) # => 2 + 'bar'.index('r', 3) # => nil + 'bar'.index(/[r-z]/, 0) # => 2 'тест'.index('с', 1) # => 2 - 'こんにちは'.index('ち', 2) # => 3 + 'тест'.index('с', 2) # => 2 + 'тест'.index('с', 3) # => nil # Offset in characters, not bytes. + 'こんにちは'.index('ち', 2) # => 3 -With negative integer +offset+, selects the search position by counting backward +With negative integer argument +offset+, selects the search position by counting backward from the end of +self+: 'foo'.index('o', -1) # => 2 @@ -35,4 +39,4 @@ from the end of +self+: 'foo'.index(/o./, -2) # => 1 'foo'.index(/.o/, -2) # => 1 -Related: String#rindex. +Related: see {Querying}[rdoc-ref:String@Querying]. diff --git a/ext/-test-/file/fs.c b/ext/-test-/file/fs.c index eb17e9768ef6f1..bc5bac407df4fb 100644 --- a/ext/-test-/file/fs.c +++ b/ext/-test-/file/fs.c @@ -105,6 +105,9 @@ get_noatime_p(VALUE self, VALUE str) void Init_fs(VALUE module) { +#ifdef HAVE_RB_EXT_RACTOR_SAFE + rb_ext_ractor_safe(true); +#endif VALUE fs = rb_define_module_under(module, "Fs"); rb_define_module_function(fs, "fsname", get_fsname, 1); rb_define_module_function(fs, "noatime?", get_noatime_p, 1); diff --git a/ext/-test-/integer/init.c b/ext/-test-/integer/init.c index fc256ea16bf46e..483af73177eec3 100644 --- a/ext/-test-/integer/init.c +++ b/ext/-test-/integer/init.c @@ -5,6 +5,9 @@ void Init_integer(void) { +#ifdef HAVE_RB_EXT_RACTOR_SAFE + rb_ext_ractor_safe(true); +#endif VALUE mBug = rb_define_module("Bug"); VALUE klass = rb_define_class_under(mBug, "Integer", rb_cObject); TEST_INIT_FUNCS(init); diff --git a/ext/-test-/iter/break.c b/ext/-test-/iter/break.c index 4d43c5d0cf4782..b0b240a47537a2 100644 --- a/ext/-test-/iter/break.c +++ b/ext/-test-/iter/break.c @@ -19,6 +19,10 @@ iter_break_value(VALUE self, VALUE val) void Init_break(VALUE klass) { +#ifdef HAVE_RB_EXT_RACTOR_SAFE + // Mark this extension as Ractor-safe. + rb_ext_ractor_safe(true); +#endif VALUE breakable = rb_define_module_under(klass, "Breakable"); rb_define_module_function(breakable, "iter_break", iter_break, 0); rb_define_module_function(breakable, "iter_break_value", iter_break_value, 1); diff --git a/ext/-test-/iter/init.c b/ext/-test-/iter/init.c index a074ec46a982d4..2eea461ddec71e 100644 --- a/ext/-test-/iter/init.c +++ b/ext/-test-/iter/init.c @@ -5,6 +5,11 @@ void Init_iter(void) { + +#ifdef HAVE_RB_EXT_RACTOR_SAFE + // Mark this extension as Ractor-safe. + rb_ext_ractor_safe(true); +#endif VALUE mBug = rb_define_module("Bug"); VALUE klass = rb_define_module_under(mBug, "Iter"); TEST_INIT_FUNCS(init); diff --git a/ext/-test-/iter/yield.c b/ext/-test-/iter/yield.c index 0f6f3e87eb7731..e47166be1db9b6 100644 --- a/ext/-test-/iter/yield.c +++ b/ext/-test-/iter/yield.c @@ -10,6 +10,11 @@ yield_block(int argc, VALUE *argv, VALUE self) void Init_yield(VALUE klass) { + +#ifdef HAVE_RB_EXT_RACTOR_SAFE + // Mark this extension as Ractor-safe. + rb_ext_ractor_safe(true); +#endif VALUE yield = rb_define_module_under(klass, "Yield"); rb_define_method(yield, "yield_block", yield_block, -1); diff --git a/ext/-test-/rb_call_super_kw/rb_call_super_kw.c b/ext/-test-/rb_call_super_kw/rb_call_super_kw.c index 61681ed7334498..3607e008c3dccf 100644 --- a/ext/-test-/rb_call_super_kw/rb_call_super_kw.c +++ b/ext/-test-/rb_call_super_kw/rb_call_super_kw.c @@ -9,6 +9,10 @@ rb_call_super_kw_m(int argc, VALUE *argv, VALUE self) void Init_rb_call_super_kw(void) { +#ifdef HAVE_RB_EXT_RACTOR_SAFE + // Mark this extension as Ractor-safe. + rb_ext_ractor_safe(true); +#endif VALUE module = rb_define_module("Bug"); module = rb_define_module_under(module, "RbCallSuperKw"); rb_define_method(module, "m", rb_call_super_kw_m, -1); diff --git a/ext/json/generator/generator.c b/ext/json/generator/generator.c index 5248a9e26aae3e..9c6ed930495a51 100644 --- a/ext/json/generator/generator.c +++ b/ext/json/generator/generator.c @@ -137,8 +137,8 @@ static inline FORCE_INLINE void search_flush(search_state *search) { // Do not remove this conditional without profiling, specifically escape-heavy text. // escape_UTF8_char_basic will advance search->ptr and search->cursor (effectively a search_flush). - // For back-to-back characters that need to be escaped, specifcally for the SIMD code paths, this method - // will be called just before calling escape_UTF8_char_basic. There will be no characers to append for the + // For back-to-back characters that need to be escaped, specifically for the SIMD code paths, this method + // will be called just before calling escape_UTF8_char_basic. There will be no characters to append for the // consecutive characters that need to be escaped. While the fbuffer_append is a no-op if // nothing needs to be flushed, we can save a few memory references with this conditional. if (search->ptr > search->cursor) { diff --git a/ext/json/lib/json.rb b/ext/json/lib/json.rb index 735f2380667daa..0ebff2f948af56 100644 --- a/ext/json/lib/json.rb +++ b/ext/json/lib/json.rb @@ -133,7 +133,7 @@ # When not specified: # # The last value is used and a deprecation warning emitted. # JSON.parse('{"a": 1, "a":2}') => {"a" => 2} -# # waring: detected duplicate keys in JSON object. +# # warning: detected duplicate keys in JSON object. # # This will raise an error in json 3.0 unless enabled via `allow_duplicate_key: true` # # When set to `+true+` diff --git a/ext/json/lib/json/add/string.rb b/ext/json/lib/json/add/string.rb index 46f07967cd624d..9c3bde27fbcf37 100644 --- a/ext/json/lib/json/add/string.rb +++ b/ext/json/lib/json/add/string.rb @@ -5,7 +5,7 @@ class String # call-seq: json_create(o) - # + # # Raw Strings are JSON Objects (the raw bytes are stored in an array for the # key "raw"). The Ruby String can be created by this class method. def self.json_create(object) @@ -13,7 +13,7 @@ def self.json_create(object) end # call-seq: to_json_raw_object() - # + # # This method creates a raw object hash, that can be nested into # other data structures and will be generated as a raw string. This # method should be used, if you want to convert raw strings to JSON @@ -26,10 +26,10 @@ def to_json_raw_object end # call-seq: to_json_raw(*args) - # + # # This method creates a JSON text from the result of a call to # to_json_raw_object of this String. def to_json_raw(...) to_json_raw_object.to_json(...) end -end \ No newline at end of file +end diff --git a/ext/json/lib/json/common.rb b/ext/json/lib/json/common.rb index 9a878cead9f6a3..e99d152a884898 100644 --- a/ext/json/lib/json/common.rb +++ b/ext/json/lib/json/common.rb @@ -1002,7 +1002,7 @@ class Coder # See {Parsing Options}[#module-JSON-label-Parsing+Options], and {Generating Options}[#module-JSON-label-Generating+Options]. # # For generation, the strict: true option is always set. When a Ruby object with no native \JSON counterpart is - # encoutered, the block provided to the initialize method is invoked, and must return a Ruby object that has a native + # encountered, the block provided to the initialize method is invoked, and must return a Ruby object that has a native # \JSON counterpart: # # module MyApp diff --git a/ext/json/parser/parser.c b/ext/json/parser/parser.c index ab9d6c205e69b2..1e6ee753f0cf4b 100644 --- a/ext/json/parser/parser.c +++ b/ext/json/parser/parser.c @@ -1265,7 +1265,7 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config) break; } - raise_parse_error("unreacheable: %s", state); + raise_parse_error("unreachable: %s", state); } static void json_ensure_eof(JSON_ParserState *state) diff --git a/gc.c b/gc.c index 160398f9a6a661..c2fc681253aa36 100644 --- a/gc.c +++ b/gc.c @@ -4698,19 +4698,22 @@ rb_raw_obj_info_buitin_type(char *const buff, const size_t buff_size, const VALU APPEND_S("shared -> "); rb_raw_obj_info(BUFF_ARGS, ARY_SHARED_ROOT(obj)); } - else if (ARY_EMBED_P(obj)) { - APPEND_F("[%s%s] len: %ld (embed)", - C(ARY_EMBED_P(obj), "E"), - C(ARY_SHARED_P(obj), "S"), - RARRAY_LEN(obj)); - } else { - APPEND_F("[%s%s] len: %ld, capa:%ld ptr:%p", - C(ARY_EMBED_P(obj), "E"), + APPEND_F("[%s%s%s] ", + C(ARY_EMBED_P(obj), "E"), C(ARY_SHARED_P(obj), "S"), - RARRAY_LEN(obj), - ARY_EMBED_P(obj) ? -1L : RARRAY(obj)->as.heap.aux.capa, - (void *)RARRAY_CONST_PTR(obj)); + C(ARY_SHARED_ROOT_P(obj), "R")); + + if (ARY_EMBED_P(obj)) { + APPEND_F("len: %ld (embed)", + RARRAY_LEN(obj)); + } + else { + APPEND_F("len: %ld, capa:%ld ptr:%p", + RARRAY_LEN(obj), + RARRAY(obj)->as.heap.aux.capa, + (void *)RARRAY_CONST_PTR(obj)); + } } break; case T_STRING: { diff --git a/gc.rb b/gc.rb index 883206dde85323..f5e62eed6058fa 100644 --- a/gc.rb +++ b/gc.rb @@ -252,61 +252,142 @@ def self.stat hash_or_key = nil end # call-seq: - # GC.stat_heap -> Hash - # GC.stat_heap(nil, hash) -> Hash - # GC.stat_heap(heap_name) -> Hash - # GC.stat_heap(heap_name, hash) -> Hash - # GC.stat_heap(heap_name, :key) -> Numeric + # GC.stat_heap -> new_hash + # GC.stat_heap(heap_id) -> new_hash + # GC.stat_heap(heap_id, key) -> value + # GC.stat_heap(nil, hash) -> hash + # GC.stat_heap(heap_id, hash) -> hash # - # Returns information for heaps in the \GC. + # This method is implementation-specific to CRuby. # - # If the first optional argument, +heap_name+, is passed in and not +nil+, it - # returns a +Hash+ containing information about the particular heap. - # Otherwise, it will return a +Hash+ with heap names as keys and - # a +Hash+ containing information about the heap as values. + # Returns statistics for \GC heaps. + # The particular statistics are implementation-specific + # and may change in the future without notice. # - # If the second optional argument, +hash_or_key+, is given as a +Hash+, it will - # be overwritten and returned. This is intended to avoid the probe effect. + # With no argument given, returns statistics for all heaps: # - # If both optional arguments are passed in and the second optional argument is - # a symbol, it will return a +Numeric+ value for the particular heap. + # GC.stat_heap + # # => + # {0 => + # {slot_size: 40, + # heap_eden_pages: 246, + # heap_eden_slots: 402802, + # total_allocated_pages: 246, + # force_major_gc_count: 2, + # force_incremental_marking_finish_count: 1, + # total_allocated_objects: 33867152, + # total_freed_objects: 33520523}, + # 1 => + # {slot_size: 80, + # heap_eden_pages: 84, + # heap_eden_slots: 68746, + # total_allocated_pages: 84, + # force_major_gc_count: 1, + # force_incremental_marking_finish_count: 4, + # total_allocated_objects: 147491, + # total_freed_objects: 90699}, + # 2 => + # {slot_size: 160, + # heap_eden_pages: 157, + # heap_eden_slots: 64182, + # total_allocated_pages: 157, + # force_major_gc_count: 0, + # force_incremental_marking_finish_count: 0, + # total_allocated_objects: 211460, + # total_freed_objects: 190075}, + # 3 => + # {slot_size: 320, + # heap_eden_pages: 8, + # heap_eden_slots: 1631, + # total_allocated_pages: 8, + # force_major_gc_count: 0, + # force_incremental_marking_finish_count: 0, + # total_allocated_objects: 1422, + # total_freed_objects: 700}, + # 4 => + # {slot_size: 640, + # heap_eden_pages: 16, + # heap_eden_slots: 1628, + # total_allocated_pages: 16, + # force_major_gc_count: 0, + # force_incremental_marking_finish_count: 0, + # total_allocated_objects: 1230, + # total_freed_objects: 309}} + # + # In the example above, the keys in the outer hash are the heap identifiers: + # + # GC.stat_heap.keys # => [0, 1, 2, 3, 4] + # + # On CRuby, each heap identifier is an integer; + # on other implementations, a heap identifier may be a string. + # + # With only argument +heap_id+ given, + # returns statistics for the given heap identifier: + # + # GC.stat_heap(2) + # # => + # {slot_size: 160, + # heap_eden_pages: 157, + # heap_eden_slots: 64182, + # total_allocated_pages: 157, + # force_major_gc_count: 0, + # force_incremental_marking_finish_count: 0, + # total_allocated_objects: 225018, + # total_freed_objects: 206647} # - # On CRuby, +heap_name+ is of the type +Integer+ but may be of type +String+ - # on other implementations. + # With arguments +heap_id+ and +key+ given, + # returns the value for the given key in the given heap: # - # The contents of the hash are implementation-specific and may change in - # the future without notice. + # GC.stat_heap(2, :slot_size) # => 160 # - # If the optional argument, hash, is given, it is overwritten and returned. + # With arguments +nil+ and +hash+ given, + # merges the statistics for all heaps into the given hash: # - # This method is only expected to work on CRuby. + # h = {foo: 0, bar: 1} + # GC.stat_heap(nil, h).keys # => [:foo, :bar, 0, 1, 2, 3, 4] # - # The hash includes the following keys about the internal information in - # the \GC: + # With arguments +heap_id+ and +hash+ given, + # merges the statistics for the given heap into the given hash: # - # [slot_size] + # h = {foo: 0, bar: 1} + # GC.stat_heap(2, h).keys + # # => + # [:foo, + # :bar, + # :slot_size, + # :heap_eden_pages, + # :heap_eden_slots, + # :total_allocated_pages, + # :force_major_gc_count, + # :force_incremental_marking_finish_count, + # :total_allocated_objects, + # :total_freed_objects] + # + # The statistics for a heap may include: + # + # - +:slot_size+: # The slot size of the heap in bytes. - # [heap_allocatable_pages] + # - +:heap_allocatable_pages+: # The number of pages that can be allocated without triggering a new # garbage collection cycle. - # [heap_eden_pages] + # - +:heap_eden_pages+: # The number of pages in the eden heap. - # [heap_eden_slots] + # - +:heap_eden_slots+: # The total number of slots in all of the pages in the eden heap. - # [heap_tomb_pages] + # - +:heap_tomb_pages+: # The number of pages in the tomb heap. The tomb heap only contains pages # that do not have any live objects. - # [heap_tomb_slots] + # - +:heap_tomb_slots+: # The total number of slots in all of the pages in the tomb heap. - # [total_allocated_pages] + # - +:total_allocated_pages+: # The total number of pages that have been allocated in the heap. - # [total_freed_pages] + # - +:total_freed_pages+: # The total number of pages that have been freed and released back to the # system in the heap. - # [force_major_gc_count] + # - +:force_major_gc_count+: # The number of times this heap has forced major garbage collection cycles # to start due to running out of free slots. - # [force_incremental_marking_finish_count] + # - +:force_incremental_marking_finish_count+: # The number of times this heap has forced incremental marking to complete # due to running out of pooled slots. # diff --git a/lib/bundler/checksum.rb b/lib/bundler/checksum.rb index 356f4a48bcd11a..ce05818bb07992 100644 --- a/lib/bundler/checksum.rb +++ b/lib/bundler/checksum.rb @@ -205,6 +205,12 @@ def missing?(spec) @store[spec.lock_name].nil? end + def empty?(spec) + return false unless spec.source.is_a?(Bundler::Source::Rubygems) + + @store[spec.lock_name].empty? + end + def register(spec, checksum) register_checksum(spec.lock_name, checksum) end diff --git a/lib/bundler/cli.rb b/lib/bundler/cli.rb index ea85f9af22ab24..47a39069cc1b56 100644 --- a/lib/bundler/cli.rb +++ b/lib/bundler/cli.rb @@ -287,8 +287,8 @@ def update(*gems) method_option "outdated", type: :boolean, banner: "Show verbose output including whether gems are outdated." def show(gem_name = nil) if ARGV.include?("--outdated") - message = "the `--outdated` flag to `bundle show` was undocumented and will be removed without replacement" - removed_message = "the `--outdated` flag to `bundle show` was undocumented and has been removed without replacement" + message = "the `--outdated` flag to `bundle show` will be removed in favor of `bundle show --verbose`" + removed_message = "the `--outdated` flag to `bundle show` has been removed in favor of `bundle show --verbose`" SharedHelpers.major_deprecation(2, message, removed_message: removed_message) end require_relative "cli/show" @@ -299,6 +299,7 @@ def show(gem_name = nil) method_option "name-only", type: :boolean, banner: "print only the gem names" method_option "only-group", type: :array, default: [], banner: "print gems from a given set of groups" method_option "without-group", type: :array, default: [], banner: "print all gems except from a given set of groups" + method_option "format", type: :string, banner: "format output ('json' is the only supported format)" method_option "paths", type: :boolean, banner: "print the path to each gem in the bundle" def list require_relative "cli/list" @@ -412,6 +413,7 @@ def fund D def cache print_remembered_flag_deprecation("--all", "cache_all", "true") if ARGV.include?("--all") + print_remembered_flag_deprecation("--no-all", "cache_all", "false") if ARGV.include?("--no-all") if flag_passed?("--path") message = @@ -518,11 +520,11 @@ def licenses Viz requires the ruby-graphviz gem (and its dependencies). The associated gems must also be installed via 'bundle install'. D - method_option :file, type: :string, default: "gem_graph", aliases: "-f", desc: "The name to use for the generated file. see format option" - method_option :format, type: :string, default: "png", aliases: "-F", desc: "This is output format option. Supported format is png, jpg, svg, dot ..." - method_option :requirements, type: :boolean, default: false, aliases: "-R", desc: "Set to show the version of each required dependency." - method_option :version, type: :boolean, default: false, aliases: "-v", desc: "Set to show each gem version." - method_option :without, type: :array, default: [], aliases: "-W", banner: "GROUP[ GROUP...]", desc: "Exclude gems that are part of the specified named group." + method_option :file, type: :string, default: "gem_graph", aliases: "-f", banner: "The name to use for the generated file. see format option" + method_option :format, type: :string, default: "png", aliases: "-F", banner: "This is output format option. Supported format is png, jpg, svg, dot ..." + method_option :requirements, type: :boolean, default: false, aliases: "-R", banner: "Set to show the version of each required dependency." + method_option :version, type: :boolean, default: false, aliases: "-v", banner: "Set to show each gem version." + method_option :without, type: :array, default: [], aliases: "-W", banner: "Exclude gems that are part of the specified named group." def viz SharedHelpers.major_deprecation 2, "The `viz` command has been renamed to `graph` and moved to a plugin. See https://github.com/rubygems/bundler-graph" require_relative "cli/viz" @@ -531,19 +533,19 @@ def viz end desc "gem NAME [OPTIONS]", "Creates a skeleton for creating a rubygem" - method_option :exe, type: :boolean, default: false, aliases: ["--bin", "-b"], desc: "Generate a binary executable for your library." - method_option :coc, type: :boolean, desc: "Generate a code of conduct file. Set a default with `bundle config set --global gem.coc true`." - method_option :edit, type: :string, aliases: "-e", required: false, banner: "EDITOR", lazy_default: [ENV["BUNDLER_EDITOR"], ENV["VISUAL"], ENV["EDITOR"]].find {|e| !e.nil? && !e.empty? }, desc: "Open generated gemspec in the specified editor (defaults to $EDITOR or $BUNDLER_EDITOR)" - method_option :ext, type: :string, desc: "Generate the boilerplate for C extension code.", enum: EXTENSIONS - method_option :git, type: :boolean, default: true, desc: "Initialize a git repo inside your library." - method_option :mit, type: :boolean, desc: "Generate an MIT license file. Set a default with `bundle config set --global gem.mit true`." - method_option :rubocop, type: :boolean, desc: "Add rubocop to the generated Rakefile and gemspec. Set a default with `bundle config set --global gem.rubocop true`." - method_option :changelog, type: :boolean, desc: "Generate changelog file. Set a default with `bundle config set --global gem.changelog true`." + method_option :exe, type: :boolean, default: false, aliases: ["--bin", "-b"], banner: "Generate a binary executable for your library." + method_option :coc, type: :boolean, banner: "Generate a code of conduct file. Set a default with `bundle config set --global gem.coc true`." + method_option :edit, type: :string, aliases: "-e", required: false, lazy_default: [ENV["BUNDLER_EDITOR"], ENV["VISUAL"], ENV["EDITOR"]].find {|e| !e.nil? && !e.empty? }, banner: "Open generated gemspec in the specified editor (defaults to $EDITOR or $BUNDLER_EDITOR)" + method_option :ext, type: :string, banner: "Generate the boilerplate for C extension code.", enum: EXTENSIONS + method_option :git, type: :boolean, default: true, banner: "Initialize a git repo inside your library." + method_option :mit, type: :boolean, banner: "Generate an MIT license file. Set a default with `bundle config set --global gem.mit true`." + method_option :rubocop, type: :boolean, banner: "Add rubocop to the generated Rakefile and gemspec. Set a default with `bundle config set --global gem.rubocop true`." + method_option :changelog, type: :boolean, banner: "Generate changelog file. Set a default with `bundle config set --global gem.changelog true`." method_option :test, type: :string, lazy_default: Bundler.settings["gem.test"] || "", aliases: "-t", banner: "Use the specified test framework for your library", enum: %w[rspec minitest test-unit], desc: "Generate a test directory for your library, either rspec, minitest or test-unit. Set a default with `bundle config set --global gem.test (rspec|minitest|test-unit)`." - method_option :ci, type: :string, lazy_default: Bundler.settings["gem.ci"] || "", enum: %w[github gitlab circle], desc: "Generate CI configuration, either GitHub Actions, GitLab CI or CircleCI. Set a default with `bundle config set --global gem.ci (github|gitlab|circle)`" - method_option :linter, type: :string, lazy_default: Bundler.settings["gem.linter"] || "", enum: %w[rubocop standard], desc: "Add a linter and code formatter, either RuboCop or Standard. Set a default with `bundle config set --global gem.linter (rubocop|standard)`" + method_option :ci, type: :string, lazy_default: Bundler.settings["gem.ci"] || "", enum: %w[github gitlab circle], banner: "Generate CI configuration, either GitHub Actions, GitLab CI or CircleCI. Set a default with `bundle config set --global gem.ci (github|gitlab|circle)`" + method_option :linter, type: :string, lazy_default: Bundler.settings["gem.linter"] || "", enum: %w[rubocop standard], banner: "Add a linter and code formatter, either RuboCop or Standard. Set a default with `bundle config set --global gem.linter (rubocop|standard)`" method_option :github_username, type: :string, default: Bundler.settings["gem.github_username"], banner: "Set your username on GitHub", desc: "Fill in GitHub username on README so that you don't have to do it manually. Set a default with `bundle config set --global gem.github_username `." - method_option :bundle, type: :boolean, default: Bundler.settings["gem.bundle"], desc: "Automatically run `bundle install` after creation. Set a default with `bundle config set --global gem.bundle true`" + method_option :bundle, type: :boolean, default: Bundler.settings["gem.bundle"], banner: "Automatically run `bundle install` after creation. Set a default with `bundle config set --global gem.bundle true`" def gem(name) require_relative "cli/gem" @@ -713,7 +715,12 @@ def print_command command_name = cmd.name return if PARSEABLE_COMMANDS.include?(command_name) command = ["bundle", command_name] + args - command << Thor::Options.to_switches(options.sort_by(&:first)).strip + options_to_print = options.dup + options_to_print.delete_if do |k, v| + next unless o = cmd.options[k] + o.default == v + end + command << Thor::Options.to_switches(options_to_print.sort_by(&:first)).strip command.reject!(&:empty?) Bundler.ui.info "Running `#{command * " "}` with bundler #{Bundler.verbose_version}" end diff --git a/lib/bundler/cli/list.rb b/lib/bundler/cli/list.rb index f56bf5b86a426a..6a467f45a94ea2 100644 --- a/lib/bundler/cli/list.rb +++ b/lib/bundler/cli/list.rb @@ -1,11 +1,14 @@ # frozen_string_literal: true +require "json" + module Bundler class CLI::List def initialize(options) @options = options @without_group = options["without-group"].map(&:to_sym) @only_group = options["only-group"].map(&:to_sym) + @format = options["format"] end def run @@ -25,6 +28,36 @@ def run end end.reject {|s| s.name == "bundler" }.sort_by(&:name) + case @format + when "json" + print_json(specs: specs) + when nil + print_human(specs: specs) + else + raise InvalidOption, "Unknown option`--format=#{@format}`. Supported formats: `json`" + end + end + + private + + def print_json(specs:) + gems = if @options["name-only"] + specs.map {|s| { name: s.name } } + else + specs.map do |s| + { + name: s.name, + version: s.version.to_s, + git_version: s.git_version&.strip, + }.tap do |h| + h[:path] = s.full_gem_path if @options["paths"] + end + end + end + Bundler.ui.info({ gems: gems }.to_json) + end + + def print_human(specs:) return Bundler.ui.info "No gems in the Gemfile" if specs.empty? return specs.each {|s| Bundler.ui.info s.name } if @options["name-only"] @@ -37,8 +70,6 @@ def run Bundler.ui.info "Use `bundle info` to print more detailed information about a gem" end - private - def verify_group_exists(groups) (@without_group + @only_group).each do |group| raise InvalidOption, "`#{group}` group could not be found." unless groups.include?(group) diff --git a/lib/bundler/cli/show.rb b/lib/bundler/cli/show.rb index 13bb8b774b670d..b55eb7bad5aecc 100644 --- a/lib/bundler/cli/show.rb +++ b/lib/bundler/cli/show.rb @@ -57,12 +57,8 @@ def run def fetch_latest_specs definition = Bundler.definition(true) - if options[:outdated] - Bundler.ui.info "Fetching remote specs for outdated check...\n\n" - Bundler.ui.silence { definition.remotely! } - else - definition.with_cache! - end + Bundler.ui.info "Fetching remote specs for outdated check...\n\n" + Bundler.ui.silence { definition.remotely! } Bundler.reset! definition.specs end diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb index 6c7a3e9c38a613..52f9c6e1255c36 100644 --- a/lib/bundler/definition.rb +++ b/lib/bundler/definition.rb @@ -492,8 +492,6 @@ def unlocking? @unlocking end - attr_writer :source_requirements - def add_checksums @locked_checksums = true @@ -533,7 +531,7 @@ def lockfile_changes_summary(update_refused_reason) return unless added.any? || deleted.any? || changed.any? || resolve_needed? - msg = String.new("#{change_reason.capitalize.strip}, but ") + msg = String.new("#{change_reason[0].upcase}#{change_reason[1..-1].strip}, but ") msg << "the lockfile " unless msg.start_with?("Your lockfile") msg << "can't be updated because #{update_refused_reason}" msg << "\n\nYou have added to the Gemfile:\n" << added.join("\n") if added.any? @@ -559,6 +557,7 @@ def something_changed? @missing_lockfile_dep || @unlocking_bundler || @locked_spec_with_missing_checksums || + @locked_spec_with_empty_checksums || @locked_spec_with_missing_deps || @locked_spec_with_invalid_deps end @@ -614,7 +613,7 @@ def write_lock(file, preserve_unknown_sections) end def resolver - @resolver ||= Resolver.new(resolution_base, gem_version_promoter, @most_specific_locked_platform) + @resolver ||= new_resolver(resolution_base) end def expanded_dependencies @@ -632,8 +631,7 @@ def resolution_base @resolution_base ||= begin last_resolve = converge_locked_specs remove_invalid_platforms! - new_resolution_platforms = @current_platform_missing ? @new_platforms + [Bundler.local_platform] : @new_platforms - base = Resolver::Base.new(source_requirements, expanded_dependencies, last_resolve, @platforms, locked_specs: @originally_locked_specs, unlock: @unlocking_all || @gems_to_unlock, prerelease: gem_version_promoter.pre?, prefer_local: @prefer_local, new_platforms: new_resolution_platforms) + base = new_resolution_base(last_resolve: last_resolve, unlock: @unlocking_all || @gems_to_unlock) base = additional_base_requirements_to_prevent_downgrades(base) base = additional_base_requirements_to_force_updates(base) base @@ -839,6 +837,7 @@ def lockfile_changed_reason [@missing_lockfile_dep, "your lockfile is missing \"#{@missing_lockfile_dep}\""], [@unlocking_bundler, "an update to the version of Bundler itself was requested"], [@locked_spec_with_missing_checksums, "your lockfile is missing a CHECKSUMS entry for \"#{@locked_spec_with_missing_checksums}\""], + [@locked_spec_with_empty_checksums, "your lockfile has an empty CHECKSUMS entry for \"#{@locked_spec_with_empty_checksums}\""], [@locked_spec_with_missing_deps, "your lockfile includes \"#{@locked_spec_with_missing_deps}\" but not some of its dependencies"], [@locked_spec_with_invalid_deps, "your lockfile does not satisfy dependencies of \"#{@locked_spec_with_invalid_deps}\""], ].select(&:first).map(&:last).join(", ") @@ -898,13 +897,23 @@ def check_lockfile @locked_spec_with_invalid_deps = nil @locked_spec_with_missing_deps = nil @locked_spec_with_missing_checksums = nil + @locked_spec_with_empty_checksums = nil missing_deps = [] missing_checksums = [] + empty_checksums = [] invalid = [] @locked_specs.each do |s| - missing_checksums << s if @locked_checksums && s.source.checksum_store.missing?(s) + if @locked_checksums + checksum_store = s.source.checksum_store + + if checksum_store.missing?(s) + missing_checksums << s + elsif checksum_store.empty?(s) + empty_checksums << s + end + end validation = @locked_specs.validate_deps(s) @@ -913,6 +922,7 @@ def check_lockfile end @locked_spec_with_missing_checksums = missing_checksums.first.name if missing_checksums.any? + @locked_spec_with_empty_checksums = empty_checksums.first.name if empty_checksums.any? if missing_deps.any? @locked_specs.delete(missing_deps) @@ -1136,7 +1146,7 @@ def additional_base_requirements_to_prevent_downgrades(resolution_base) def additional_base_requirements_to_force_updates(resolution_base) return resolution_base if @explicit_unlocks.empty? - full_update = dup_for_full_unlock.resolve + full_update = SpecSet.new(new_resolver_for_full_update.start) @explicit_unlocks.each do |name| version = full_update.version_for(name) resolution_base.base_requirements[name] = Gem::Requirement.new("= #{version}") if version @@ -1144,17 +1154,6 @@ def additional_base_requirements_to_force_updates(resolution_base) resolution_base end - def dup_for_full_unlock - unlocked_definition = self.class.new(@lockfile, @dependencies, @sources, true, @ruby_version, @optional_groups, @gemfiles) - unlocked_definition.source_requirements = source_requirements - unlocked_definition.gem_version_promoter.tap do |gvp| - gvp.level = gem_version_promoter.level - gvp.strict = gem_version_promoter.strict - gvp.pre = gem_version_promoter.pre - end - unlocked_definition - end - def remove_invalid_platforms! return if Bundler.frozen_bundle? @@ -1173,5 +1172,22 @@ def remove_invalid_platforms! def source_map @source_map ||= SourceMap.new(sources, dependencies, @locked_specs) end + + def new_resolver_for_full_update + new_resolver(unlocked_resolution_base) + end + + def unlocked_resolution_base + new_resolution_base(last_resolve: SpecSet.new([]), unlock: true) + end + + def new_resolution_base(last_resolve:, unlock:) + new_resolution_platforms = @current_platform_missing ? @new_platforms + [Bundler.local_platform] : @new_platforms + Resolver::Base.new(source_requirements, expanded_dependencies, last_resolve, @platforms, locked_specs: @originally_locked_specs, unlock: unlock, prerelease: gem_version_promoter.pre?, prefer_local: @prefer_local, new_platforms: new_resolution_platforms) + end + + def new_resolver(base) + Resolver.new(base, gem_version_promoter, @most_specific_locked_platform) + end end end diff --git a/lib/bundler/man/bundle-add.1 b/lib/bundler/man/bundle-add.1 index baa4a376c83b4c..74422cbd313ddf 100644 --- a/lib/bundler/man/bundle-add.1 +++ b/lib/bundler/man/bundle-add.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-ADD" "1" "July 2025" "" +.TH "BUNDLE\-ADD" "1" "August 2025" "" .SH "NAME" \fBbundle\-add\fR \- Add gem to the Gemfile and run bundle install .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-binstubs.1 b/lib/bundler/man/bundle-binstubs.1 index 0131dd663ea38e..be9c6d0d097390 100644 --- a/lib/bundler/man/bundle-binstubs.1 +++ b/lib/bundler/man/bundle-binstubs.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-BINSTUBS" "1" "July 2025" "" +.TH "BUNDLE\-BINSTUBS" "1" "August 2025" "" .SH "NAME" \fBbundle\-binstubs\fR \- Install the binstubs of the listed gems .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-cache.1 b/lib/bundler/man/bundle-cache.1 index 4c5dcff052bc42..1d16b164fa2806 100644 --- a/lib/bundler/man/bundle-cache.1 +++ b/lib/bundler/man/bundle-cache.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-CACHE" "1" "July 2025" "" +.TH "BUNDLE\-CACHE" "1" "August 2025" "" .SH "NAME" \fBbundle\-cache\fR \- Package your needed \fB\.gem\fR files into your application .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-check.1 b/lib/bundler/man/bundle-check.1 index 376becdbe47d5b..4f0d51bb71472e 100644 --- a/lib/bundler/man/bundle-check.1 +++ b/lib/bundler/man/bundle-check.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-CHECK" "1" "July 2025" "" +.TH "BUNDLE\-CHECK" "1" "August 2025" "" .SH "NAME" \fBbundle\-check\fR \- Verifies if dependencies are satisfied by installed gems .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-clean.1 b/lib/bundler/man/bundle-clean.1 index 85e6186f49cf2e..df66523829d35e 100644 --- a/lib/bundler/man/bundle-clean.1 +++ b/lib/bundler/man/bundle-clean.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-CLEAN" "1" "July 2025" "" +.TH "BUNDLE\-CLEAN" "1" "August 2025" "" .SH "NAME" \fBbundle\-clean\fR \- Cleans up unused gems in your bundler directory .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-config.1 b/lib/bundler/man/bundle-config.1 index 6f12696ab6961f..5157e514531238 100644 --- a/lib/bundler/man/bundle-config.1 +++ b/lib/bundler/man/bundle-config.1 @@ -1,16 +1,16 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-CONFIG" "1" "July 2025" "" +.TH "BUNDLE\-CONFIG" "1" "August 2025" "" .SH "NAME" \fBbundle\-config\fR \- Set bundler configuration options .SH "SYNOPSIS" -\fBbundle config\fR list +\fBbundle config\fR [list] .br -\fBbundle config\fR [get] NAME +\fBbundle config\fR [get [\-\-local|\-\-global]] NAME .br -\fBbundle config\fR [set] NAME VALUE +\fBbundle config\fR [set [\-\-local|\-\-global]] NAME VALUE .br -\fBbundle config\fR unset NAME +\fBbundle config\fR unset [\-\-local|\-\-global] NAME .SH "DESCRIPTION" This command allows you to interact with Bundler's configuration system\. .P @@ -25,23 +25,40 @@ Global config (\fB~/\.bundle/config\fR) Bundler default config .IP "" 0 .P +Executing \fBbundle\fR with the \fBBUNDLE_IGNORE_CONFIG\fR environment variable set will cause it to ignore all configuration\. +.SH "SUB\-COMMANDS" +.SS "list (default command)" Executing \fBbundle config list\fR will print a list of all bundler configuration for the current bundle, and where that configuration was set\. +.SS "get" +Executing \fBbundle config get \fR will print the value of that configuration setting, and all locations where it was set\. .P -Executing \fBbundle config get \fR will print the value of that configuration setting, and where it was set\. -.P -Executing \fBbundle config set \fR defaults to setting \fBlocal\fR configuration if executing from within a local application, otherwise it will set \fBglobal\fR configuration\. See \fB\-\-local\fR and \fB\-\-global\fR options below\. +\fBOPTIONS\fR +.TP +\fB\-\-local\fR +Get configuration from configuration file for the local application, namely, \fB/\.bundle/config\fR, or \fB$BUNDLE_APP_CONFIG/config\fR if \fBBUNDLE_APP_CONFIG\fR is set\. +.TP +\fB\-\-global\fR +Get configuration from configuration file global to all bundles executed as the current user, namely, from \fB~/\.bundle/config\fR\. +.SS "set" +Executing \fBbundle config set \fR defaults to setting \fBlocal\fR configuration if executing from within a local application, otherwise it will set \fBglobal\fR configuration\. .P +\fBOPTIONS\fR +.TP +\fB\-\-local\fR Executing \fBbundle config set \-\-local \fR will set that configuration in the directory for the local application\. The configuration will be stored in \fB/\.bundle/config\fR\. If \fBBUNDLE_APP_CONFIG\fR is set, the configuration will be stored in \fB$BUNDLE_APP_CONFIG/config\fR\. -.P +.TP +\fB\-\-global\fR Executing \fBbundle config set \-\-global \fR will set that configuration to the value specified for all bundles executed as the current user\. The configuration will be stored in \fB~/\.bundle/config\fR\. If \fIname\fR already is set, \fIname\fR will be overridden and user will be warned\. -.P +.SS "unset" Executing \fBbundle config unset \fR will delete the configuration in both local and global sources\. .P -Executing \fBbundle config unset \-\-global \fR will delete the configuration only from the user configuration\. -.P +\fBOPTIONS\fR +.TP +\fB\-\-local\fR Executing \fBbundle config unset \-\-local \fR will delete the configuration only from the local application\. -.P -Executing bundle with the \fBBUNDLE_IGNORE_CONFIG\fR environment variable set will cause it to ignore all configuration\. +.TP +\fB\-\-global\fR +Executing \fBbundle config unset \-\-global \fR will delete the configuration only from the user configuration\. .SH "CONFIGURATION KEYS" Configuration keys in bundler have two forms: the canonical form and the environment variable form\. .P diff --git a/lib/bundler/man/bundle-config.1.ronn b/lib/bundler/man/bundle-config.1.ronn index 7f31eb4c39a0ad..2b2e39f03eb7f0 100644 --- a/lib/bundler/man/bundle-config.1.ronn +++ b/lib/bundler/man/bundle-config.1.ronn @@ -3,10 +3,10 @@ bundle-config(1) -- Set bundler configuration options ## SYNOPSIS -`bundle config` list
-`bundle config` [get] NAME
-`bundle config` [set] NAME VALUE
-`bundle config` unset NAME +`bundle config` [list]
+`bundle config` [get [--local|--global]] NAME
+`bundle config` [set [--local|--global]] NAME VALUE
+`bundle config` unset [--local|--global] NAME ## DESCRIPTION @@ -19,38 +19,67 @@ Bundler loads configuration settings in this order: 3. Global config (`~/.bundle/config`) 4. Bundler default config +Executing `bundle` with the `BUNDLE_IGNORE_CONFIG` environment variable set will +cause it to ignore all configuration. + +## SUB-COMMANDS + +### list (default command) + Executing `bundle config list` will print a list of all bundler configuration for the current bundle, and where that configuration was set. +### get + Executing `bundle config get ` will print the value of that configuration -setting, and where it was set. +setting, and all locations where it was set. + +**OPTIONS** + +* `--local`: + Get configuration from configuration file for the local application, namely, + `/.bundle/config`, or `$BUNDLE_APP_CONFIG/config` if + `BUNDLE_APP_CONFIG` is set. + +* `--global`: + Get configuration from configuration file global to all bundles executed as + the current user, namely, from `~/.bundle/config`. + +### set Executing `bundle config set ` defaults to setting `local` configuration if executing from within a local application, otherwise it will -set `global` configuration. See `--local` and `--global` options below. +set `global` configuration. -Executing `bundle config set --local ` will set that configuration -in the directory for the local application. The configuration will be stored in -`/.bundle/config`. If `BUNDLE_APP_CONFIG` is set, the configuration -will be stored in `$BUNDLE_APP_CONFIG/config`. +**OPTIONS** -Executing `bundle config set --global ` will set that -configuration to the value specified for all bundles executed as the current -user. The configuration will be stored in `~/.bundle/config`. If already -is set, will be overridden and user will be warned. +* `--local`: + Executing `bundle config set --local ` will set that configuration + in the directory for the local application. The configuration will be stored in + `/.bundle/config`. If `BUNDLE_APP_CONFIG` is set, the configuration + will be stored in `$BUNDLE_APP_CONFIG/config`. + +* `--global`: + Executing `bundle config set --global ` will set that + configuration to the value specified for all bundles executed as the current + user. The configuration will be stored in `~/.bundle/config`. If already + is set, will be overridden and user will be warned. + +### unset Executing `bundle config unset ` will delete the configuration in both local and global sources. -Executing `bundle config unset --global ` will delete the configuration -only from the user configuration. +**OPTIONS** -Executing `bundle config unset --local ` will delete the configuration -only from the local application. +* `--local`: + Executing `bundle config unset --local ` will delete the configuration + only from the local application. -Executing bundle with the `BUNDLE_IGNORE_CONFIG` environment variable set will -cause it to ignore all configuration. +* `--global`: + Executing `bundle config unset --global ` will delete the configuration + only from the user configuration. ## CONFIGURATION KEYS diff --git a/lib/bundler/man/bundle-console.1 b/lib/bundler/man/bundle-console.1 index a263fef37640ae..18c765372b4230 100644 --- a/lib/bundler/man/bundle-console.1 +++ b/lib/bundler/man/bundle-console.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-CONSOLE" "1" "July 2025" "" +.TH "BUNDLE\-CONSOLE" "1" "August 2025" "" .SH "NAME" \fBbundle\-console\fR \- Open an IRB session with the bundle pre\-loaded .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-doctor.1 b/lib/bundler/man/bundle-doctor.1 index 2b695dc2eef2ec..6d4b0376a68ad8 100644 --- a/lib/bundler/man/bundle-doctor.1 +++ b/lib/bundler/man/bundle-doctor.1 @@ -1,12 +1,12 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-DOCTOR" "1" "July 2025" "" +.TH "BUNDLE\-DOCTOR" "1" "August 2025" "" .SH "NAME" \fBbundle\-doctor\fR \- Checks the bundle for common problems .SH "SYNOPSIS" \fBbundle doctor [diagnose]\fR [\-\-quiet] [\-\-gemfile=GEMFILE] [\-\-ssl] .br -\fBbundle doctor ssl\fR [\-\-host=HOST] [\-\-tls\-version=VERSION] [\-\-verify\-mode=MODE] +\fBbundle doctor ssl\fR [\-\-host=HOST] [\-\-tls\-version=TLS\-VERSION] [\-\-verify\-mode=VERIFY\-MODE] .br \fBbundle doctor\fR help [COMMAND] .SH "DESCRIPTION" @@ -57,12 +57,12 @@ Open a TLS connection and verify the outcome\. \fB\-\-host=HOST\fR Perform the diagnostic on HOST\. Defaults to \fBrubygems\.org\fR\. .TP -\fB\-\-tls\-version=VERSION\fR +\fB\-\-tls\-version=TLS\-VERSION\fR Specify the TLS version when opening the connection to HOST\. .IP Accepted values are: \fB1\.1\fR or \fB1\.2\fR\. .TP -\fB\-\-verify\-mode=MODE\fR +\fB\-\-verify\-mode=VERIFY\-MODE\fR Specify the TLS verify mode when opening the connection to HOST\. Defaults to \fBSSL_VERIFY_PEER\fR\. .IP Accepted values are: \fBCLIENT_ONCE\fR, \fBFAIL_IF_NO_PEER_CERT\fR, \fBNONE\fR, \fBPEER\fR\. diff --git a/lib/bundler/man/bundle-doctor.1.ronn b/lib/bundler/man/bundle-doctor.1.ronn index 7e8a21b1c58968..7495099ff546bc 100644 --- a/lib/bundler/man/bundle-doctor.1.ronn +++ b/lib/bundler/man/bundle-doctor.1.ronn @@ -7,8 +7,8 @@ bundle-doctor(1) -- Checks the bundle for common problems [--gemfile=GEMFILE] [--ssl]
`bundle doctor ssl` [--host=HOST] - [--tls-version=VERSION] - [--verify-mode=MODE]
+ [--tls-version=TLS-VERSION] + [--verify-mode=VERIFY-MODE]
`bundle doctor` help [COMMAND] ## DESCRIPTION @@ -65,12 +65,12 @@ The diagnostic will perform a few checks such as: * `--host=HOST`: Perform the diagnostic on HOST. Defaults to `rubygems.org`. -* `--tls-version=VERSION`: +* `--tls-version=TLS-VERSION`: Specify the TLS version when opening the connection to HOST. Accepted values are: `1.1` or `1.2`. -* `--verify-mode=MODE`: +* `--verify-mode=VERIFY-MODE`: Specify the TLS verify mode when opening the connection to HOST. Defaults to `SSL_VERIFY_PEER`. diff --git a/lib/bundler/man/bundle-env.1 b/lib/bundler/man/bundle-env.1 index 3e6c9f6e171de8..28ccc17f03aa9f 100644 --- a/lib/bundler/man/bundle-env.1 +++ b/lib/bundler/man/bundle-env.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-ENV" "1" "July 2025" "" +.TH "BUNDLE\-ENV" "1" "August 2025" "" .SH "NAME" \fBbundle\-env\fR \- Print information about the environment Bundler is running under .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-exec.1 b/lib/bundler/man/bundle-exec.1 index 79cdad0288f498..cd53916cffcc34 100644 --- a/lib/bundler/man/bundle-exec.1 +++ b/lib/bundler/man/bundle-exec.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-EXEC" "1" "July 2025" "" +.TH "BUNDLE\-EXEC" "1" "August 2025" "" .SH "NAME" \fBbundle\-exec\fR \- Execute a command in the context of the bundle .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-fund.1 b/lib/bundler/man/bundle-fund.1 index 3f6e3a46dfec80..a91c1809514aee 100644 --- a/lib/bundler/man/bundle-fund.1 +++ b/lib/bundler/man/bundle-fund.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-FUND" "1" "July 2025" "" +.TH "BUNDLE\-FUND" "1" "August 2025" "" .SH "NAME" \fBbundle\-fund\fR \- Lists information about gems seeking funding assistance .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-gem.1 b/lib/bundler/man/bundle-gem.1 index 44a02c033c70af..5fe27772306930 100644 --- a/lib/bundler/man/bundle-gem.1 +++ b/lib/bundler/man/bundle-gem.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-GEM" "1" "July 2025" "" +.TH "BUNDLE\-GEM" "1" "August 2025" "" .SH "NAME" \fBbundle\-gem\fR \- Generate a project skeleton for creating a rubygem .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-help.1 b/lib/bundler/man/bundle-help.1 index e6bbea6dadbf39..9ea28bef14d082 100644 --- a/lib/bundler/man/bundle-help.1 +++ b/lib/bundler/man/bundle-help.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-HELP" "1" "July 2025" "" +.TH "BUNDLE\-HELP" "1" "August 2025" "" .SH "NAME" \fBbundle\-help\fR \- Displays detailed help for each subcommand .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-info.1 b/lib/bundler/man/bundle-info.1 index 435518e120fe73..29d649d342cc42 100644 --- a/lib/bundler/man/bundle-info.1 +++ b/lib/bundler/man/bundle-info.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-INFO" "1" "July 2025" "" +.TH "BUNDLE\-INFO" "1" "August 2025" "" .SH "NAME" \fBbundle\-info\fR \- Show information for the given gem in your bundle .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-init.1 b/lib/bundler/man/bundle-init.1 index 48b3232b8cba2a..be9399c20f2367 100644 --- a/lib/bundler/man/bundle-init.1 +++ b/lib/bundler/man/bundle-init.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-INIT" "1" "July 2025" "" +.TH "BUNDLE\-INIT" "1" "August 2025" "" .SH "NAME" \fBbundle\-init\fR \- Generates a Gemfile into the current working directory .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-inject.1 b/lib/bundler/man/bundle-inject.1 index abc63c392e525c..7e30e26a4e4637 100644 --- a/lib/bundler/man/bundle-inject.1 +++ b/lib/bundler/man/bundle-inject.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-INJECT" "1" "July 2025" "" +.TH "BUNDLE\-INJECT" "1" "August 2025" "" .SH "NAME" \fBbundle\-inject\fR \- Add named gem(s) with version requirements to Gemfile .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-install.1 b/lib/bundler/man/bundle-install.1 index bf067475584a03..f9bbade2fd59fb 100644 --- a/lib/bundler/man/bundle-install.1 +++ b/lib/bundler/man/bundle-install.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-INSTALL" "1" "July 2025" "" +.TH "BUNDLE\-INSTALL" "1" "August 2025" "" .SH "NAME" \fBbundle\-install\fR \- Install the dependencies specified in your Gemfile .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-issue.1 b/lib/bundler/man/bundle-issue.1 index 668da5712f7cd9..3c7e5305f3721a 100644 --- a/lib/bundler/man/bundle-issue.1 +++ b/lib/bundler/man/bundle-issue.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-ISSUE" "1" "July 2025" "" +.TH "BUNDLE\-ISSUE" "1" "August 2025" "" .SH "NAME" \fBbundle\-issue\fR \- Get help reporting Bundler issues .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-licenses.1 b/lib/bundler/man/bundle-licenses.1 index cccb860854819b..eb0ad5ae405cd3 100644 --- a/lib/bundler/man/bundle-licenses.1 +++ b/lib/bundler/man/bundle-licenses.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-LICENSES" "1" "July 2025" "" +.TH "BUNDLE\-LICENSES" "1" "August 2025" "" .SH "NAME" \fBbundle\-licenses\fR \- Print the license of all gems in the bundle .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-list.1 b/lib/bundler/man/bundle-list.1 index 26c2833218093a..a345787a5e9ee0 100644 --- a/lib/bundler/man/bundle-list.1 +++ b/lib/bundler/man/bundle-list.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-LIST" "1" "July 2025" "" +.TH "BUNDLE\-LIST" "1" "August 2025" "" .SH "NAME" \fBbundle\-list\fR \- List all the gems in the bundle .SH "SYNOPSIS" @@ -19,6 +19,8 @@ bundle list \-\-without\-group test bundle list \-\-only\-group dev .P bundle list \-\-only\-group dev test \-\-paths +.P +bundle list \-\-format json .SH "OPTIONS" .TP \fB\-\-name\-only\fR @@ -32,4 +34,7 @@ A space\-separated list of groups of gems to skip during printing\. .TP \fB\-\-only\-group=\fR A space\-separated list of groups of gems to print\. +.TP +\fB\-\-format=FORMAT\fR +Format output ('json' is the only supported format) diff --git a/lib/bundler/man/bundle-list.1.ronn b/lib/bundler/man/bundle-list.1.ronn index 81bee0ac332047..9ec2b132828958 100644 --- a/lib/bundler/man/bundle-list.1.ronn +++ b/lib/bundler/man/bundle-list.1.ronn @@ -21,6 +21,8 @@ bundle list --only-group dev bundle list --only-group dev test --paths +bundle list --format json + ## OPTIONS * `--name-only`: @@ -34,3 +36,6 @@ bundle list --only-group dev test --paths * `--only-group=`: A space-separated list of groups of gems to print. + +* `--format=FORMAT`: + Format output ('json' is the only supported format) diff --git a/lib/bundler/man/bundle-lock.1 b/lib/bundler/man/bundle-lock.1 index 5faa46da180afb..79aa1e2452f6d3 100644 --- a/lib/bundler/man/bundle-lock.1 +++ b/lib/bundler/man/bundle-lock.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-LOCK" "1" "July 2025" "" +.TH "BUNDLE\-LOCK" "1" "August 2025" "" .SH "NAME" \fBbundle\-lock\fR \- Creates / Updates a lockfile without installing .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-open.1 b/lib/bundler/man/bundle-open.1 index e8a24f35414207..b1c2022f40195b 100644 --- a/lib/bundler/man/bundle-open.1 +++ b/lib/bundler/man/bundle-open.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-OPEN" "1" "July 2025" "" +.TH "BUNDLE\-OPEN" "1" "August 2025" "" .SH "NAME" \fBbundle\-open\fR \- Opens the source directory for a gem in your bundle .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-outdated.1 b/lib/bundler/man/bundle-outdated.1 index 3259b0f0233fa3..d4790f8876a54d 100644 --- a/lib/bundler/man/bundle-outdated.1 +++ b/lib/bundler/man/bundle-outdated.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-OUTDATED" "1" "July 2025" "" +.TH "BUNDLE\-OUTDATED" "1" "August 2025" "" .SH "NAME" \fBbundle\-outdated\fR \- List installed gems with newer versions available .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-platform.1 b/lib/bundler/man/bundle-platform.1 index 1032acc4e6405c..78de506b57b838 100644 --- a/lib/bundler/man/bundle-platform.1 +++ b/lib/bundler/man/bundle-platform.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-PLATFORM" "1" "July 2025" "" +.TH "BUNDLE\-PLATFORM" "1" "August 2025" "" .SH "NAME" \fBbundle\-platform\fR \- Displays platform compatibility information .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-plugin.1 b/lib/bundler/man/bundle-plugin.1 index 5803b7a5549917..5fcc88b50df308 100644 --- a/lib/bundler/man/bundle-plugin.1 +++ b/lib/bundler/man/bundle-plugin.1 @@ -1,10 +1,10 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-PLUGIN" "1" "July 2025" "" +.TH "BUNDLE\-PLUGIN" "1" "August 2025" "" .SH "NAME" \fBbundle\-plugin\fR \- Manage Bundler plugins .SH "SYNOPSIS" -\fBbundle plugin\fR install PLUGINS [\-\-source=\fISOURCE\fR] [\-\-version=\fIversion\fR] [\-\-git=\fIgit\-url\fR] [\-\-branch=\fIbranch\fR|\-\-ref=\fIrev\fR] [\-\-path=\fIpath\fR] +\fBbundle plugin\fR install PLUGINS [\-\-source=SOURCE] [\-\-version=VERSION] [\-\-git=GIT] [\-\-branch=BRANCH|\-\-ref=REF] [\-\-local\-git=LOCAL_GIT] [\-\-path=PATH] .br \fBbundle plugin\fR uninstall PLUGINS [\-\-all] .br @@ -16,18 +16,23 @@ You can install, uninstall, and list plugin(s) with this command to extend funct .SH "SUB\-COMMANDS" .SS "install" Install the given plugin(s)\. +.P +For example, \fBbundle plugin install bundler\-graph\fR will install bundler\-graph gem from globally configured sources (defaults to RubyGems\.org)\. Note that the global source specified in Gemfile is ignored\. +.P +\fBOPTIONS\fR .TP -\fBbundle plugin install bundler\-graph\fR -Install bundler\-graph gem from globally configured sources (defaults to RubyGems\.org)\. The global source, specified in source in Gemfile is ignored\. -.TP -\fBbundle plugin install bundler\-graph \-\-source https://example\.com\fR -Install bundler\-graph gem from example\.com\. The global source, specified in source in Gemfile is not considered\. +\fB\-\-source=SOURCE\fR +Install the plugin gem from a specific source, rather than from globally configured sources\. +.IP +Example: \fBbundle plugin install bundler\-graph \-\-source https://example\.com\fR .TP -\fBbundle plugin install bundler\-graph \-\-version 0\.2\.1\fR -You can specify the version of the gem via \fB\-\-version\fR\. +\fB\-\-version=VERSION\fR +Specify a version of the plugin gem to install via \fB\-\-version\fR\. +.IP +Example: \fBbundle plugin install bundler\-graph \-\-version 0\.2\.1\fR .TP -\fBbundle plugin install bundler\-graph \-\-git https://github\.com/rubygems/bundler\-graph\fR -Install bundler\-graph gem from Git repository\. You can use standard Git URLs like: +\fB\-\-git=GIT\fR +Install the plugin gem from a Git repository\. You can use standard Git URLs like: .IP \fBssh://[user@]host\.xz[:port]/path/to/repo\.git\fR .br @@ -37,12 +42,24 @@ Install bundler\-graph gem from Git repository\. You can use standard Git URLs l .br \fBfile:///path/to/repo\fR .IP -When you specify \fB\-\-git\fR, you can use \fB\-\-branch\fR or \fB\-\-ref\fR to specify any branch, tag, or commit hash (revision) to use\. +Example: \fBbundle plugin install bundler\-graph \-\-git https://github\.com/rubygems/bundler\-graph\fR .TP -\fBbundle plugin install bundler\-graph \-\-path \.\./bundler\-graph\fR -Install bundler\-graph gem from a local path\. +\fB\-\-branch=BRANCH\fR +When you specify \fB\-\-git\fR, you can use \fB\-\-branch\fR to use\. .TP -\fBbundle plugin install bundler\-graph \-\-local\-git \.\./bundler\-graph\fR +\fB\-\-ref=REF\fR +When you specify \fB\-\-git\fR, you can use \fB\-\-ref\fR to specify any tag, or commit hash (revision) to use\. +.TP +\fB\-\-path=PATH\fR +Install the plugin gem from a local path\. +.IP +Example: \fBbundle plugin install bundler\-graph \-\-path \.\./bundler\-graph\fR +.TP +\fB\-\-local\-git=LOCAL_GIT\fR +Install the plugin gem from a local Git repository\. +.IP +Example: \fBbundle plugin install bundler\-graph \-\-local\-git \.\./bundler\-graph\fR\. +.IP This option is deprecated in favor of \fB\-\-git\fR\. .SS "uninstall" Uninstall the plugin(s) specified in PLUGINS\. diff --git a/lib/bundler/man/bundle-plugin.1.ronn b/lib/bundler/man/bundle-plugin.1.ronn index 74879aa6812d63..efb42407611836 100644 --- a/lib/bundler/man/bundle-plugin.1.ronn +++ b/lib/bundler/man/bundle-plugin.1.ronn @@ -3,9 +3,10 @@ bundle-plugin(1) -- Manage Bundler plugins ## SYNOPSIS -`bundle plugin` install PLUGINS [--source=] [--version=] - [--git=] [--branch=|--ref=] - [--path=]
+`bundle plugin` install PLUGINS [--source=SOURCE] [--version=VERSION] + [--git=GIT] [--branch=BRANCH|--ref=REF] + [--local-git=LOCAL_GIT] + [--path=PATH]
`bundle plugin` uninstall PLUGINS [--all]
`bundle plugin` list
`bundle plugin` help [COMMAND] @@ -20,29 +21,49 @@ You can install, uninstall, and list plugin(s) with this command to extend funct Install the given plugin(s). -* `bundle plugin install bundler-graph`: - Install bundler-graph gem from globally configured sources (defaults to RubyGems.org). The global source, specified in source in Gemfile is ignored. +For example, `bundle plugin install bundler-graph` will install bundler-graph +gem from globally configured sources (defaults to RubyGems.org). Note that the +global source specified in Gemfile is ignored. -* `bundle plugin install bundler-graph --source https://example.com`: - Install bundler-graph gem from example.com. The global source, specified in source in Gemfile is not considered. +**OPTIONS** + +* `--source=SOURCE`: + Install the plugin gem from a specific source, rather than from globally configured sources. + + Example: `bundle plugin install bundler-graph --source https://example.com` -* `bundle plugin install bundler-graph --version 0.2.1`: - You can specify the version of the gem via `--version`. +* `--version=VERSION`: + Specify a version of the plugin gem to install via `--version`. -* `bundle plugin install bundler-graph --git https://github.com/rubygems/bundler-graph`: - Install bundler-graph gem from Git repository. You can use standard Git URLs like: + Example: `bundle plugin install bundler-graph --version 0.2.1` + +* `--git=GIT`: + Install the plugin gem from a Git repository. You can use standard Git URLs like: `ssh://[user@]host.xz[:port]/path/to/repo.git`
`http[s]://host.xz[:port]/path/to/repo.git`
`/path/to/repo`
`file:///path/to/repo` - When you specify `--git`, you can use `--branch` or `--ref` to specify any branch, tag, or commit hash (revision) to use. + Example: `bundle plugin install bundler-graph --git https://github.com/rubygems/bundler-graph` + +* `--branch=BRANCH`: + When you specify `--git`, you can use `--branch` to use. + +* `--ref=REF`: + When you specify `--git`, you can use `--ref` to specify any tag, or commit + hash (revision) to use. + +* `--path=PATH`: + Install the plugin gem from a local path. + + Example: `bundle plugin install bundler-graph --path ../bundler-graph` + +* `--local-git=LOCAL_GIT`: + Install the plugin gem from a local Git repository. -* `bundle plugin install bundler-graph --path ../bundler-graph`: - Install bundler-graph gem from a local path. + Example: `bundle plugin install bundler-graph --local-git ../bundler-graph`. -* `bundle plugin install bundler-graph --local-git ../bundler-graph`: This option is deprecated in favor of `--git`. ### uninstall diff --git a/lib/bundler/man/bundle-pristine.1 b/lib/bundler/man/bundle-pristine.1 index 5c7871069c0940..e39f264ceff298 100644 --- a/lib/bundler/man/bundle-pristine.1 +++ b/lib/bundler/man/bundle-pristine.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-PRISTINE" "1" "July 2025" "" +.TH "BUNDLE\-PRISTINE" "1" "August 2025" "" .SH "NAME" \fBbundle\-pristine\fR \- Restores installed gems to their pristine condition .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-remove.1 b/lib/bundler/man/bundle-remove.1 index df8ce3232ab8dc..67508176802bf4 100644 --- a/lib/bundler/man/bundle-remove.1 +++ b/lib/bundler/man/bundle-remove.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-REMOVE" "1" "July 2025" "" +.TH "BUNDLE\-REMOVE" "1" "August 2025" "" .SH "NAME" \fBbundle\-remove\fR \- Removes gems from the Gemfile .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-show.1 b/lib/bundler/man/bundle-show.1 index ca10c00701e85d..67b387559d7ca5 100644 --- a/lib/bundler/man/bundle-show.1 +++ b/lib/bundler/man/bundle-show.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-SHOW" "1" "July 2025" "" +.TH "BUNDLE\-SHOW" "1" "August 2025" "" .SH "NAME" \fBbundle\-show\fR \- Shows all the gems in your bundle, or the path to a gem .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-update.1 b/lib/bundler/man/bundle-update.1 index 8655aa5cd3545e..fbcabb69a8d61f 100644 --- a/lib/bundler/man/bundle-update.1 +++ b/lib/bundler/man/bundle-update.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-UPDATE" "1" "July 2025" "" +.TH "BUNDLE\-UPDATE" "1" "August 2025" "" .SH "NAME" \fBbundle\-update\fR \- Update your gems to the latest available versions .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-version.1 b/lib/bundler/man/bundle-version.1 index e591f597664636..261140ff3816f5 100644 --- a/lib/bundler/man/bundle-version.1 +++ b/lib/bundler/man/bundle-version.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-VERSION" "1" "July 2025" "" +.TH "BUNDLE\-VERSION" "1" "August 2025" "" .SH "NAME" \fBbundle\-version\fR \- Prints Bundler version information .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-viz.1 b/lib/bundler/man/bundle-viz.1 index b5dd1db7b7f05a..f2570103dcc546 100644 --- a/lib/bundler/man/bundle-viz.1 +++ b/lib/bundler/man/bundle-viz.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE\-VIZ" "1" "July 2025" "" +.TH "BUNDLE\-VIZ" "1" "August 2025" "" .SH "NAME" \fBbundle\-viz\fR \- Generates a visual dependency graph for your Gemfile .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle.1 b/lib/bundler/man/bundle.1 index 269e28141d3101..f87a98150da609 100644 --- a/lib/bundler/man/bundle.1 +++ b/lib/bundler/man/bundle.1 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "BUNDLE" "1" "July 2025" "" +.TH "BUNDLE" "1" "August 2025" "" .SH "NAME" \fBbundle\fR \- Ruby Dependency Management .SH "SYNOPSIS" diff --git a/lib/bundler/man/gemfile.5 b/lib/bundler/man/gemfile.5 index c926e1ff2d30da..cd04d3d1983d37 100644 --- a/lib/bundler/man/gemfile.5 +++ b/lib/bundler/man/gemfile.5 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "GEMFILE" "5" "July 2025" "" +.TH "GEMFILE" "5" "August 2025" "" .SH "NAME" \fBGemfile\fR \- A format for describing gem dependencies for Ruby programs .SH "SYNOPSIS" diff --git a/lib/bundler/resolver.rb b/lib/bundler/resolver.rb index fba9badec727ba..1dbf565d4676e8 100644 --- a/lib/bundler/resolver.rb +++ b/lib/bundler/resolver.rb @@ -165,7 +165,7 @@ def parse_dependency(package, dependency) PubGrub::VersionConstraint.new(package, range: range) end - def versions_for(package, range=VersionRange.any) + def versions_for(package, range = VersionRange.any) range.select_versions(@sorted_versions[package]) end diff --git a/lib/bundler/rubygems_ext.rb b/lib/bundler/rubygems_ext.rb index 8cf3b56b831f0f..fedf44b0e69b14 100644 --- a/lib/bundler/rubygems_ext.rb +++ b/lib/bundler/rubygems_ext.rb @@ -417,7 +417,7 @@ class NameTuple unless Gem::NameTuple.new("a", Gem::Version.new("1"), Gem::Platform.new("x86_64-linux")).platform.is_a?(String) alias_method :initialize_with_platform, :initialize - def initialize(name, version, platform=Gem::Platform::RUBY) + def initialize(name, version, platform = Gem::Platform::RUBY) if Gem::Platform === platform initialize_with_platform(name, version, platform.to_s) else diff --git a/lib/rubygems.rb b/lib/rubygems.rb index d4e88579e823db..f8f1451ee661a7 100644 --- a/lib/rubygems.rb +++ b/lib/rubygems.rb @@ -224,7 +224,7 @@ def self.needs finish_resolve rs end - def self.finish_resolve(request_set=Gem::RequestSet.new) + def self.finish_resolve(request_set = Gem::RequestSet.new) request_set.import Gem::Specification.unresolved_deps.values request_set.import Gem.loaded_specs.values.map {|s| Gem::Dependency.new(s.name, s.version) } @@ -341,7 +341,7 @@ def self.binary_mode ## # The path where gem executables are to be installed. - def self.bindir(install_dir=Gem.dir) + def self.bindir(install_dir = Gem.dir) return File.join install_dir, "bin" unless install_dir.to_s == Gem.default_dir.to_s Gem.default_bindir @@ -350,7 +350,7 @@ def self.bindir(install_dir=Gem.dir) ## # The path were rubygems plugins are to be installed. - def self.plugindir(install_dir=Gem.dir) + def self.plugindir(install_dir = Gem.dir) File.join install_dir, "plugins" end @@ -534,7 +534,7 @@ def self.extension_api_version # :nodoc: # Note that find_files will return all files even if they are from different # versions of the same gem. See also find_latest_files - def self.find_files(glob, check_load_path=true) + def self.find_files(glob, check_load_path = true) files = [] files = find_files_from_load_path glob if check_load_path @@ -571,7 +571,7 @@ def self.find_files_from_load_path(glob) # :nodoc: # Unlike find_files, find_latest_files will return only files from the # latest version of a gem. - def self.find_latest_files(glob, check_load_path=true) + def self.find_latest_files(glob, check_load_path = true) files = [] files = find_files_from_load_path glob if check_load_path diff --git a/lib/rubygems/command.rb b/lib/rubygems/command.rb index 3a149ea38e23e2..d38363f293c79c 100644 --- a/lib/rubygems/command.rb +++ b/lib/rubygems/command.rb @@ -117,7 +117,7 @@ def self.specific_extra_args_hash # Unhandled arguments (gem names, files, etc.) are left in # options[:args]. - def initialize(command, summary=nil, defaults={}) + def initialize(command, summary = nil, defaults = {}) @command = command @summary = summary @program_name = "gem #{command}" diff --git a/lib/rubygems/command_manager.rb b/lib/rubygems/command_manager.rb index 15834ce4dd0c09..8521517a24ef93 100644 --- a/lib/rubygems/command_manager.rb +++ b/lib/rubygems/command_manager.rb @@ -118,7 +118,7 @@ def initialize ## # Register the Symbol +command+ as a gem command. - def register_command(command, obj=false) + def register_command(command, obj = false) @commands[command] = obj end @@ -148,7 +148,7 @@ def command_names ## # Run the command specified by +args+. - def run(args, build_args=nil) + def run(args, build_args = nil) process_args(args, build_args) rescue StandardError, Gem::Timeout::Error => ex if ex.respond_to?(:detailed_message) @@ -165,7 +165,7 @@ def run(args, build_args=nil) terminate_interaction(1) end - def process_args(args, build_args=nil) + def process_args(args, build_args = nil) if args.empty? say Gem::Command::HELP terminate_interaction 1 diff --git a/lib/rubygems/dependency.rb b/lib/rubygems/dependency.rb index d1ec9222af1a89..1e91f493a64eb5 100644 --- a/lib/rubygems/dependency.rb +++ b/lib/rubygems/dependency.rb @@ -217,7 +217,7 @@ def =~(other) # NOTE: Unlike #matches_spec? this method does not return true when the # version is a prerelease version unless this is a prerelease dependency. - def match?(obj, version=nil, allow_prerelease=false) + def match?(obj, version = nil, allow_prerelease = false) if !version name = obj.name version = obj.version diff --git a/lib/rubygems/dependency_installer.rb b/lib/rubygems/dependency_installer.rb index b119dca1cf2912..b4152e83e913b4 100644 --- a/lib/rubygems/dependency_installer.rb +++ b/lib/rubygems/dependency_installer.rb @@ -127,7 +127,7 @@ def consider_remote? # sources. Gems are sorted with newer gems preferred over older gems, and # local gems preferred over remote gems. - def find_gems_with_sources(dep, best_only=false) # :nodoc: + def find_gems_with_sources(dep, best_only = false) # :nodoc: set = Gem::AvailableSet.new if consider_local? diff --git a/lib/rubygems/dependency_list.rb b/lib/rubygems/dependency_list.rb index ad5e59e8c173f1..99643a426d423a 100644 --- a/lib/rubygems/dependency_list.rb +++ b/lib/rubygems/dependency_list.rb @@ -140,7 +140,7 @@ def why_not_ok?(quick = false) # If removing the gemspec creates breaks a currently ok dependency, then it # is NOT ok to remove the gemspec. - def ok_to_remove?(full_name, check_dev=true) + def ok_to_remove?(full_name, check_dev = true) gem_to_remove = find_name full_name # If the state is inconsistent, at least don't crash diff --git a/lib/rubygems/deprecate.rb b/lib/rubygems/deprecate.rb index a20649cbdab166..303b344d42c838 100644 --- a/lib/rubygems/deprecate.rb +++ b/lib/rubygems/deprecate.rb @@ -126,7 +126,7 @@ def deprecate(name, repl, year, month) # telling the user of +repl+ (unless +repl+ is :none) and the # Rubygems version that it is planned to go away. - def rubygems_deprecate(name, replacement=:none, version=nil) + def rubygems_deprecate(name, replacement = :none, version = nil) class_eval do old = "_deprecated_#{name}" alias_method old, name diff --git a/lib/rubygems/errors.rb b/lib/rubygems/errors.rb index 57fb3eb12008a1..4bbc5217e0e639 100644 --- a/lib/rubygems/errors.rb +++ b/lib/rubygems/errors.rb @@ -26,7 +26,7 @@ class LoadError < ::LoadError # system. Instead of rescuing from this class, make sure to rescue from the # superclass Gem::LoadError to catch all types of load errors. class MissingSpecError < Gem::LoadError - def initialize(name, requirement, extra_message=nil) + def initialize(name, requirement, extra_message = nil) @name = name @requirement = requirement @extra_message = extra_message diff --git a/lib/rubygems/exceptions.rb b/lib/rubygems/exceptions.rb index 793324b875c754..adf7ad6d7d05ac 100644 --- a/lib/rubygems/exceptions.rb +++ b/lib/rubygems/exceptions.rb @@ -110,7 +110,7 @@ class Gem::SpecificGemNotFoundException < Gem::GemNotFoundException # and +version+. Any +errors+ encountered when attempting to find the gem # are also stored. - def initialize(name, version, errors=nil) + def initialize(name, version, errors = nil) super "Could not find a valid gem '#{name}' (#{version}) locally or in a repository" @name = name @@ -261,7 +261,7 @@ class Gem::UnsatisfiableDependencyError < Gem::DependencyError # Creates a new UnsatisfiableDependencyError for the unsatisfiable # Gem::Resolver::DependencyRequest +dep+ - def initialize(dep, platform_mismatch=nil) + def initialize(dep, platform_mismatch = nil) if platform_mismatch && !platform_mismatch.empty? plats = platform_mismatch.map {|x| x.platform.to_s }.sort.uniq super "Unable to resolve dependency: No match for '#{dep}' on this platform. Found: #{plats.join(", ")}" diff --git a/lib/rubygems/ext/builder.rb b/lib/rubygems/ext/builder.rb index 05cd735bd90d4f..b47996d0920bb3 100644 --- a/lib/rubygems/ext/builder.rb +++ b/lib/rubygems/ext/builder.rb @@ -11,6 +11,9 @@ class Gem::Ext::Builder include Gem::UserInteraction + class NoMakefileError < Gem::InstallError + end + attr_accessor :build_args # :nodoc: def self.class_name @@ -21,7 +24,8 @@ def self.class_name def self.make(dest_path, results, make_dir = Dir.pwd, sitedir = nil, targets = ["clean", "", "install"], target_rbconfig: Gem.target_rbconfig) unless File.exist? File.join(make_dir, "Makefile") - raise Gem::InstallError, "Makefile not found" + # No makefile exists, nothing to do. + raise NoMakefileError, "No Makefile found in #{make_dir}" end # try to find make program from Ruby configure arguments first diff --git a/lib/rubygems/ext/cargo_builder.rb b/lib/rubygems/ext/cargo_builder.rb index 21b50f394d552d..e58d0bb75ccb9d 100644 --- a/lib/rubygems/ext/cargo_builder.rb +++ b/lib/rubygems/ext/cargo_builder.rb @@ -15,7 +15,7 @@ def initialize end def build(extension, dest_path, results, args = [], lib_dir = nil, cargo_dir = Dir.pwd, - target_rbconfig=Gem.target_rbconfig) + target_rbconfig = Gem.target_rbconfig) require "tempfile" require "fileutils" diff --git a/lib/rubygems/ext/cmake_builder.rb b/lib/rubygems/ext/cmake_builder.rb index 34564f668da87d..c7bfbb8a57ad27 100644 --- a/lib/rubygems/ext/cmake_builder.rb +++ b/lib/rubygems/ext/cmake_builder.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true class Gem::Ext::CmakeBuilder < Gem::Ext::Builder - def self.build(extension, dest_path, results, args=[], lib_dir=nil, cmake_dir=Dir.pwd, - target_rbconfig=Gem.target_rbconfig) + def self.build(extension, dest_path, results, args = [], lib_dir = nil, cmake_dir = Dir.pwd, + target_rbconfig = Gem.target_rbconfig) if target_rbconfig.path warn "--target-rbconfig is not yet supported for CMake extensions. Ignoring" end diff --git a/lib/rubygems/ext/configure_builder.rb b/lib/rubygems/ext/configure_builder.rb index d91b1ec5e82a17..76c1cd8b197548 100644 --- a/lib/rubygems/ext/configure_builder.rb +++ b/lib/rubygems/ext/configure_builder.rb @@ -7,8 +7,8 @@ #++ class Gem::Ext::ConfigureBuilder < Gem::Ext::Builder - def self.build(extension, dest_path, results, args=[], lib_dir=nil, configure_dir=Dir.pwd, - target_rbconfig=Gem.target_rbconfig) + def self.build(extension, dest_path, results, args = [], lib_dir = nil, configure_dir = Dir.pwd, + target_rbconfig = Gem.target_rbconfig) if target_rbconfig.path warn "--target-rbconfig is not yet supported for configure-based extensions. Ignoring" end diff --git a/lib/rubygems/ext/ext_conf_builder.rb b/lib/rubygems/ext/ext_conf_builder.rb index e652a221f83b32..ec2fa59412df64 100644 --- a/lib/rubygems/ext/ext_conf_builder.rb +++ b/lib/rubygems/ext/ext_conf_builder.rb @@ -7,8 +7,8 @@ #++ class Gem::Ext::ExtConfBuilder < Gem::Ext::Builder - def self.build(extension, dest_path, results, args=[], lib_dir=nil, extension_dir=Dir.pwd, - target_rbconfig=Gem.target_rbconfig) + def self.build(extension, dest_path, results, args = [], lib_dir = nil, extension_dir = Dir.pwd, + target_rbconfig = Gem.target_rbconfig) require "fileutils" require "tempfile" @@ -66,6 +66,10 @@ def self.build(extension, dest_path, results, args=[], lib_dir=nil, extension_di end results + rescue Gem::Ext::Builder::NoMakefileError => error + results << error.message + results << "Skipping make for #{extension} as no Makefile was found." + # We are good, do not re-raise the error. ensure FileUtils.rm_rf tmp_dest if tmp_dest end diff --git a/lib/rubygems/ext/rake_builder.rb b/lib/rubygems/ext/rake_builder.rb index 8edd8d1373768f..0eac5a180ca3ca 100644 --- a/lib/rubygems/ext/rake_builder.rb +++ b/lib/rubygems/ext/rake_builder.rb @@ -7,8 +7,8 @@ #++ class Gem::Ext::RakeBuilder < Gem::Ext::Builder - def self.build(extension, dest_path, results, args=[], lib_dir=nil, extension_dir=Dir.pwd, - target_rbconfig=Gem.target_rbconfig) + def self.build(extension, dest_path, results, args = [], lib_dir = nil, extension_dir = Dir.pwd, + target_rbconfig = Gem.target_rbconfig) if target_rbconfig.path warn "--target-rbconfig is not yet supported for Rake extensions. Ignoring" end diff --git a/lib/rubygems/installer.rb b/lib/rubygems/installer.rb index 2b3200223a5db7..0cfe59b5bb5be3 100644 --- a/lib/rubygems/installer.rb +++ b/lib/rubygems/installer.rb @@ -67,23 +67,6 @@ class Gem::Installer attr_reader :package class << self - # - # Changes in rubygems to lazily loading `rubygems/command` (in order to - # lazily load `optparse` as a side effect) affect bundler's custom installer - # which uses `Gem::Command` without requiring it (up until bundler 2.2.29). - # This hook is to compensate for that missing require. - # - # TODO: Remove when rubygems no longer supports running on bundler older - # than 2.2.29. - - def inherited(klass) - if klass.name == "Bundler::RubyGemsGemInstaller" - require "rubygems/command" - end - - super(klass) - end - ## # Overrides the executable format. # @@ -170,7 +153,7 @@ def self.for_spec(spec, options = {}) # process. If not set, then Gem::Command.build_args is used # :post_install_message:: Print gem post install message if true - def initialize(package, options={}) + def initialize(package, options = {}) require "fileutils" @options = options diff --git a/lib/rubygems/name_tuple.rb b/lib/rubygems/name_tuple.rb index 3f4a6fcf3dfbb1..67c6f30a3dfff4 100644 --- a/lib/rubygems/name_tuple.rb +++ b/lib/rubygems/name_tuple.rb @@ -6,7 +6,7 @@ # wrap the data returned from the indexes. class Gem::NameTuple - def initialize(name, version, platform=Gem::Platform::RUBY) + def initialize(name, version, platform = Gem::Platform::RUBY) @name = name @version = version diff --git a/lib/rubygems/package/tar_writer.rb b/lib/rubygems/package/tar_writer.rb index 7dcb9737c06620..39fed9e2afe74b 100644 --- a/lib/rubygems/package/tar_writer.rb +++ b/lib/rubygems/package/tar_writer.rb @@ -99,7 +99,7 @@ def initialize(io) # Gem.source_date_epoch if not specified), and yields an IO for # writing the file to - def add_file(name, mode, mtime=nil) # :yields: io + def add_file(name, mode, mtime = nil) # :yields: io check_closed name, prefix = split_name name diff --git a/lib/rubygems/remote_fetcher.rb b/lib/rubygems/remote_fetcher.rb index 355a668b39f81e..6ed0842963e6f0 100644 --- a/lib/rubygems/remote_fetcher.rb +++ b/lib/rubygems/remote_fetcher.rb @@ -72,7 +72,7 @@ def self.fetcher # +headers+: A set of additional HTTP headers to be sent to the server when # fetching the gem. - def initialize(proxy=nil, dns=nil, headers={}) + def initialize(proxy = nil, dns = nil, headers = {}) require_relative "core_ext/tcpsocket_init" if Gem.configuration.ipv4_fallback_enabled require_relative "vendored_net_http" require_relative "vendor/uri/lib/uri" diff --git a/lib/rubygems/resolver.rb b/lib/rubygems/resolver.rb index 9bf5f8093041d7..ed4cbde3bab12c 100644 --- a/lib/rubygems/resolver.rb +++ b/lib/rubygems/resolver.rb @@ -144,7 +144,7 @@ def activation_request(dep, possible) # :nodoc: [spec, activation_request] end - def requests(s, act, reqs=[]) # :nodoc: + def requests(s, act, reqs = []) # :nodoc: return reqs if @ignore_dependencies s.fetch_development_dependencies if @development diff --git a/lib/rubygems/resolver/conflict.rb b/lib/rubygems/resolver/conflict.rb index 367a36b43d7fe5..77c3add4b32d21 100644 --- a/lib/rubygems/resolver/conflict.rb +++ b/lib/rubygems/resolver/conflict.rb @@ -21,7 +21,7 @@ class Gem::Resolver::Conflict # Creates a new resolver conflict when +dependency+ is in conflict with an # already +activated+ specification. - def initialize(dependency, activated, failed_dep=dependency) + def initialize(dependency, activated, failed_dep = dependency) @dependency = dependency @activated = activated @failed_dep = failed_dep diff --git a/lib/rubygems/source.rb b/lib/rubygems/source.rb index 772ad04bc92575..8b031e27a8d611 100644 --- a/lib/rubygems/source.rb +++ b/lib/rubygems/source.rb @@ -190,7 +190,7 @@ def load_specs(type) # Downloads +spec+ and writes it to +dir+. See also # Gem::RemoteFetcher#download. - def download(spec, dir=Dir.pwd) + def download(spec, dir = Dir.pwd) fetcher = Gem::RemoteFetcher.fetcher fetcher.download spec, uri.to_s, dir end @@ -210,7 +210,7 @@ def pretty_print(q) # :nodoc: end end - def typo_squatting?(host, distance_threshold=4) + def typo_squatting?(host, distance_threshold = 4) return if @uri.host.nil? levenshtein_distance(@uri.host, host).between? 1, distance_threshold end diff --git a/lib/rubygems/spec_fetcher.rb b/lib/rubygems/spec_fetcher.rb index 285f117b393269..835dedf9489a2c 100644 --- a/lib/rubygems/spec_fetcher.rb +++ b/lib/rubygems/spec_fetcher.rb @@ -83,7 +83,7 @@ def initialize(sources = nil) # # If +matching_platform+ is false, gems for all platforms are returned. - def search_for_dependency(dependency, matching_platform=true) + def search_for_dependency(dependency, matching_platform = true) found = {} rejected_specs = {} @@ -130,7 +130,7 @@ def search_for_dependency(dependency, matching_platform=true) ## # Return all gem name tuples who's names match +obj+ - def detect(type=:complete) + def detect(type = :complete) tuples = [] list, _ = available_specs(type) @@ -150,7 +150,7 @@ def detect(type=:complete) # # If +matching_platform+ is false, gems for all platforms are returned. - def spec_for_dependency(dependency, matching_platform=true) + def spec_for_dependency(dependency, matching_platform = true) tuples, errors = search_for_dependency(dependency, matching_platform) specs = [] @@ -280,7 +280,7 @@ def available_specs(type) # Retrieves NameTuples from +source+ of the given +type+ (:prerelease, # etc.). If +gracefully_ignore+ is true, errors are ignored. - def tuples_for(source, type, gracefully_ignore=false) # :nodoc: + def tuples_for(source, type, gracefully_ignore = false) # :nodoc: @caches[type][source.uri] ||= source.load_specs(type).sort_by(&:name) rescue Gem::RemoteFetcher::FetchError diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb index 68ebbf8bc31454..1d351f8aff9746 100644 --- a/lib/rubygems/specification.rb +++ b/lib/rubygems/specification.rb @@ -1757,7 +1757,7 @@ def dependencies # # [depending_gem, dependency, [list_of_gems_that_satisfy_dependency]] - def dependent_gems(check_dev=true) + def dependent_gems(check_dev = true) out = [] Gem::Specification.each do |spec| deps = check_dev ? spec.dependencies : spec.runtime_dependencies diff --git a/lib/rubygems/text.rb b/lib/rubygems/text.rb index da0795b771b350..88d4ce59b4b9ae 100644 --- a/lib/rubygems/text.rb +++ b/lib/rubygems/text.rb @@ -21,7 +21,7 @@ def truncate_text(text, description, max_length = 100_000) # Wraps +text+ to +wrap+ characters and optionally indents by +indent+ # characters - def format_text(text, wrap, indent=0) + def format_text(text, wrap, indent = 0) result = [] work = clean_text(text) diff --git a/lib/rubygems/user_interaction.rb b/lib/rubygems/user_interaction.rb index 0172c4ee897a40..571137629406fb 100644 --- a/lib/rubygems/user_interaction.rb +++ b/lib/rubygems/user_interaction.rb @@ -193,7 +193,7 @@ class Gem::StreamUI # then special operations (like asking for passwords) will use the TTY # commands to disable character echo. - def initialize(in_stream, out_stream, err_stream=$stderr, usetty=true) + def initialize(in_stream, out_stream, err_stream = $stderr, usetty = true) @ins = in_stream @outs = out_stream @errs = err_stream @@ -246,7 +246,7 @@ def choose_from_list(question, list) # to a tty, raises an exception if default is nil, otherwise returns # default. - def ask_yes_no(question, default=nil) + def ask_yes_no(question, default = nil) unless tty? if default.nil? raise Gem::OperationNotSupportedError, @@ -325,14 +325,14 @@ def _gets_noecho ## # Display a statement. - def say(statement="") + def say(statement = "") @outs.puts statement end ## # Display an informational alert. Will ask +question+ if it is not nil. - def alert(statement, question=nil) + def alert(statement, question = nil) @outs.puts "INFO: #{statement}" ask(question) if question end @@ -340,7 +340,7 @@ def alert(statement, question=nil) ## # Display a warning on stderr. Will ask +question+ if it is not nil. - def alert_warning(statement, question=nil) + def alert_warning(statement, question = nil) @errs.puts "WARNING: #{statement}" ask(question) if question end @@ -349,7 +349,7 @@ def alert_warning(statement, question=nil) # Display an error message in a location expected to get error messages. # Will ask +question+ if it is not nil. - def alert_error(statement, question=nil) + def alert_error(statement, question = nil) @errs.puts "ERROR: #{statement}" ask(question) if question end diff --git a/lib/rubygems/validator.rb b/lib/rubygems/validator.rb index 57e0747eb4a7d5..eb5b513570778e 100644 --- a/lib/rubygems/validator.rb +++ b/lib/rubygems/validator.rb @@ -59,7 +59,7 @@ def <=>(other) # :nodoc: #-- # TODO needs further cleanup - def alien(gems=[]) + def alien(gems = []) errors = Hash.new {|h,k| h[k] = {} } Gem::Specification.each do |spec| diff --git a/prism/generate-srcs.mk.rb b/prism/generate-srcs.mk.rb new file mode 100644 index 00000000000000..af031ef2e4a71a --- /dev/null +++ b/prism/generate-srcs.mk.rb @@ -0,0 +1,17 @@ +require_relative 'templates/template' + +puts %[ +PRISM_TEMPLATES_DIR = $(PRISM_SRCDIR)/templates +PRISM_TEMPLATE = $(PRISM_TEMPLATES_DIR)/template.rb +PRISM_CONFIG = $(PRISM_SRCDIR)/config.yml +] + +Prism::Template::TEMPLATES.map do |t| + /\.(?:[ch]|rb)\z/ =~ t or next + s = t.sub(%r[\A(?:(src)|ext|include)/]) {$1 && 'prism/'} + puts %[ +main srcs: $(srcdir)/#{s} +$(srcdir)/#{s}: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/#{t}.erb +\t$(Q) $(BASERUBY) $(PRISM_TEMPLATE) #{t} $@ +] +end diff --git a/spec/bundler/commands/list_spec.rb b/spec/bundler/commands/list_spec.rb index cc0db9169d64ad..c890646a816cc4 100644 --- a/spec/bundler/commands/list_spec.rb +++ b/spec/bundler/commands/list_spec.rb @@ -1,6 +1,28 @@ # frozen_string_literal: true +require "json" + RSpec.describe "bundle list" do + def find_gem_name(json:, name:) + parse_json(json)["gems"].detect {|h| h["name"] == name } + end + + def parse_json(json) + JSON.parse(json) + end + + context "in verbose mode" do + it "logs the actual flags passed to the command" do + install_gemfile <<-G + source "https://gem.repo1" + G + + bundle "list --verbose" + + expect(out).to include("Running `bundle list --verbose`") + end + end + context "with name-only and paths option" do it "raises an error" do bundle "list --name-only --paths", raise_on_error: false @@ -17,6 +39,20 @@ end end + context "with invalid format option" do + before do + install_gemfile <<-G + source "https://gem.repo1" + G + end + + it "raises an error" do + bundle "list --format=nope", raise_on_error: false + + expect(err).to eq "Unknown option`--format=nope`. Supported formats: `json`" + end + end + describe "with without-group option" do before do install_gemfile <<-G @@ -36,6 +72,17 @@ expect(out).to include(" * rails (2.3.2)") expect(out).not_to include(" * rspec (1.2.7)") end + + it "prints the gems not in the specified group with json" do + bundle "list --without-group test --format=json" + + gem = find_gem_name(json: out, name: "myrack") + expect(gem["version"]).to eq("1.0.0") + gem = find_gem_name(json: out, name: "rails") + expect(gem["version"]).to eq("2.3.2") + gem = find_gem_name(json: out, name: "rspec") + expect(gem).to be_nil + end end context "when group is not found" do @@ -54,6 +101,17 @@ expect(out).not_to include(" * rails (2.3.2)") expect(out).not_to include(" * rspec (1.2.7)") end + + it "prints the gems not in the specified groups with json" do + bundle "list --without-group test production --format=json" + + gem = find_gem_name(json: out, name: "myrack") + expect(gem["version"]).to eq("1.0.0") + gem = find_gem_name(json: out, name: "rails") + expect(gem).to be_nil + gem = find_gem_name(json: out, name: "rspec") + expect(gem).to be_nil + end end end @@ -75,6 +133,15 @@ expect(out).to include(" * myrack (1.0.0)") expect(out).not_to include(" * rspec (1.2.7)") end + + it "prints the gems in the specified group with json" do + bundle "list --only-group default --format=json" + + gem = find_gem_name(json: out, name: "myrack") + expect(gem["version"]).to eq("1.0.0") + gem = find_gem_name(json: out, name: "rspec") + expect(gem).to be_nil + end end context "when group is not found" do @@ -93,6 +160,17 @@ expect(out).to include(" * rails (2.3.2)") expect(out).not_to include(" * rspec (1.2.7)") end + + it "prints the gems in the specified groups with json" do + bundle "list --only-group default production --format=json" + + gem = find_gem_name(json: out, name: "myrack") + expect(gem["version"]).to eq("1.0.0") + gem = find_gem_name(json: out, name: "rails") + expect(gem["version"]).to eq("2.3.2") + gem = find_gem_name(json: out, name: "rspec") + expect(gem).to be_nil + end end end @@ -112,6 +190,15 @@ expect(out).to include("myrack") expect(out).to include("rspec") end + + it "prints only the name of the gems in the bundle with json" do + bundle "list --name-only --format=json" + + gem = find_gem_name(json: out, name: "myrack") + expect(gem.keys).to eq(["name"]) + gem = find_gem_name(json: out, name: "rspec") + expect(gem.keys).to eq(["name"]) + end end context "with paths option" do @@ -146,6 +233,27 @@ expect(out).to match(%r{.*\/git_test\-\w}) expect(out).to match(%r{.*\/gemspec_test}) end + + it "prints the path of each gem in the bundle with json" do + bundle "list --paths --format=json" + + gem = find_gem_name(json: out, name: "rails") + expect(gem["path"]).to match(%r{.*\/rails\-2\.3\.2}) + expect(gem["git_version"]).to be_nil + + gem = find_gem_name(json: out, name: "myrack") + expect(gem["path"]).to match(%r{.*\/myrack\-1\.2}) + expect(gem["git_version"]).to be_nil + + gem = find_gem_name(json: out, name: "git_test") + expect(gem["path"]).to match(%r{.*\/git_test\-\w}) + expect(gem["git_version"]).to be_truthy + expect(gem["git_version"].strip).to eq(gem["git_version"]) + + gem = find_gem_name(json: out, name: "gemspec_test") + expect(gem["path"]).to match(%r{.*\/gemspec_test}) + expect(gem["git_version"]).to be_nil + end end context "when no gems are in the gemfile" do @@ -159,6 +267,11 @@ bundle "list" expect(out).to include("No gems in the Gemfile") end + + it "prints empty json" do + bundle "list --format=json" + expect(parse_json(out)["gems"]).to eq([]) + end end context "without options" do @@ -175,6 +288,13 @@ bundle "list" expect(out).to include(" * myrack (1.0.0)") end + + it "lists gems installed in the bundle with json" do + bundle "list --format=json" + + gem = find_gem_name(json: out, name: "myrack") + expect(gem["version"]).to eq("1.0.0") + end end context "when using the ls alias" do diff --git a/spec/bundler/commands/show_spec.rb b/spec/bundler/commands/show_spec.rb index 82ec6e51f2e74e..ba903ac4957a5a 100644 --- a/spec/bundler/commands/show_spec.rb +++ b/spec/bundler/commands/show_spec.rb @@ -3,8 +3,10 @@ RSpec.describe "bundle show" do context "with a standard Gemfile" do before :each do + build_repo2 + install_gemfile <<-G - source "https://gem.repo1" + source "https://gem.repo2" gem "rails" G end @@ -86,6 +88,24 @@ \tStatus: Up to date MSG end + + it "includes up to date status in summary of gems" do + update_repo2 do + build_gem "rails", "3.0.0" + end + + bundle "show --verbose" + + expect(out).to include <<~MSG + * rails (2.3.2) + \tSummary: This is just a fake gem for testing + \tHomepage: http://example.com + \tStatus: Outdated - 2.3.2 < 3.0.0 + MSG + + # check lockfile is not accidentally updated + expect(lockfile).to include("actionmailer (2.3.2)") + end end context "with a git repo in the Gemfile" do @@ -219,6 +239,6 @@ end end -RSpec.describe "bundle show", bundler: "4" do +RSpec.describe "bundle show", bundler: "5" do pending "shows a friendly error about the command removal" end diff --git a/spec/bundler/commands/update_spec.rb b/spec/bundler/commands/update_spec.rb index 22bb1662e6571c..7702c723977559 100644 --- a/spec/bundler/commands/update_spec.rb +++ b/spec/bundler/commands/update_spec.rb @@ -445,6 +445,49 @@ expect(out).to include("Installing sneakers 2.11.0").and include("Installing rake 13.0.6") end + it "downgrades indirect dependencies if required to fulfill an explicit upgrade request" do + build_repo4 do + build_gem "rbs", "3.6.1" + build_gem "rbs", "3.9.4" + + build_gem "solargraph", "0.56.0" do |s| + s.add_dependency "rbs", "~> 3.3" + end + + build_gem "solargraph", "0.56.2" do |s| + s.add_dependency "rbs", "~> 3.6.1" + end + end + + gemfile <<~G + source "https://gem.repo4" + + gem 'solargraph', '~> 0.56.0' + G + + lockfile <<~L + GEM + remote: https://gem.repo4/ + specs: + rbs (3.9.4) + solargraph (0.56.0) + rbs (~> 3.3) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + solargraph (~> 0.56.0) + + BUNDLED WITH + #{Bundler::VERSION} + L + + bundle "lock --update solargraph" + + expect(lockfile).to include("solargraph (0.56.2)") + end + it "does not downgrade direct dependencies unnecessarily" do build_repo4 do build_gem "redis", "4.8.1" @@ -1809,7 +1852,7 @@ system_gems "bundler-9.9.9", path: local_gem_path bundle "update --bundler=9.9.9", env: { "BUNDLE_FROZEN" => "true" }, raise_on_error: false - expect(err).to include("An update to the version of bundler itself was requested, but the lockfile can't be updated because frozen mode is set") + expect(err).to include("An update to the version of Bundler itself was requested, but the lockfile can't be updated because frozen mode is set") end end diff --git a/spec/bundler/install/gemfile/git_spec.rb b/spec/bundler/install/gemfile/git_spec.rb index cd83ad71c07e63..216548cf27ccee 100644 --- a/spec/bundler/install/gemfile/git_spec.rb +++ b/spec/bundler/install/gemfile/git_spec.rb @@ -2,12 +2,8 @@ RSpec.describe "bundle install with git sources" do describe "when floating on main" do - before :each do - build_git "foo" do |s| - s.executables = "foobar" - end - - install_gemfile <<-G + let(:base_gemfile) do + <<-G source "https://gem.repo1" git "#{lib_path("foo-1.0")}" do gem 'foo' @@ -15,7 +11,16 @@ G end + let(:install_base_gemfile) do + build_git "foo" do |s| + s.executables = "foobar" + end + + install_gemfile base_gemfile + end + it "fetches gems" do + install_base_gemfile expect(the_bundle).to include_gems("foo 1.0") run <<-RUBY @@ -26,17 +31,57 @@ expect(out).to eq("WIN") end + it "does not (yet?) enforce CHECKSUMS" do + build_git "foo" + revision = revision_for(lib_path("foo-1.0")) + + bundle "config set lockfile_checksums true" + gemfile base_gemfile + + lockfile <<~L + GIT + remote: #{lib_path("foo-1.0")} + revision: #{revision} + specs: + foo (1.0) + + GEM + remote: https://gem.repo1/ + specs: + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + foo! + + CHECKSUMS + foo (1.0) + + BUNDLED WITH + #{Bundler::VERSION} + L + + bundle "config set frozen true" + + bundle "install" + expect(the_bundle).to include_gems("foo 1.0") + end + it "caches the git repo" do + install_base_gemfile expect(Dir["#{default_bundle_path}/cache/bundler/git/foo-1.0-*"]).to have_attributes size: 1 end it "does not write to cache on bundler/setup" do + install_base_gemfile FileUtils.rm_r(default_cache_path) ruby "require 'bundler/setup'" expect(default_cache_path).not_to exist end it "caches the git repo globally and properly uses the cached repo on the next invocation" do + install_base_gemfile pristine_system_gems bundle "config set global_gem_cache true" bundle :install @@ -48,6 +93,7 @@ end it "caches the evaluated gemspec" do + install_base_gemfile git = update_git "foo" do |s| s.executables = ["foobar"] # we added this the first time, so keep it now s.files = ["bin/foobar"] # updating git nukes the files list @@ -66,6 +112,7 @@ end it "does not update the git source implicitly" do + install_base_gemfile update_git "foo" install_gemfile bundled_app2("Gemfile"), <<-G, dir: bundled_app2 @@ -84,6 +131,7 @@ end it "sets up git gem executables on the path" do + install_base_gemfile bundle "exec foobar" expect(out).to eq("1.0") end @@ -136,7 +184,7 @@ it "still works after moving the application directory" do bundle "config set --local path vendor/bundle" - bundle "install" + install_base_gemfile FileUtils.mv bundled_app, tmp("bundled_app.bck") @@ -145,7 +193,7 @@ it "can still install after moving the application directory" do bundle "config set --local path vendor/bundle" - bundle "install" + install_base_gemfile FileUtils.mv bundled_app, tmp("bundled_app.bck") diff --git a/spec/bundler/install/gemfile/specific_platform_spec.rb b/spec/bundler/install/gemfile/specific_platform_spec.rb index 71065c36f33507..62540f0488de62 100644 --- a/spec/bundler/install/gemfile/specific_platform_spec.rb +++ b/spec/bundler/install/gemfile/specific_platform_spec.rb @@ -1432,7 +1432,7 @@ end end - it "does not fail when a platform variant is incompatible with the current ruby and another equivalent platform specific variant is part of the resolution", rubygems: ">= 3.3.21" do + it "does not fail when a platform variant is incompatible with the current ruby and another equivalent platform specific variant is part of the resolution" do build_repo4 do build_gem "nokogiri", "1.15.5" @@ -1578,7 +1578,7 @@ end end - it "adds current musl platform, when there are also gnu variants", rubygems: ">= 3.3.21" do + it "adds current musl platform, when there are also gnu variants" do build_repo4 do build_gem "rcee_precompiled", "0.5.0" do |s| s.platform = "x86_64-linux-gnu" diff --git a/spec/bundler/lock/lockfile_spec.rb b/spec/bundler/lock/lockfile_spec.rb index e1fbe6934a1b6e..6b98e0924e41d8 100644 --- a/spec/bundler/lock/lockfile_spec.rb +++ b/spec/bundler/lock/lockfile_spec.rb @@ -1638,7 +1638,7 @@ G expect(err).to eq <<~L.strip - Your lockfile is missing a checksums entry for \"myrack_middleware\", but can't be updated because frozen mode is set + Your lockfile is missing a CHECKSUMS entry for \"myrack_middleware\", but can't be updated because frozen mode is set Run `bundle install` elsewhere and add the updated Gemfile.lock to version control. L @@ -1646,6 +1646,40 @@ expect(the_bundle).not_to include_gems "myrack_middleware 1.0" end + it "raises a clear error when frozen mode is set and lockfile has empty checksums in CHECKSUMS section, and does not install any gems" do + lockfile <<-L + GEM + remote: https://gem.repo2/ + specs: + myrack (0.9.1) + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + myrack + + CHECKSUMS + myrack (0.9.1) + + BUNDLED WITH + #{Bundler::VERSION} + L + + install_gemfile <<-G, env: { "BUNDLE_FROZEN" => "true" }, raise_on_error: false + source "https://gem.repo2" + gem "myrack" + G + + expect(err).to eq <<~L.strip + Your lockfile has an empty CHECKSUMS entry for \"myrack\", but can't be updated because frozen mode is set + + Run `bundle install` elsewhere and add the updated Gemfile.lock to version control. + L + + expect(the_bundle).not_to include_gems "myrack 0.9.1" + end + it "automatically fixes the lockfile when it's missing deps, they conflict with other locked deps, but conflicts are fixable" do build_repo4 do build_gem "other_dep", "0.9" diff --git a/spec/bundler/other/cli_man_pages_spec.rb b/spec/bundler/other/cli_man_pages_spec.rb index 84ffca14e62379..6efd2904d6497a 100644 --- a/spec/bundler/other/cli_man_pages_spec.rb +++ b/spec/bundler/other/cli_man_pages_spec.rb @@ -1,49 +1,72 @@ # frozen_string_literal: true RSpec.describe "bundle commands" do - it "expects all commands to have a man page" do - Bundler::CLI.all_commands.each_key do |command_name| - next if command_name == "cli_help" + it "expects all commands to have all options and subcommands documented" do + check_commands!(Bundler::CLI) - expect(man_page(command_name)).to exist + Bundler::CLI.subcommand_classes.each_value do |klass| + check_commands!(klass) end end - it "expects all commands to have all options documented" do - Bundler::CLI.all_commands.each do |command_name, command| - next if command_name == "cli_help" + private + + def check_commands!(command_class) + command_class.commands.each do |command_name, command| + next if command.is_a?(Bundler::Thor::HiddenCommand) + + if command_class == Bundler::CLI + man_page = man_page(command_name) + expect(man_page).to exist + + check_options!(command, man_page) + else + man_page = man_page(command.ancestor_name) + expect(man_page).to exist - man_page_content = man_page(command_name).read + check_options!(command, man_page) + check_subcommand!(command_name, man_page) + end + end + end - command.options.each do |_, option| - aliases = option.aliases - formatted_aliases = aliases.sort.map {|name| "`#{name}`" }.join(", ") if aliases + def check_options!(command, man_page) + command.options.each do |_, option| + check_option!(option, man_page) + end + end - help = if option.type == :boolean - "* #{append_aliases("`#{option.switch_name}`", formatted_aliases)}:" - elsif option.enum - formatted_aliases = "`#{option.switch_name}`" if aliases.empty? && option.lazy_default - "* #{prepend_aliases(option.enum.sort.map {|enum| "`#{option.switch_name}=#{enum}`" }.join(", "), formatted_aliases)}:" - else - names = [option.switch_name, *aliases] - value = - case option.type - when :array then "" - when :numeric then "" - else option.name.upcase - end + def check_option!(option, man_page) + man_page_content = man_page.read - value = option.type != :numeric && option.lazy_default ? "[=#{value}]" : "=#{value}" + aliases = option.aliases + formatted_aliases = aliases.sort.map {|name| "`#{name}`" }.join(", ") if aliases - "* #{names.map {|name| "`#{name}#{value}`" }.join(", ")}:" + help = if option.type == :boolean + "* #{append_aliases("`#{option.switch_name}`", formatted_aliases)}:" + elsif option.enum + formatted_aliases = "`#{option.switch_name}`" if aliases.empty? && option.lazy_default + "* #{prepend_aliases(option.enum.sort.map {|enum| "`#{option.switch_name}=#{enum}`" }.join(", "), formatted_aliases)}:" + else + names = [option.switch_name, *aliases] + value = + case option.type + when :array then "" + when :numeric then "" + else option.name.upcase end - expect(man_page_content).to include(help) - end + value = option.type != :numeric && option.lazy_default ? "[=#{value}]" : "=#{value}" + + "* #{names.map {|name| "`#{name}#{value}`" }.join(", ")}:" end + + expect(man_page_content).to include(help) end - private + def check_subcommand!(name, man_page) + expect(man_page.read).to match(name) + end def append_aliases(text, aliases) return text if aliases.empty? @@ -57,6 +80,10 @@ def prepend_aliases(text, aliases) "#{aliases}, #{text}" end + def man_page_content(command_name) + man_page(command_name).read + end + def man_page(command_name) source_root.join("lib/bundler/man/bundle-#{command_name}.1.ronn") end diff --git a/spec/bundler/other/major_deprecation_spec.rb b/spec/bundler/other/major_deprecation_spec.rb index 51d490ea7247ac..d57abe45f35259 100644 --- a/spec/bundler/other/major_deprecation_spec.rb +++ b/spec/bundler/other/major_deprecation_spec.rb @@ -199,6 +199,28 @@ pending "fails with a helpful error", bundler: "4" end + context "bundle cache --no-all" do + before do + install_gemfile <<-G + source "https://gem.repo1" + gem "myrack" + G + + bundle "cache --no-all", raise_on_error: false + end + + it "should print a deprecation warning" do + expect(deprecations).to include( + "The `--no-all` flag is deprecated because it relies on being " \ + "remembered across bundler invocations, which bundler will no " \ + "longer do in future versions. Instead please use `bundle config set " \ + "cache_all false`, and stop using this flag" + ) + end + + pending "fails with a helpful error", bundler: "4" + end + context "bundle cache --path" do before do install_gemfile <<-G @@ -592,7 +614,7 @@ end it "prints a deprecation warning informing about its removal" do - expect(deprecations).to include("the `--outdated` flag to `bundle show` was undocumented and will be removed without replacement") + expect(deprecations).to include("the `--outdated` flag to `bundle show` will be removed in favor of `bundle show --verbose`") end pending "fails with a helpful message", bundler: "4" diff --git a/spec/bundler/quality_spec.rb b/spec/bundler/quality_spec.rb index 18d8e20030ce1a..3e5a960a960f2e 100644 --- a/spec/bundler/quality_spec.rb +++ b/spec/bundler/quality_spec.rb @@ -251,58 +251,9 @@ def check_for_specific_pronouns(filename) expect(lib_code).to eq(spec_code) end - it "documents all cli command options in their associated man pages" do - commands = normalize_commands_and_options(Bundler::CLI) - cli_and_man_pages_in_sync!(commands) - - Bundler::CLI.subcommand_classes.each do |_, klass| - subcommands = normalize_commands_and_options(klass) - - cli_and_man_pages_in_sync!(subcommands) - end - end - private def each_line(filename, &block) File.readlines(filename, encoding: "UTF-8").each_with_index(&block) end - - def normalize_commands_and_options(command_class) - commands = {} - - command_class.commands.each do |command_name, command| - next if command.is_a?(Bundler::Thor::HiddenCommand) - - key = command.ancestor_name || command_name - commands[key] ||= [] - # Verify that all subcommands are documented in the main command's man page. - commands[key] << command_name unless command_class == Bundler::CLI - - command.options.each do |_, option| - commands[key] << option.switch_name - end - end - - commands - end - - def cli_and_man_pages_in_sync!(commands) - commands.each do |command_name, opts| - man_page_path = man_tracked_files.find {|f| File.basename(f) == "bundle-#{command_name}.1.ronn" } - expect(man_page_path).to_not be_nil, "The command #{command_name} has no associated man page." - - next if opts.empty? - - man_page_content = File.read(man_page_path) - opts.each do |option_name| - error_msg = <<~EOM - The command #{command_name} has no mention of the option or subcommand `#{option_name}` in its man page. - Document the `#{option_name}` in the man page to discard this error. - EOM - - expect(man_page_content).to match(option_name), error_msg - end - end - end end diff --git a/spec/bundler/resolver/platform_spec.rb b/spec/bundler/resolver/platform_spec.rb index 13f3e152828e16..a1d095d024de10 100644 --- a/spec/bundler/resolver/platform_spec.rb +++ b/spec/bundler/resolver/platform_spec.rb @@ -387,7 +387,7 @@ should_resolve_as %w[thin-1.2.7-x64-mingw-ucrt] end - it "finds universal-mingw gems on x64-mingw-ucrt", rubygems: ">= 3.3.18" do + it "finds universal-mingw gems on x64-mingw-ucrt" do platform "x64-mingw-ucrt" dep "win32-api" should_resolve_as %w[win32-api-1.5.1-universal-mingw32] diff --git a/spec/bundler/runtime/inline_spec.rb b/spec/bundler/runtime/inline_spec.rb index 0467d8b14abdcb..cffaab35799aca 100644 --- a/spec/bundler/runtime/inline_spec.rb +++ b/spec/bundler/runtime/inline_spec.rb @@ -590,14 +590,10 @@ def confirm(msg, newline = nil) expect(err).to be_empty end - it "does not load default timeout" do + it "does not load default timeout", rubygems: ">= 3.5.0" do default_timeout_version = ruby "gem 'timeout', '< 999999'; require 'timeout'; puts Timeout::VERSION", raise_on_error: false skip "timeout isn't a default gem" if default_timeout_version.empty? - # This only works on RubyGems 3.5.0 or higher - ruby "require 'rubygems/timeout'", raise_on_error: false - skip "rubygems under test does not yet vendor timeout" unless last_command.success? - build_repo4 do build_gem "timeout", "999" end diff --git a/string.c b/string.c index 96a9f96bd3432b..d9d8678c71a748 100644 --- a/string.c +++ b/string.c @@ -4501,8 +4501,7 @@ rb_strseq_index(VALUE str, VALUE sub, long offset, int in_byte) /* * call-seq: - * index(substring, offset = 0) -> integer or nil - * index(regexp, offset = 0) -> integer or nil + * index(pattern, offset = 0) -> integer or nil * * :include: doc/string/index.rdoc * @@ -7083,13 +7082,17 @@ rb_str_reverse_bang(VALUE str) * call-seq: * include?(other_string) -> true or false * - * Returns +true+ if +self+ contains +other_string+, +false+ otherwise: + * Returns whether +self+ contains +other_string+: * - * s = 'foo' - * s.include?('f') # => true - * s.include?('fo') # => true - * s.include?('food') # => false + * s = 'bar' + * s.include?('ba') # => true + * s.include?('ar') # => true + * s.include?('bar') # => true + * s.include?('a') # => true + * s.include?('') # => true + * s.include?('foo') # => false * + * Related: see {Querying}[rdoc-ref:String@Querying]. */ VALUE @@ -10681,18 +10684,21 @@ rb_str_scan(VALUE str, VALUE pat) * call-seq: * hex -> integer * - * Interprets the leading substring of +self+ as a string of hexadecimal digits - * (with an optional sign and an optional 0x) and returns the - * corresponding number; - * returns zero if there is no such leading substring: + * Interprets the leading substring of +self+ as hexadecimal; + * returns its integer value: + * + * '0xFFFF'.hex # => 65535 + * 'FFzzzFF'.hex # => 255 # Hex ends at first non-hex character, 'z'. + * 'ffzzzFF'.hex # => 255 # Case does not matter. + * '-FFzzzFF'.hex # => -255 # May have leading '-'. + * '0xFFzzzFF'.hex # => 255 # May have leading '0x'. + * '-0xFFzzzFF'.hex # => -255 # May have leading '-0x'. * - * '0x0a'.hex # => 10 - * '-1234'.hex # => -4660 - * '0'.hex # => 0 - * 'non-numeric'.hex # => 0 + * Returns zero if there is no such leading substring: * - * Related: String#oct. + * 'zzz'.hex # => 0 * + * Related: See {Converting to Non-String}[rdoc-ref:String@Converting+to+Non--5CString]. */ static VALUE diff --git a/template/Makefile.in b/template/Makefile.in index 66ac10de1b4578..daecd1debe9eb2 100644 --- a/template/Makefile.in +++ b/template/Makefile.in @@ -350,13 +350,40 @@ $(LIBRUBY_$(LIBRUBY_WITH_EXT)): $(LIBRUBY_SO_UPDATE) PKG_CONFIG = @PKG_CONFIG@ ruby_pc = @ruby_pc@ $(ruby_pc): config.status Makefile - $(Q)./config.status --file=-:$(srcdir)/template/ruby.pc.in | \ + $(Q) \ + pkg="$(@libdirname@)/pkgconfig" prefix="$(prefix)"; \ + if [ "$(LIBRUBY_RELATIVE)" = yes ]; then \ + case "$$pkg" in "$$prefix"/?*) \ + pkg="$${pkg#$$prefix/}"; \ + prefix='$${pcfiledir}'`echo "/$${pkg}" | sed -e 's|/[^/][^/]*|/..|g'`; \ + esac; \ + fi; \ + ./config.status --file=-:$(srcdir)/template/ruby.pc.in | \ sed -e 's/\$$(\([A-Za-z_][A-Za-z0-9_]*\))/$${\1}/g' \ - -e 's|^prefix=.*|prefix=$(prefix)|' \ + -e "s|^prefix=.*|prefix=$$prefix|" \ > ruby.tmp.pc $(Q)pkg_config=${PKG_CONFIG} && PKG_CONFIG_PATH=. $${pkg_config:-:} --print-errors ruby.tmp $(Q)$(MV) -f ruby.tmp.pc $(ruby_pc) +test-pc: install-data + set -ex; \ + [ -z "$${pkg_config=$(PKG_CONFIG)}" ] && exit; \ + export PKG_CONFIG_PATH=$(DESTDIR)/$(libdir)/pkgconfig$${PKG_CONFIG_PATH:+:$$PKG_CONFIG_PATH}; \ + $${pkg_config} --exists $(ruby_pc:.pc=); \ + path=`$${pkg_config} --variable=prefix $(ruby_pc:.pc=)`; \ + if [ "$(LIBRUBY_RELATIVE)" = yes ]; then \ + test "$$path" -ef "$(DESTDIR)$(prefix)"; \ + else \ + test "$$path" = "$(prefix)"; \ + fi + +install-data: pkgconfig-data pre-install-data do-install-data post-install-data +pre-install-data:: install-prereq +do-install-data: $(PREP) pre-install-data + $(INSTRUBY) --make="$(MAKE)" $(INSTRUBY_ARGS) --install=data +post-install-data:: + @$(NULLCMD) + modular-gc-precheck: $(Q) if test -z $(modular_gc_dir); then \ echo "You must configure with --with-modular-gc to use modular GC"; \ @@ -400,7 +427,7 @@ $(MKFILES): config.status $(srcdir)/version.h $(ABI_VERSION_HDR) { echo "$@ updated, restart."; exit 1; } uncommon.mk: $(srcdir)/common.mk $(srcdir)/depend - sed 's/{\$$([^(){}]*)[^{}]*}//g' $(srcdir)/common.mk $(srcdir)/depend > $@ + sed -f $(srcdir)/tool/prereq.status $(srcdir)/common.mk $(srcdir)/depend > $@ .PHONY: reconfig reconfig-args = $(srcdir)/$(CONFIGURE) $(yes_silence:yes=--silent) $(configure_args) diff --git a/test/-ext-/symbol/test_type.rb b/test/-ext-/symbol/test_type.rb index 2b0fbe5b798b93..ed019062faf218 100644 --- a/test/-ext-/symbol/test_type.rb +++ b/test/-ext-/symbol/test_type.rb @@ -123,16 +123,20 @@ def test_attrset def test_check_id_invalid_type cx = EnvUtil.labeled_class("X\u{1f431}") - assert_raise_with_message(TypeError, /X\u{1F431}/) { - Bug::Symbol.pinneddown?(cx) - } + EnvUtil.with_default_internal(Encoding::UTF_8) do + assert_raise_with_message(TypeError, /X\u{1F431}/) { + Bug::Symbol.pinneddown?(cx) + } + end end def test_check_symbol_invalid_type cx = EnvUtil.labeled_class("X\u{1f431}") - assert_raise_with_message(TypeError, /X\u{1F431}/) { - Bug::Symbol.find(cx) - } + EnvUtil.with_default_internal(Encoding::UTF_8) do + assert_raise_with_message(TypeError, /X\u{1F431}/) { + Bug::Symbol.find(cx) + } + end end def test_const_name_type diff --git a/test/fileutils/test_fileutils.rb b/test/fileutils/test_fileutils.rb index 92308d95573206..2e145b4ee93f83 100644 --- a/test/fileutils/test_fileutils.rb +++ b/test/fileutils/test_fileutils.rb @@ -84,13 +84,10 @@ def check_have_hardlink? return true end - @@no_broken_symlink = false - if /cygwin/ =~ RUBY_PLATFORM and /\bwinsymlinks:native(?:strict)?\b/ =~ ENV["CYGWIN"] - @@no_broken_symlink = true - end + NO_BROKEN_SYMLINK = /cygwin/ =~ RUBY_PLATFORM and /\bwinsymlinks:native(?:strict)?\b/ =~ ENV["CYGWIN"] def no_broken_symlink? - @@no_broken_symlink + NO_BROKEN_SYMLINK end def has_capsh? @@ -196,7 +193,7 @@ def teardown end - TARGETS = %w( data/a data/all data/random data/zero ) + TARGETS = %w( data/a data/all data/random data/zero ).freeze def prepare_data_file File.open('data/a', 'w') {|f| diff --git a/test/json/json_common_interface_test.rb b/test/json/json_common_interface_test.rb index 745400faa14d3a..f656dba5d456e5 100644 --- a/test/json/json_common_interface_test.rb +++ b/test/json/json_common_interface_test.rb @@ -118,6 +118,7 @@ def o.to_s end def test_load + pend "Tempfile" if non_main_ractor? assert_equal @hash, JSON.load(@json) tempfile = Tempfile.open('@json') tempfile.write @json @@ -129,7 +130,7 @@ def test_load assert_equal nil, JSON.load(nil) assert_equal nil, JSON.load('') ensure - tempfile.close! + tempfile&.close! end def test_load_with_proc diff --git a/test/json/json_fixtures_test.rb b/test/json/json_fixtures_test.rb index c153ebef7cbed1..bdeeefff447ca7 100644 --- a/test/json/json_fixtures_test.rb +++ b/test/json/json_fixtures_test.rb @@ -7,20 +7,23 @@ class JSONFixturesTest < Test::Unit::TestCase passed.each do |f| name = File.basename(f).gsub(".", "_") - source = File.read(f) - define_method("test_#{name}") do - assert JSON.parse(source), "Did not pass for fixture '#{File.basename(f)}': #{source.inspect}" + class_eval <<-RUBY, __FILE__, __LINE__+1 + def test_#{name} + assert JSON.parse(File.read(#{f.inspect})), "Did not pass for fixture '#{File.basename(f)}': \#{File.read(#{f.inspect})}" end + RUBY end failed.each do |f| name = File.basename(f).gsub(".", "_") - source = File.read(f) - define_method("test_#{name}") do - assert_raise(JSON::ParserError, JSON::NestingError, - "Did not fail for fixture '#{name}': #{source.inspect}") do - JSON.parse(source) + class_eval <<-RUBY, __FILE__, __LINE__+1 + def test_#{name} + source = File.read(#{f.inspect}) + assert_raise(JSON::ParserError, JSON::NestingError, + "Did not fail for fixture '#{name}': \#{source.inspect}") do + JSON.parse(source) + end end - end + RUBY end end diff --git a/test/json/ractor_test.rb b/test/json/ractor_test.rb index dda34c64c08520..0ebdb0e91a1cfc 100644 --- a/test/json/ractor_test.rb +++ b/test/json/ractor_test.rb @@ -42,7 +42,7 @@ def test_generate else puts "Expected:" puts expected_json - puts "Acutual:" + puts "Actual:" puts actual_json puts exit 1 diff --git a/test/ruby/enc/test_case_comprehensive.rb b/test/ruby/enc/test_case_comprehensive.rb index b812b88b832be2..0692391ea89cf7 100644 --- a/test/ruby/enc/test_case_comprehensive.rb +++ b/test/ruby/enc/test_case_comprehensive.rb @@ -5,8 +5,8 @@ class TestComprehensiveCaseMapping < Test::Unit::TestCase UNICODE_VERSION = RbConfig::CONFIG['UNICODE_VERSION'] - path = File.expand_path("../../../enc/unicode/data/#{UNICODE_VERSION}", __dir__) - UNICODE_DATA_PATH = File.directory?("#{path}/ucd") ? "#{path}/ucd" : path + path = File.expand_path("../../../enc/unicode/data/#{UNICODE_VERSION}", __dir__).freeze + UNICODE_DATA_PATH = File.directory?("#{path}/ucd") ? "#{path}/ucd".freeze : path def self.hex2utf8(s) s.split(' ').map { |c| c.to_i(16) }.pack('U*') @@ -29,7 +29,7 @@ def test_data_files_available end end -TestComprehensiveCaseMapping.data_files_available? and class TestComprehensiveCaseMapping +TestComprehensiveCaseMapping.data_files_available? && will_run_in_main_ractor? && class TestComprehensiveCaseMapping (CaseTest = Struct.new(:method_name, :attributes, :first_data, :follow_data)).class_eval do def initialize(method_name, attributes, first_data, follow_data=first_data) super diff --git a/test/ruby/enc/test_emoji_breaks.rb b/test/ruby/enc/test_emoji_breaks.rb index bb5114680e686f..7789c8eed2bb4d 100644 --- a/test/ruby/enc/test_emoji_breaks.rb +++ b/test/ruby/enc/test_emoji_breaks.rb @@ -46,15 +46,16 @@ def self.files end UNICODE_VERSION = RbConfig::CONFIG['UNICODE_VERSION'] - UNICODE_DATA_PATH = File.expand_path("../../../enc/unicode/data/#{UNICODE_VERSION}/ucd/emoji", __dir__) + UNICODE_DATA_PATH = File.expand_path("../../../enc/unicode/data/#{UNICODE_VERSION}/ucd/emoji", __dir__).freeze EMOJI_VERSION = RbConfig::CONFIG['UNICODE_EMOJI_VERSION'] - EMOJI_DATA_PATH = File.expand_path("../../../enc/unicode/data/emoji/#{EMOJI_VERSION}", __dir__) + EMOJI_DATA_PATH = File.expand_path("../../../enc/unicode/data/emoji/#{EMOJI_VERSION}", __dir__).freeze EMOJI_DATA_FILES = %w[emoji-sequences emoji-test emoji-zwj-sequences].map do |basename| BreakFile.new(basename, EMOJI_DATA_PATH, EMOJI_VERSION) end UNICODE_DATA_FILE = BreakFile.new('emoji-variation-sequences', UNICODE_DATA_PATH, UNICODE_VERSION) EMOJI_DATA_FILES << UNICODE_DATA_FILE + Ractor.make_shareable(EMOJI_DATA_FILES) def self.data_files_available? EMOJI_DATA_FILES.all? do |f| diff --git a/test/ruby/enc/test_grapheme_breaks.rb b/test/ruby/enc/test_grapheme_breaks.rb index 7e6d722d4076e1..88eeaf6cf8ab89 100644 --- a/test/ruby/enc/test_grapheme_breaks.rb +++ b/test/ruby/enc/test_grapheme_breaks.rb @@ -27,9 +27,9 @@ def initialize(line_number, data, comment) end UNICODE_VERSION = RbConfig::CONFIG['UNICODE_VERSION'] - path = File.expand_path("../../../enc/unicode/data/#{UNICODE_VERSION}", __dir__) - UNICODE_DATA_PATH = File.directory?("#{path}/ucd/auxiliary") ? "#{path}/ucd/auxiliary" : path - GRAPHEME_BREAK_TEST_FILE = File.expand_path("#{UNICODE_DATA_PATH}/GraphemeBreakTest.txt", __dir__) + path = File.expand_path("../../../enc/unicode/data/#{UNICODE_VERSION}", __dir__).freeze + UNICODE_DATA_PATH = File.directory?("#{path}/ucd/auxiliary") ? "#{path}/ucd/auxiliary".freeze : path + GRAPHEME_BREAK_TEST_FILE = File.expand_path("#{UNICODE_DATA_PATH}/GraphemeBreakTest.txt", __dir__).freeze def self.file_available? File.exist? GRAPHEME_BREAK_TEST_FILE @@ -44,10 +44,12 @@ def test_data_files_available if file_available? def read_data tests = [] + lineno = 1 File.foreach(GRAPHEME_BREAK_TEST_FILE, encoding: Encoding::UTF_8) do |line| - if $. == 1 and not line.start_with?("# GraphemeBreakTest-#{UNICODE_VERSION}.txt") + if lineno == 1 and not line.start_with?("# GraphemeBreakTest-#{UNICODE_VERSION}.txt") raise "File Version Mismatch" end + lineno += 1 next if /\A#/.match? line tests << BreakTest.new($., *line.chomp.split('#')) rescue 'whatever' end @@ -55,9 +57,9 @@ def read_data end def all_tests - @@tests ||= read_data + @grapheme_breaks_tests ||= read_data rescue Errno::ENOENT - @@tests ||= [] + @grapheme_breaks_tests ||= [] end def test_each_grapheme_cluster diff --git a/test/ruby/enc/test_iso_8859.rb b/test/ruby/enc/test_iso_8859.rb index ed663be24307fb..3b0a830bafeba7 100644 --- a/test/ruby/enc/test_iso_8859.rb +++ b/test/ruby/enc/test_iso_8859.rb @@ -2,7 +2,7 @@ require 'test/unit' class TestISO8859 < Test::Unit::TestCase - ASSERTS = %q( + ASSERTS = Ractor.make_shareable(%q( assert_match(/^(\xdf)\1$/i, "\xdf\xdf") assert_match(/^(\xdf)\1$/i, "ssss") # assert_match(/^(\xdf)\1$/i, "\xdfss") # this must be bug... @@ -18,7 +18,7 @@ class TestISO8859 < Test::Unit::TestCase assert_match(/^[#{ c2 }]+$/i, c1 + c2) end assert_match(/^\xff$/i, "\xff") - ) + )) def test_iso_8859_1 eval("# encoding: iso8859-1\n" + ASSERTS.gsub(/ENCODING/m, "iso8859-1")) diff --git a/test/ruby/enc/test_koi8.rb b/test/ruby/enc/test_koi8.rb index 4a4d233e8d686d..8557ff29590912 100644 --- a/test/ruby/enc/test_koi8.rb +++ b/test/ruby/enc/test_koi8.rb @@ -2,7 +2,7 @@ require "test/unit" class TestKOI8 < Test::Unit::TestCase - ASSERTS = %q( + ASSERTS = Ractor.make_shareable(%q( (0xc0..0xdf).each do |c| c1 = c.chr("ENCODING") c2 = (c + 0x20).chr("ENCODING") @@ -11,7 +11,7 @@ class TestKOI8 < Test::Unit::TestCase assert_match(/^[#{ c1 }]+$/i, c2 + c1) assert_match(/^[#{ c2 }]+$/i, c1 + c2) end - ) + )) def test_koi8_r eval("# encoding: koi8-r\n" + ASSERTS.gsub("ENCODING", "koi8-r")) diff --git a/test/ruby/enc/test_regex_casefold.rb b/test/ruby/enc/test_regex_casefold.rb index b5d5c6e33740f5..a006453e856f23 100644 --- a/test/ruby/enc/test_regex_casefold.rb +++ b/test/ruby/enc/test_regex_casefold.rb @@ -5,8 +5,8 @@ class TestCaseFold < Test::Unit::TestCase UNICODE_VERSION = RbConfig::CONFIG['UNICODE_VERSION'] - path = File.expand_path("../../../enc/unicode/data/#{UNICODE_VERSION}", __dir__) - UNICODE_DATA_PATH = File.directory?("#{path}/ucd") ? "#{path}/ucd" : path + path = File.expand_path("../../../enc/unicode/data/#{UNICODE_VERSION}", __dir__).freeze + UNICODE_DATA_PATH = File.directory?("#{path}/ucd") ? "#{path}/ucd".freeze : path CaseTest = Struct.new :source, :target, :kind, :line def check_downcase_properties(expected, start, *flags) @@ -36,15 +36,21 @@ def to_codepoints(string) end def setup - @@tests ||= read_tests + pend "TODO: tests use define_method" if non_main_ractor? + @regex_casefold_tests ||= read_tests rescue Errno::ENOENT => e - @@tests ||= [] + @regex_casefold_tests ||= [] omit e.message end + def tests + setup + @regex_casefold_tests + end + def self.generate_test_casefold(encoding) define_method "test_mbc_case_fold_#{encoding}" do - @@tests.each do |test| + tests.each do |test| begin source = test.source.encode encoding target = test.target.encode encoding @@ -57,7 +63,7 @@ def self.generate_test_casefold(encoding) end define_method "test_get_case_fold_codes_by_str_#{encoding}" do - @@tests.each do |test| + tests.each do |test| begin source = test.source.encode encoding target = test.target.encode encoding @@ -71,7 +77,7 @@ def self.generate_test_casefold(encoding) end define_method "test_apply_all_case_fold_#{encoding}" do - @@tests.each do |test| + tests.each do |test| begin source = test.source.encode encoding target = test.target.encode encoding @@ -90,7 +96,7 @@ def self.generate_test_casefold(encoding) end def test_downcase_fold - @@tests.each do |test| + tests.each do |test| check_downcase_properties test.target, test.source, :fold end end diff --git a/test/ruby/marshaltestlib.rb b/test/ruby/marshaltestlib.rb index 7f100b787362b4..93a0c6d25606ef 100644 --- a/test/ruby/marshaltestlib.rb +++ b/test/ruby/marshaltestlib.rb @@ -365,6 +365,7 @@ def test_range_cyclic end def test_singleton + omit "ivar of singleton class" if non_main_ractor? o = Object.new def o.m() end assert_raise(TypeError) { marshaltest(o) } diff --git a/test/ruby/test_alias.rb b/test/ruby/test_alias.rb index 539cd4948878b3..31eaa465556a90 100644 --- a/test/ruby/test_alias.rb +++ b/test/ruby/test_alias.rb @@ -227,6 +227,7 @@ def test_alias_method_equation end def test_alias_class_method_added + omit "class ivars" if non_main_ractor? name = nil k = Class.new { def foo;end @@ -241,6 +242,7 @@ def self.method_added(mid) end def test_alias_module_method_added + omit "module ivars" if non_main_ractor? name = nil k = Module.new { def foo;end diff --git a/test/ruby/test_allocation.rb b/test/ruby/test_allocation.rb index a2ccd7bd659d0e..d7a8f9302bc647 100644 --- a/test/ruby/test_allocation.rb +++ b/test/ruby/test_allocation.rb @@ -6,6 +6,7 @@ def setup # The namespace changes on i686 platform triggers a bug to allocate objects unexpectedly. # For now, skip these tests only on i686 pend if RUBY_PLATFORM =~ /^i686/ + pend if non_main_ractor? end def munge_checks(checks) diff --git a/test/ruby/test_argf.rb b/test/ruby/test_argf.rb index 55a06296aa7275..6d209e25cd9bde 100644 --- a/test/ruby/test_argf.rb +++ b/test/ruby/test_argf.rb @@ -7,6 +7,7 @@ class TestArgf < Test::Unit::TestCase def setup + omit "ARGF is not shareable" unless main_ractor? @tmpdir = Dir.mktmpdir @tmp_count = 0 @t1 = make_tempfile("argf-foo", %w"1 2", binmode: true) @@ -15,6 +16,7 @@ def setup end def teardown + return unless main_ractor? FileUtils.rmtree(@tmpdir) end diff --git a/test/ruby/test_array.rb b/test/ruby/test_array.rb index a3ac0a6a0b420d..457140d6f47cbb 100644 --- a/test/ruby/test_array.rb +++ b/test/ruby/test_array.rb @@ -660,14 +660,16 @@ def test_concat assert_raise(TypeError) { @cls[0].concat(:foo) } assert_raise(FrozenError) { @cls[0].freeze.concat(:foo) } - a = @cls[nil] - def (x = Object.new).to_ary - ary = Array.new(2) - ary << [] << [] << :ok + unless multiple_ractors? + a = @cls[nil] + def (x = Object.new).to_ary + ary = Array.new(2) + ary << [] << [] << :ok + end + EnvUtil.under_gc_stress {a.concat(x)} + GC.start + assert_equal(:ok, a.last) end - EnvUtil.under_gc_stress {a.concat(x)} - GC.start - assert_equal(:ok, a.last) end def test_count @@ -1173,44 +1175,52 @@ def test_values_at end def test_join - assert_deprecated_warning {$, = ""} + if main_ractor? + assert_deprecated_warn = method(:assert_deprecated_warn) + assert_deprecated_warning {$, = ""} + else + assert_deprecated_warn = lambda { |*, &blk| blk.call } + end + a = @cls[] - assert_equal("", assert_deprecated_warn(/non-nil value/) {a.join}) + assert_equal("", assert_deprecated_warn.(/non-nil value/) {a.join}) assert_equal("", a.join(',')) - assert_equal(Encoding::US_ASCII, assert_deprecated_warn(/non-nil value/) {a.join}.encoding) + assert_equal(Encoding::US_ASCII, assert_deprecated_warn.(/non-nil value/) {a.join}.encoding) - assert_deprecated_warning {$, = ""} + assert_deprecated_warning {$, = ""} if main_ractor? a = @cls[1, 2] - assert_equal("12", assert_deprecated_warn(/non-nil value/) {a.join}) - assert_equal("12", assert_deprecated_warn(/non-nil value/) {a.join(nil)}) + assert_equal("12", assert_deprecated_warn.(/non-nil value/) {a.join}) + assert_equal("12", assert_deprecated_warn.(/non-nil value/) {a.join(nil)}) assert_equal("1,2", a.join(',')) - assert_deprecated_warning {$, = ""} + assert_deprecated_warning {$, = ""} if main_ractor? a = @cls[1, 2, 3] - assert_equal("123", assert_deprecated_warn(/non-nil value/) {a.join}) - assert_equal("123", assert_deprecated_warn(/non-nil value/) {a.join(nil)}) + assert_equal("123", assert_deprecated_warn.(/non-nil value/) {a.join}) + assert_equal("123", assert_deprecated_warn.(/non-nil value/) {a.join(nil)}) assert_equal("1,2,3", a.join(',')) - assert_deprecated_warning {$, = ":"} + assert_deprecated_warning {$, = ":"} if main_ractor? a = @cls[1, 2, 3] - assert_equal("1:2:3", assert_deprecated_warn(/non-nil value/) {a.join}) - assert_equal("1:2:3", assert_deprecated_warn(/non-nil value/) {a.join(nil)}) + if main_ractor? + assert_equal("1:2:3", assert_deprecated_warn.(/non-nil value/) {a.join}) + assert_equal("1:2:3", assert_deprecated_warn.(/non-nil value/) {a.join(nil)}) + end assert_equal("1,2,3", a.join(',')) - assert_deprecated_warning {$, = ""} + assert_deprecated_warning {$, = ""} if main_ractor? e = ''.force_encoding('EUC-JP') u = ''.force_encoding('UTF-8') - assert_equal(Encoding::US_ASCII, assert_deprecated_warn(/non-nil value/) {[[]].join}.encoding) - assert_equal(Encoding::US_ASCII, assert_deprecated_warn(/non-nil value/) {[1, [u]].join}.encoding) - assert_equal(Encoding::UTF_8, assert_deprecated_warn(/non-nil value/) {[u, [e]].join}.encoding) - assert_equal(Encoding::UTF_8, assert_deprecated_warn(/non-nil value/) {[u, [1]].join}.encoding) - assert_equal(Encoding::UTF_8, assert_deprecated_warn(/non-nil value/) {[Struct.new(:to_str).new(u)].join}.encoding) + assert_equal(Encoding::US_ASCII, assert_deprecated_warn.(/non-nil value/) {[[]].join}.encoding) + assert_equal(Encoding::US_ASCII, assert_deprecated_warn.(/non-nil value/) {[1, [u]].join}.encoding) + assert_equal(Encoding::UTF_8, assert_deprecated_warn.(/non-nil value/) {[u, [e]].join}.encoding) + assert_equal(Encoding::UTF_8, assert_deprecated_warn.(/non-nil value/) {[u, [1]].join}.encoding) + assert_equal(Encoding::UTF_8, assert_deprecated_warn.(/non-nil value/) {[Struct.new(:to_str).new(u)].join}.encoding) bug5379 = '[ruby-core:39776]' - assert_equal(Encoding::US_ASCII, assert_deprecated_warn(/non-nil value/) {[[], u, nil].join}.encoding, bug5379) - assert_equal(Encoding::UTF_8, assert_deprecated_warn(/non-nil value/) {[[], "\u3042", nil].join}.encoding, bug5379) + assert_equal(Encoding::US_ASCII, assert_deprecated_warn.(/non-nil value/) {[[], u, nil].join}.encoding, bug5379) + assert_equal(Encoding::UTF_8, assert_deprecated_warn.(/non-nil value/) {[[], "\u3042", nil].join}.encoding, bug5379) ensure - $, = nil + $, = nil if main_ractor? end def test_last @@ -1468,6 +1478,7 @@ def test_replace end def test_replace_wb_variable_width_alloc + omit "not working properly across ractors" if multiple_ractors? small_embed = [] 4.times { GC.start } # age small_embed large_embed = [1, 2, 3, 4, 5, Array.new] # new young object @@ -1956,33 +1967,33 @@ def o.to_ary end def test_to_s - assert_deprecated_warning {$, = ""} + assert_deprecated_warning {$, = ""} if main_ractor? a = @cls[] assert_equal("[]", a.to_s) - assert_deprecated_warning {$, = ""} + assert_deprecated_warning {$, = ""} if main_ractor? a = @cls[1, 2] assert_equal("[1, 2]", a.to_s) - assert_deprecated_warning {$, = ""} + assert_deprecated_warning {$, = ""} if main_ractor? a = @cls[1, 2, 3] assert_equal("[1, 2, 3]", a.to_s) - assert_deprecated_warning {$, = ""} + assert_deprecated_warning {$, = ""} if main_ractor? a = @cls[1, 2, 3] assert_equal("[1, 2, 3]", a.to_s) ensure - $, = nil + $, = nil if main_ractor? end - StubToH = [ + StubToH = Ractor.make_shareable([ [:key, :value], Object.new.tap do |kvp| def kvp.to_ary [:obtained, :via_to_ary] end end, - ] + ]) def test_to_h array = StubToH @@ -2436,11 +2447,13 @@ def test_product assert_equal(@cls[], @cls[1,2].product([])) bug3394 = '[ruby-dev:41540]' - acc = [] - EnvUtil.under_gc_stress {[1,2].product([3,4,5],[6,8]){|array| acc << array}} - assert_equal([[1, 3, 6], [1, 3, 8], [1, 4, 6], [1, 4, 8], [1, 5, 6], [1, 5, 8], - [2, 3, 6], [2, 3, 8], [2, 4, 6], [2, 4, 8], [2, 5, 6], [2, 5, 8]], - acc, bug3394) + unless multiple_ractors? + acc = [] + EnvUtil.under_gc_stress {[1,2].product([3,4,5],[6,8]){|array| acc << array}} + assert_equal([[1, 3, 6], [1, 3, 8], [1, 4, 6], [1, 4, 8], [1, 5, 6], [1, 5, 8], + [2, 3, 6], [2, 3, 8], [2, 4, 6], [2, 4, 8], [2, 5, 6], [2, 5, 8]], + acc, bug3394) + end def (o = Object.new).to_ary; GC.start; [3,4] end acc = [1,2].product(*[o]*10) @@ -2977,6 +2990,7 @@ def o.==(x); :foo; end end def test_equal_resize + omit "global variable access" if non_main_ractor? $test_equal_resize_a = Array.new(3, &:to_s) $test_equal_resize_b = $test_equal_resize_a.dup o = Object.new @@ -3590,6 +3604,7 @@ def need_continuation EnvUtil.suppress_warning {require 'continuation'} end omit 'requires callcc support' unless respond_to?(:callcc, true) + omit "not ractor safe" if non_main_ractor? end def random_generator(&block) diff --git a/test/ruby/test_assignment.rb b/test/ruby/test_assignment.rb index 3d0e773c825664..05c50c10a0a1f6 100644 --- a/test/ruby/test_assignment.rb +++ b/test/ruby/test_assignment.rb @@ -140,6 +140,7 @@ def test_massign_order end def test_massign_const_order + pend "mutated constants" if non_main_ractor? order = [] test_mod_class = Class.new(Module) do @@ -315,6 +316,7 @@ def []=(i, a); 42; end end def test_yield + omit "lots of undefs" unless main_ractor? def f; yield(nil); end; f {|a| assert_nil(a)}; undef f def f; yield(1); end; f {|a| assert_equal(1, a)}; undef f def f; yield([]); end; f {|a| assert_equal([], a)}; undef f @@ -371,6 +373,7 @@ def f; yield(*[*[1,2]]); end; f {|a,b,*c| assert_equal([1,2,[]], [a,b,c])}; unde end def test_return + omit "lots of undefs" unless main_ractor? def r; return; end; a = r(); assert_nil(a); undef r def r; return nil; end; a = r(); assert_nil(a); undef r def r; return 1; end; a = r(); assert_equal(1, a); undef r @@ -555,6 +558,7 @@ def test_break end def test_next + omit "lots of undefs" unless main_ractor? def r(val); a = yield(); assert_equal(val, a); end r(nil){next} r(nil){next nil} @@ -928,6 +932,7 @@ def check(assign) end def test_assignment + pend "errors with ractors" if non_main_ractor? syntax = Sentence.expand_syntax(Syntax) Sentence.each(syntax, :xassign, 4) {|assign| check(assign) diff --git a/test/ruby/test_ast.rb b/test/ruby/test_ast.rb index 9a7d75c270b661..b9aeaff613e529 100644 --- a/test/ruby/test_ast.rb +++ b/test/ruby/test_ast.rb @@ -116,49 +116,53 @@ def validate_not_cared0(node) SRCDIR = File.expand_path("../../..", __FILE__) Dir.glob("test/**/*.rb", base: SRCDIR).each do |path| - define_method("test_ranges:#{path}") do - helper = Helper.new("#{SRCDIR}/#{path}") - helper.validate_range - - assert_equal([], helper.errors) - end + class_eval <<-RUBY + def #{"test_ranges_#{path}".gsub(/[^\w]/, '_')} + helper = Helper.new("#{SRCDIR}/#{path}") + helper.validate_range + assert_equal([], helper.errors) + end + RUBY end Dir.glob("test/**/*.rb", base: SRCDIR).each do |path| - define_method("test_not_cared:#{path}") do - helper = Helper.new("#{SRCDIR}/#{path}") - helper.validate_not_cared - - assert_equal([], helper.errors) - end + class_eval <<-RUBY + def #{"test_not_cared:#{path}".gsub(/[^\w]/, '_')} + helper = Helper.new("#{SRCDIR}/#{path}") + helper.validate_not_cared + assert_equal([], helper.errors) + end + RUBY end Dir.glob("test/**/*.rb", base: SRCDIR).each do |path| - define_method("test_all_tokens:#{path}") do - node = RubyVM::AbstractSyntaxTree.parse_file("#{SRCDIR}/#{path}", keep_tokens: true) - tokens = node.all_tokens.sort_by { [_1.last[0], _1.last[1]] } - tokens_bytes = tokens.map { _1[2]}.join.bytes - source_bytes = File.read("#{SRCDIR}/#{path}").bytes - - assert_equal(source_bytes, tokens_bytes) - - (tokens.count - 1).times do |i| - token_0 = tokens[i] - token_1 = tokens[i + 1] - end_pos = token_0.last[2..3] - beg_pos = token_1.last[0..1] - - if end_pos[0] == beg_pos[0] - # When both tokens are same line, column should be consecutives - assert_equal(beg_pos[1], end_pos[1], "#{token_0}. #{token_1}") - else - # Line should be next - assert_equal(beg_pos[0], end_pos[0] + 1, "#{token_0}. #{token_1}") - # It should be on the beginning of the line - assert_equal(0, beg_pos[1], "#{token_0}. #{token_1}") + class_eval <<-RUBY + def #{"test_all_tokens:#{path}".gsub(/[^\w]/, '_')} + node = RubyVM::AbstractSyntaxTree.parse_file("#{SRCDIR}/#{path}", keep_tokens: true) + tokens = node.all_tokens.sort_by { [_1.last[0], _1.last[1]] } + tokens_bytes = tokens.map { _1[2]}.join.bytes + source_bytes = File.read("#{SRCDIR}/#{path}").bytes + + assert_equal(source_bytes, tokens_bytes) + + (tokens.count - 1).times do |i| + token_0 = tokens[i] + token_1 = tokens[i + 1] + end_pos = token_0.last[2..3] + beg_pos = token_1.last[0..1] + + if end_pos[0] == beg_pos[0] + # When both tokens are same line, column should be consecutives + assert_equal(beg_pos[1], end_pos[1], "\#{token_0}. \#{token_1}") + else + # Line should be next + assert_equal(beg_pos[0], end_pos[0] + 1, "\#{token_0}. \#{token_1}") + # It should be on the beginning of the line + assert_equal(0, beg_pos[1], "\#{token_0}. \#{token_1}") + end end end - end + RUBY end private def parse(src) @@ -206,6 +210,7 @@ def test_parse_raises_syntax_error end def test_parse_file_raises_syntax_error + omit "Tempfile" unless main_ractor? Tempfile.create(%w"test_ast .rb") do |f| f.puts "end" f.close @@ -373,6 +378,7 @@ def test_node_id_for_backtrace_location_raises_argument_error def test_of_proc_and_method omit if ParserSupport.prism_enabled? || ParserSupport.prism_enabled_in_subprocess? + omit "Tempfile" unless main_ractor? proc = Proc.new { 1 + 2 } method = self.method(__method__) diff --git a/test/ruby/test_autoload.rb b/test/ruby/test_autoload.rb index 607f0e3355efe9..f5a208caf155f7 100644 --- a/test/ruby/test_autoload.rb +++ b/test/ruby/test_autoload.rb @@ -3,6 +3,10 @@ require 'tempfile' class TestAutoload < Test::Unit::TestCase + def setup + pend "autoload" unless main_ractor? + end + def test_autoload_so # Date is always available, unless excluded intentionally. assert_in_out_err([], <<-INPUT, [], []) @@ -66,6 +70,7 @@ def test_autoload_p end def test_autoload_p_with_static_extensions + pend "belonging issue" unless main_ractor? require 'rbconfig' omit unless RbConfig::CONFIG['EXTSTATIC'] == 'static' begin @@ -84,6 +89,7 @@ def test_autoload_p_with_static_extensions end def test_autoload_with_unqualified_file_name # [ruby-core:69206] + omit "global variable access" unless main_ractor? Object.send(:remove_const, :A) if Object.const_defined?(:A) lp = $LOAD_PATH.dup @@ -106,12 +112,13 @@ module A end } ensure - $LOAD_PATH.replace lp - $LOADED_FEATURES.replace lf + $LOAD_PATH.replace lp if lp + $LOADED_FEATURES.replace lf if lf Object.send(:remove_const, :A) if Object.const_defined?(:A) end def test_require_explicit + pend "Tempfile" unless main_ractor? Tempfile.create(['autoload', '.rb']) {|file| file.puts 'class Object; AutoloadTest = 1; end' file.close @@ -128,6 +135,7 @@ def test_require_explicit end def test_threaded_accessing_constant + pend "Tempfile" unless main_ractor? # Suppress "warning: loading in progress, circular require considered harmful" EnvUtil.default_warning { Tempfile.create(['autoload', '.rb']) {|file| @@ -148,6 +156,7 @@ def test_threaded_accessing_constant end def test_threaded_accessing_inner_constant + pend "Tempfile" unless main_ractor? # Suppress "warning: loading in progress, circular require considered harmful" EnvUtil.default_warning { Tempfile.create(['autoload', '.rb']) {|file| @@ -168,6 +177,7 @@ def test_threaded_accessing_inner_constant end def test_nameerror_when_autoload_did_not_define_the_constant + pend "Tempfile" unless main_ractor? verbose_bak, $VERBOSE = $VERBOSE, nil Tempfile.create(['autoload', '.rb']) {|file| file.puts '' @@ -186,6 +196,7 @@ def test_nameerror_when_autoload_did_not_define_the_constant end def test_override_autoload + pend "Tempfile" unless main_ractor? Tempfile.create(['autoload', '.rb']) {|file| file.puts '' file.close @@ -200,6 +211,7 @@ def test_override_autoload end def test_override_while_autoloading + pend "Tempfile" unless main_ractor? Tempfile.create(['autoload', '.rb']) {|file| file.puts 'class AutoloadTest; sleep 0.5; end' file.close @@ -251,6 +263,7 @@ def ruby_impl_require end def test_require_implemented_in_ruby_is_called + pend "Tempfile" unless main_ractor? ruby_impl_require do |called_with| Tempfile.create(['autoload', '.rb']) {|file| file.puts 'class AutoloadTest; end' @@ -268,6 +281,7 @@ def test_require_implemented_in_ruby_is_called end def test_autoload_while_autoloading + pend "Tempfile" unless main_ractor? ruby_impl_require do |called_with| Tempfile.create(%w(a .rb)) do |a| Tempfile.create(%w(b .rb)) do |b| @@ -397,6 +411,7 @@ class AutoloadTest end def test_autoload_fork + pend "Tempfile" unless main_ractor? EnvUtil.default_warning do Tempfile.create(['autoload', '.rb']) {|file| file.puts 'sleep 0.3; class AutoloadTest; end' diff --git a/test/ruby/test_backtrace.rb b/test/ruby/test_backtrace.rb index dad7dfcb558471..db5c7e6591f297 100644 --- a/test/ruby/test_backtrace.rb +++ b/test/ruby/test_backtrace.rb @@ -258,6 +258,7 @@ def test_caller_locations_to_s_inspect end def test_caller_locations_path + omit "Tempfile" unless main_ractor? loc, = caller_locations(0, 1) assert_equal(__FILE__, loc.path) Tempfile.create(%w"caller_locations .rb") do |f| @@ -269,6 +270,7 @@ def test_caller_locations_path end def test_caller_locations_absolute_path + omit "Tempfile" unless main_ractor? loc, = caller_locations(0, 1) assert_equal(__FILE__, loc.absolute_path) Tempfile.create(%w"caller_locations .rb") do |f| @@ -279,6 +281,7 @@ def test_caller_locations_absolute_path end def test_caller_locations_lineno + omit "Tempfile" unless main_ractor? loc, = caller_locations(0, 1) assert_equal(__LINE__-1, loc.lineno) Tempfile.create(%w"caller_locations .rb") do |f| diff --git a/test/ruby/test_basicinstructions.rb b/test/ruby/test_basicinstructions.rb index f6b69cc1e57e58..6acf200a4dbf16 100644 --- a/test/ruby/test_basicinstructions.rb +++ b/test/ruby/test_basicinstructions.rb @@ -9,6 +9,10 @@ class Class class TestBasicInstructions < Test::Unit::TestCase + def setup + omit "Lots of unfrozen strings in constants" if non_main_ractor? + end + def test_immediates assert_equal((1==1), true) assert_equal((1==2), false) diff --git a/test/ruby/test_beginendblock.rb b/test/ruby/test_beginendblock.rb index 3706efab52dd0b..d2fa95af08b274 100644 --- a/test/ruby/test_beginendblock.rb +++ b/test/ruby/test_beginendblock.rb @@ -3,7 +3,7 @@ EnvUtil.suppress_warning {require 'continuation'} class TestBeginEndBlock < Test::Unit::TestCase - DIR = File.dirname(File.expand_path(__FILE__)) + DIR = File.dirname(File.expand_path(__FILE__)).freeze def test_beginendblock target = File.join(DIR, 'beginmainend.rb') @@ -73,6 +73,7 @@ def test_exitcode_in_at_exit end def test_propagate_exit_code + omit "TODO: look into this. Getting unexpected values but can't reproduce it in non-test environment" ruby = EnvUtil.rubybin assert_equal false, system(ruby, '-e', 'at_exit{exit 2}') assert_equal 2, $?.exitstatus @@ -119,6 +120,7 @@ def test_nested_at_exit end def test_rescue_at_exit + omit "subprocess" unless main_ractor? bug5218 = '[ruby-core:43173][Bug #5218]' cmd = [ "raise 'X' rescue nil", @@ -165,12 +167,13 @@ def test_errinfo_at_exit if defined?(fork) def test_internal_errinfo_at_exit + omit "at_exit handlers cannot use ractor-local objects" if non_main_ractor? # TODO: use other than break-in-fork to throw an internal # error info. error, pid, status = IO.pipe do |r, w| pid = fork do r.close - STDERR.reopen(w) + $stderr.reopen(w) at_exit do $!.class end diff --git a/test/ruby/test_bignum.rb b/test/ruby/test_bignum.rb index dd6f4baa4c292b..3807a83f1c303e 100644 --- a/test/ruby/test_bignum.rb +++ b/test/ruby/test_bignum.rb @@ -70,17 +70,18 @@ def test_prepare end def test_bignum - $x = fact(40) - assert_equal($x, $x) - assert_equal($x, fact(40)) - assert_operator($x, :<, $x+2) - assert_operator($x, :>, $x-2) - assert_equal(815915283247897734345611269596115894272000000000, $x) - assert_not_equal(815915283247897734345611269596115894272000000001, $x) - assert_equal(815915283247897734345611269596115894272000000001, $x+1) - assert_equal(335367096786357081410764800000, $x/fact(20)) - $x = -$x - assert_equal(-815915283247897734345611269596115894272000000000, $x) + omit "global var access" if non_main_ractor? + x = fact(40) + assert_equal(x, x) + assert_equal(x, fact(40)) + assert_operator(x, :<, x+2) + assert_operator(x, :>, x-2) + assert_equal(815915283247897734345611269596115894272000000000, x) + assert_not_equal(815915283247897734345611269596115894272000000001, x) + assert_equal(815915283247897734345611269596115894272000000001, x+1) + assert_equal(335367096786357081410764800000, x/fact(20)) + x = -x + assert_equal(-815915283247897734345611269596115894272000000000, x) b = 2*BIGNUM_MIN assert_equal(2-b, -(b-2)) @@ -705,6 +706,7 @@ def test_interrupt_during_bigdivrem return # GMP doesn't support interrupt during an operation. end return unless Process.respond_to?(:kill) + omit "Signal.trap lambda accesses outers" if non_main_ractor? begin trace = [] oldtrap = Signal.trap(:INT) {|sig| trace << :int } diff --git a/test/ruby/test_class.rb b/test/ruby/test_class.rb index 9a34a81334f5ba..57a5075e55120c 100644 --- a/test/ruby/test_class.rb +++ b/test/ruby/test_class.rb @@ -38,6 +38,7 @@ class ClassFour < ClassThree # ------------------ def test_s_inherited + pend "accesses class variables" if non_main_ractor? assert_equal([ClassTwo, ClassThree, ClassFour], ClassOne.new.subs) end @@ -243,9 +244,11 @@ def test_check_inheritable assert_raise(TypeError) { Class.new(c) } assert_raise(TypeError) { Class.new(Class) } assert_raise(TypeError) { eval("class Foo < Class; end") } - m = "M\u{1f5ff}" - o = Class.new {break eval("class #{m}; self; end.new")} - assert_raise_with_message(TypeError, /#{m}/) {Class.new(o)} + if main_ractor? + m = "M\u{1f5ff}" + o = Class.new {break eval("class #{m}; self; end.new")} + assert_raise_with_message(TypeError, /#{m}/) {Class.new(o)} + end end def test_initialize_copy @@ -288,6 +291,7 @@ def test_uninitialized end def test_nonascii_name + omit "global side effects" if multiple_ractors? c = eval("class ::C\u{df}; self; end") assert_equal("C\u{df}", c.name, '[ruby-core:24600]') c = eval("class C\u{df}; self; end") @@ -465,20 +469,26 @@ class C < c } end - define_method :test_invalid_reset_superclass do - class A; end - class SuperclassCannotBeReset < A - end + def test_invalid_reset_superclass + self.class.class_eval <<-RUBY + class A; end + class SuperclassCannotBeReset < A + end + RUBY assert_equal A, SuperclassCannotBeReset.superclass assert_raise_with_message(TypeError, /superclass mismatch/) { - class SuperclassCannotBeReset < String - end + self.class.class_eval <<-RUBY + class SuperclassCannotBeReset < String + end + RUBY } assert_raise_with_message(TypeError, /superclass mismatch/, "[ruby-core:75446]") { - class SuperclassCannotBeReset < Object - end + self.class.class_eval <<-RUBY + class SuperclassCannotBeReset < Object + end + RUBY } assert_equal A, SuperclassCannotBeReset.superclass @@ -574,6 +584,7 @@ def c.f; end end def test_singleton_class_should_has_own_namespace + pend "Accesses global" if non_main_ractor? # CONST in singleton class objs = [] $i = 0 @@ -696,9 +707,11 @@ def xyzzy def test_namescope_error_message m = Module.new o = m.module_eval "class A\u{3042}; self; end.new" - assert_raise_with_message(TypeError, /A\u{3042}/) { - o::Foo - } + EnvUtil.with_default_internal(Encoding::UTF_8) do + assert_raise_with_message(TypeError, /A\u{3042}/) { + o::Foo + } + end end def test_redefinition_mismatch @@ -763,7 +776,11 @@ def test_subclasses ssc = Class.new(sc) [c, sc, ssc].each do |k| k.include Module.new - k.new.define_singleton_method(:force_singleton_class){} + k.new.define_singleton_method(:force_singleton_class, &Ractor.make_shareable( + nil.instance_eval do + proc { } + end + )) end assert_equal([sc], c.subclasses) assert_equal([ssc], sc.subclasses) diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index b95add5bd45fe4..e643cecaa42374 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -3,6 +3,10 @@ # This file is organized to match itemization in https://github.com/ruby/prism/issues/1335 module Prism class TestCompilePrism < Test::Unit::TestCase + def setup + omit "Not ractor safe" if multiple_ractors? + end + def test_iseq_has_node_id code = "proc { < 1 @@ -1848,8 +1880,10 @@ def test_PreExecutionNode def test_PostExecutionNode assert_prism_eval("END { 1 }") - assert_prism_eval("END { @b }; @b = 1") - assert_prism_eval("END { @b; 0 }; @b = 1") + if main_ractor? + assert_prism_eval("END { @b }; @b = 1") + assert_prism_eval("END { @b; 0 }; @b = 1") + end assert_prism_eval("foo = 1; END { foo.nil? }") assert_prism_eval("foo = 1; END { END { foo.nil? }}") end @@ -2270,6 +2304,7 @@ def test_SuperNode ############################################################################ def test_AliasGlobalVariableNode + omit "global variable access" if non_main_ractor? assert_prism_eval("alias $prism_foo $prism_bar") end @@ -2612,9 +2647,11 @@ def test_PinnedExpressionNode end def test_PinnedVariableNode - assert_prism_eval("module Prism; @@prism = 1; 1 in ^@@prism; end") - assert_prism_eval("module Prism; @prism = 1; 1 in ^@prism; end") - assert_prism_eval("$prism = 1; 1 in ^$prism") + if main_ractor? + assert_prism_eval("module Prism; @@prism = 1; 1 in ^@@prism; end") + assert_prism_eval("module Prism; @prism = 1; 1 in ^@prism; end") + assert_prism_eval("$prism = 1; 1 in ^$prism") + end assert_prism_eval("prism = 1; 1 in ^prism") assert_prism_eval("[1].each { 1 => ^it }") end diff --git a/test/ruby/test_condition.rb b/test/ruby/test_condition.rb index ab0ffc4b6a2559..a6b955fe592340 100644 --- a/test/ruby/test_condition.rb +++ b/test/ruby/test_condition.rb @@ -6,12 +6,12 @@ class TestCondition < Test::Unit::TestCase # [should] first test to see if we can run the tests. def test_condition - $x = '0'; + x = '0'; - $x == $x && assert(true) - $x != $x && assert(false) - $x == $x || assert(false) - $x != $x || assert(true) + x == x && assert(true) + x != x && assert(false) + x == x || assert(false) + x != x || assert(true) end end diff --git a/test/ruby/test_const.rb b/test/ruby/test_const.rb index f6b9ea83d3c02d..f07ffa44455496 100644 --- a/test/ruby/test_const.rb +++ b/test/ruby/test_const.rb @@ -25,6 +25,7 @@ module Const2 end def test_const + omit "not ractor safe" if non_main_ractor? Constants_Setup.call assert defined?(TEST1) diff --git a/test/ruby/test_default_gems.rb b/test/ruby/test_default_gems.rb index b82e304cbdb1c6..d21c8b9c597cda 100644 --- a/test/ruby/test_default_gems.rb +++ b/test/ruby/test_default_gems.rb @@ -15,6 +15,7 @@ def self.load(file) end def test_validate_gemspec + omit "loading gemspecs accesses load path" if non_main_ractor? srcdir = File.expand_path('../../..', __FILE__) specs = 0 Dir.chdir(srcdir) do diff --git a/test/ruby/test_defined.rb b/test/ruby/test_defined.rb index db1fdc8e25a3c5..a7e02fb2b7c0bf 100644 --- a/test/ruby/test_defined.rb +++ b/test/ruby/test_defined.rb @@ -24,6 +24,7 @@ def defined_test end def test_defined_global_variable + omit "global var" if non_main_ractor? $x = nil assert(defined?($x)) # global variable @@ -302,6 +303,7 @@ def b? end def test_autoloaded_noload + omit "accesses load path" if non_main_ractor? loaded = $".dup $".clear loadpath = $:.dup @@ -311,8 +313,8 @@ def test_autoloaded_noload assert_nil(x.b?) assert_equal([], $") ensure - $".replace(loaded) - $:.replace(loadpath) + $".replace(loaded) if loaded + $:.replace(loadpath) if loadpath end def test_exception @@ -371,6 +373,8 @@ def x; b {return defined?(super)}; end end def test_super_in_basic_object + omit "global side effects" if multiple_ractors? + run_ensure = true BasicObject.class_eval do def a defined?(super) @@ -381,7 +385,7 @@ def a ensure BasicObject.class_eval do undef_method :a if defined?(a) - end + end if run_ensure end def test_super_toplevel @@ -389,6 +393,7 @@ def test_super_toplevel end def test_respond_to + omit "Warning[]= used" if multiple_ractors? obj = "#{self.class.name}##{__method__}" class << obj def respond_to?(mid) diff --git a/test/ruby/test_dir.rb b/test/ruby/test_dir.rb index edb5210af16313..5ab46ae1c6d16d 100644 --- a/test/ruby/test_dir.rb +++ b/test/ruby/test_dir.rb @@ -7,6 +7,7 @@ class TestDir < Test::Unit::TestCase def setup + omit "lots of Dir.chdir" if multiple_ractors? @verbose = $VERBOSE @root = File.realpath(Dir.mktmpdir('__test_dir__')) @nodir = File.join(@root, "dummy") @@ -23,6 +24,7 @@ def setup end def teardown + return if multiple_ractors? $VERBOSE = @verbose FileUtils.remove_entry_secure @root if File.directory?(@root) ENV.update(@envs) if @envs @@ -97,6 +99,7 @@ def test_rewind end def test_class_chdir + omit "Dir.chdir" unless main_ractor? pwd = Dir.pwd setup_envs @@ -129,13 +132,14 @@ def test_class_chdir ensure begin - Dir.chdir(pwd) + Dir.chdir(pwd) if pwd rescue abort("cannot return the original directory: #{ pwd }") end end def test_instance_chdir + omit "Dir.chdir" unless main_ractor? pwd = Dir.pwd dir = Dir.new(pwd) root_dir = Dir.new(@root) @@ -194,15 +198,16 @@ def Warning.warn(message) assert_equal(42, ret) ensure begin - assert_equal(0, dir.chdir) + assert_equal(0, dir.chdir) if dir rescue abort("cannot return the original directory: #{ pwd }") end - dir.close - root_dir.close + dir&.close + root_dir&.close end def test_chdir_conflict + omit "Dir.chdir" unless main_ractor? pwd = Dir.pwd q = Thread::Queue.new t = Thread.new do @@ -279,6 +284,7 @@ def test_glob end def test_glob_recursive + omit "Dir.chdir" unless main_ractor? bug6977 = '[ruby-core:47418]' bug8006 = '[ruby-core:53108] [Bug #8006]' Dir.chdir(@root) do @@ -308,6 +314,7 @@ def test_glob_recursive end def test_glob_recursive_directory + omit "Dir.chdir" unless main_ractor? Dir.chdir(@root) do ['d', 'e'].each do |path| FileUtils.mkdir_p("c/#{path}/a/b/c") @@ -325,6 +332,7 @@ def test_glob_recursive_directory end def test_glob_starts_with_brace + omit "Dir.chdir" unless main_ractor? Dir.chdir(@root) do bug15649 = '[ruby-core:91728] [Bug #15649]' assert_equal(["#{@root}/a", "#{@root}/b"], @@ -333,6 +341,7 @@ def test_glob_starts_with_brace end def test_glob_recursive_with_brace + omit "Dir.chdir" unless main_ractor? Dir.chdir(@root) do bug19042 = '[ruby-core:110220] [Bug #19042]' %w"c/dir_a c/dir_b c/dir_b/dir".each do |d| @@ -347,6 +356,7 @@ def test_glob_recursive_with_brace end def test_glob_order + omit "Dir.chdir" unless main_ractor? Dir.chdir(@root) do assert_equal(["#{@root}/a", "#{@root}/b"], Dir.glob("#{@root}/[ba]")) assert_equal(["#{@root}/b", "#{@root}/a"], Dir.glob(%W"#{@root}/b #{@root}/a")) @@ -376,6 +386,7 @@ def test_glob_too_may_open_files end def test_glob_base + omit "Dir.chdir" unless main_ractor? files = %w[a/foo.c c/bar.c] files.each {|n| File.write(File.join(@root, n), "")} Dir.mkdir(File.join(@root, "a/dir")) @@ -416,6 +427,7 @@ def test_glob_base end def test_glob_base_dir + omit "Dir.chdir" unless main_ractor? files = %w[a/foo.c c/bar.c] files.each {|n| File.write(File.join(@root, n), "")} Dir.mkdir(File.join(@root, "a/dir")) @@ -438,6 +450,7 @@ def test_glob_base_dir end def test_glob_ignore_casefold_invalid_encoding + omit "Dir.chdir" unless main_ractor? bug14456 = "[ruby-core:85448]" filename = "\u00AAa123".encode('ISO-8859-1') File.write(File.join(@root, filename), "") @@ -555,6 +568,7 @@ def test_glob_metachar end def test_glob_cases + omit "Dir.chdir" unless main_ractor? feature5994 = "[ruby-core:42469] [Feature #5994]" feature5994 << "\nDir.glob should return the filename with actual cases on the filesystem" Dir.chdir(File.join(@root, "a")) do @@ -659,6 +673,7 @@ def test_children_long_name end def test_home + omit "not ractor safe" unless main_ractor? setup_envs ENV["HOME"] = @nodir @@ -690,6 +705,7 @@ def test_home_utf8 end def test_symlinks_not_resolved + omit "not ractors safe (Dir.chdir)" unless main_ractor? Dir.mktmpdir do |dirname| Dir.chdir(dirname) do begin @@ -718,6 +734,7 @@ def test_fileno end def test_for_fd + omit "Dir.chdir" unless main_ractor? if Dir.respond_to? :for_fd begin new_dir = Dir.new('..') diff --git a/test/ruby/test_dir_m17n.rb b/test/ruby/test_dir_m17n.rb index cdf8b44ef2705c..591e941e3a8a10 100644 --- a/test/ruby/test_dir_m17n.rb +++ b/test/ruby/test_dir_m17n.rb @@ -4,6 +4,10 @@ require '-test-/file' class TestDir_M17N < Test::Unit::TestCase + def setup + omit "Uses Dir.chdir" if multiple_ractors? + end + def with_tmpdir Dir.mktmpdir {|dir| Dir.chdir(dir) { @@ -395,6 +399,7 @@ def PP.mu_pp(ary) #:nodoc: end def test_entries_compose + omit "accesses non-shareable object PP" if non_main_ractor? bug7267 = '[ruby-core:48745] [Bug #7267]' with_tmpdir {|d| @@ -410,6 +415,7 @@ def test_entries_compose end def test_pwd + omit "accesses non-shareable object PP" if non_main_ractor? orig = %W"d\u{e9}tente x\u{304c 304e 3050 3052 3054}" expected = [] results = [] diff --git a/test/ruby/test_enumerator.rb b/test/ruby/test_enumerator.rb index cd62cd8acb7746..f9c6da403c354c 100644 --- a/test/ruby/test_enumerator.rb +++ b/test/ruby/test_enumerator.rb @@ -129,6 +129,7 @@ def test_with_index def test_with_index_under_gc_compact_stress omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077 + omit "EnvUtil.under_gc_compact_stress" if multiple_ractors? EnvUtil.under_gc_compact_stress do assert_equal([[1, 0], [2, 1], [3, 2]], @obj.to_enum(:foo, 1, 2, 3).with_index.to_a) assert_equal([[1, 5], [2, 6], [3, 7]], @obj.to_enum(:foo, 1, 2, 3).with_index(5).to_a) @@ -865,6 +866,7 @@ def test_lazy_chain def test_lazy_chain_under_gc_compact_stress omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077 + omit "EnvUtil.under_gc_compact_stress" if multiple_ractors? EnvUtil.under_gc_compact_stress do ea = (10..).lazy.select(&:even?).take(10) ed = (20..).lazy.select(&:odd?) diff --git a/test/ruby/test_env.rb b/test/ruby/test_env.rb index 2727620c198522..d4252f06a6da04 100644 --- a/test/ruby/test_env.rb +++ b/test/ruby/test_env.rb @@ -5,12 +5,12 @@ class TestEnv < Test::Unit::TestCase windows = /bccwin|mswin|mingw/ =~ RUBY_PLATFORM IGNORE_CASE = windows ENCODING = windows ? Encoding::UTF_8 : Encoding.find("locale") - PATH_ENV = "PATH" + PATH_ENV = "PATH".freeze INVALID_ENVVARS = [ - "foo\0bar", - "\xa1\xa1".force_encoding(Encoding::UTF_16LE), - "foo".force_encoding(Encoding::ISO_2022_JP), - ] + "foo\0bar".freeze, + "\xa1\xa1".force_encoding(Encoding::UTF_16LE).freeze, + "foo".force_encoding(Encoding::ISO_2022_JP).freeze, + ].freeze def assert_invalid_env(msg = nil) all_assertions(msg) do |a| @@ -23,6 +23,7 @@ def assert_invalid_env(msg = nil) end def setup + omit "unpredictable results" if multiple_ractors? @verbose = $VERBOSE @backup = ENV.to_hash ENV.delete('test') @@ -30,9 +31,11 @@ def setup end def teardown - $VERBOSE = @verbose - ENV.clear - @backup.each {|k, v| ENV[k] = v } + if @verbose + $VERBOSE = @verbose + ENV.clear + @backup.each {|k, v| ENV[k] = v } + end end def test_bracket @@ -645,7 +648,7 @@ def check(as, bs) end assert_equal(as.sort, bs.sort) end - } + }.freeze def test_bracket_in_ractor assert_ractor(<<-"end;") diff --git a/test/ruby/test_eval.rb b/test/ruby/test_eval.rb index d2145bec5d9f13..aadd2968fa7232 100644 --- a/test/ruby/test_eval.rb +++ b/test/ruby/test_eval.rb @@ -28,8 +28,10 @@ def test_eval_basic assert_equal 11, eval("11") @ivar = 12 assert_equal 12, eval("@ivar") - assert_equal 13, eval("@@cvar") - assert_equal 14, eval("$gvar__eval") + if main_ractor? + assert_equal 13, eval("@@cvar") + assert_equal 14, eval("$gvar__eval") + end assert_equal 15, eval("Const") assert_equal 16, eval("7 + 9") @@ -39,8 +41,10 @@ def test_eval_basic 1.times { assert_equal 12, eval("@ivar") - assert_equal 13, eval("@@cvar") - assert_equal 14, eval("$gvar__eval") + if main_ractor? + assert_equal 13, eval("@@cvar") + assert_equal 14, eval("$gvar__eval") + end assert_equal 15, eval("Const") } end @@ -56,8 +60,10 @@ def test_eval_binding_basic assert_equal 11, eval("11", binding()) @ivar = 12 assert_equal 12, eval("@ivar", binding()) - assert_equal 13, eval("@@cvar", binding()) - assert_equal 14, eval("$gvar__eval", binding()) + if main_ractor? + assert_equal 13, eval("@@cvar", binding()) + assert_equal 14, eval("$gvar__eval", binding()) + end assert_equal 15, eval("Const", binding()) assert_equal 16, eval("7 + 9", binding()) @@ -67,8 +73,10 @@ def test_eval_binding_basic 1.times { assert_equal 12, eval("@ivar") - assert_equal 13, eval("@@cvar") - assert_equal 14, eval("$gvar__eval") + if main_ractor? + assert_equal 13, eval("@@cvar") + assert_equal 14, eval("$gvar__eval") + end assert_equal 15, eval("Const") } end @@ -83,8 +91,10 @@ def test_module_eval_string_basic assert_equal 11, c.module_eval("11") @ivar = 12 assert_equal 12, c.module_eval("@ivar") - assert_equal 13, c.module_eval("@@cvar") - assert_equal 14, c.module_eval("$gvar__eval") + if main_ractor? + assert_equal 13, c.module_eval("@@cvar") + assert_equal 14, c.module_eval("$gvar__eval") + end assert_equal 15, c.module_eval("Const") assert_equal 16, c.module_eval("7 + 9") assert_equal 17, c.module_eval("17.to_i") @@ -94,8 +104,10 @@ def test_module_eval_string_basic @ivar = 12 1.times { assert_equal 12, c.module_eval("@ivar") - assert_equal 13, c.module_eval("@@cvar") - assert_equal 14, c.module_eval("$gvar__eval") + if main_ractor? + assert_equal 13, c.module_eval("@@cvar") + assert_equal 14, c.module_eval("$gvar__eval") + end assert_equal 15, c.module_eval("Const") } end @@ -110,8 +122,10 @@ def test_module_eval_block_basic assert_equal 11, c.module_eval { 11 } @ivar = 12 assert_equal 12, c.module_eval { @ivar } - assert_equal 13, c.module_eval { @@cvar } - assert_equal 14, c.module_eval { $gvar__eval } + if main_ractor? + assert_equal 13, c.module_eval { @@cvar } + assert_equal 14, c.module_eval { $gvar__eval } + end assert_equal 15, c.module_eval { Const } assert_equal 16, c.module_eval { 7 + 9 } assert_equal 17, c.module_eval { "17".to_i } @@ -121,8 +135,10 @@ def test_module_eval_block_basic @ivar = 12 1.times { assert_equal 12, c.module_eval { @ivar } - assert_equal 13, c.module_eval { @@cvar } - assert_equal 14, c.module_eval { $gvar__eval } + if main_ractor? + assert_equal 13, c.module_eval { @@cvar } + assert_equal 14, c.module_eval { $gvar__eval } + end assert_equal 15, c.module_eval { Const } } end @@ -150,8 +166,10 @@ def test_instance_eval_string_basic assert_equal 11, o.instance_eval("11") assert_equal 12, o.instance_eval("@ivar") unless o.frozen? - assert_equal 13, o.instance_eval("@@cvar") - assert_equal 14, o.instance_eval("$gvar__eval") + if main_ractor? + assert_equal 13, o.instance_eval("@@cvar") + assert_equal 14, o.instance_eval("$gvar__eval") + end assert_equal 15, o.instance_eval("Const") assert_equal 16, o.instance_eval("7 + 9") assert_equal 17, o.instance_eval("17.to_i") @@ -160,8 +178,10 @@ def test_instance_eval_string_basic 1.times { assert_equal 12, o.instance_eval("@ivar") unless o.frozen? - assert_equal 13, o.instance_eval("@@cvar") - assert_equal 14, o.instance_eval("$gvar__eval") + if main_ractor? + assert_equal 13, o.instance_eval("@@cvar") + assert_equal 14, o.instance_eval("$gvar__eval") + end assert_equal 15, o.instance_eval("Const") } end @@ -178,8 +198,10 @@ def test_instance_eval_block_basic assert_equal 11, o.instance_eval { 11 } assert_equal 12, o.instance_eval { @ivar } unless o.frozen? - assert_equal 13, o.instance_eval { @@cvar } - assert_equal 14, o.instance_eval { $gvar__eval } + if main_ractor? + assert_equal 13, o.instance_eval { @@cvar } + assert_equal 14, o.instance_eval { $gvar__eval } + end assert_equal 15, o.instance_eval { Const } assert_equal 16, o.instance_eval { 7 + 9 } assert_equal 17, o.instance_eval { 17.to_i } @@ -188,8 +210,10 @@ def test_instance_eval_block_basic 1.times { assert_equal 12, o.instance_eval { @ivar } unless o.frozen? - assert_equal 13, o.instance_eval { @@cvar } - assert_equal 14, o.instance_eval { $gvar__eval } + if main_ractor? + assert_equal 13, o.instance_eval { @@cvar } + assert_equal 14, o.instance_eval { $gvar__eval } + end assert_equal 15, o.instance_eval { Const } } end @@ -211,6 +235,7 @@ def test_instance_eval_block_symbol end def test_instance_eval_cvar + omit "class variable access" if non_main_ractor? [Object.new, [], 7, :sym, true, false, nil].each do |obj| assert_equal(13, obj.instance_eval("@@cvar")) assert_equal(13, obj.instance_eval{@@cvar}) @@ -220,6 +245,7 @@ def test_instance_eval_cvar end def test_instance_exec_cvar + omit "class variable access" if non_main_ractor? [Object.new, [], 7, :sym, true, false, nil].each do |obj| assert_equal(13, obj.instance_exec{@@cvar}) end @@ -241,6 +267,7 @@ class << o end def test_instance_eval_on_argf_singleton_class + omit "ARGF access" if non_main_ractor? bug8188 = '[ruby-core:53839] [Bug #8188]' assert_warning('', bug8188) do ARGF.singleton_class.instance_eval{} @@ -270,8 +297,10 @@ def test_instance_exec_block_basic assert_equal 11, o.instance_exec { 11 } assert_equal 12, o.instance_exec { @ivar } unless o.frozen? - assert_equal 13, o.instance_exec { @@cvar } - assert_equal 14, o.instance_exec { $gvar__eval } + if main_ractor? + assert_equal 13, o.instance_exec { @@cvar } + assert_equal 14, o.instance_exec { $gvar__eval } + end assert_equal 15, o.instance_exec { Const } assert_equal 16, o.instance_exec { 7 + 9 } assert_equal 17, o.instance_exec { 17.to_i } @@ -280,8 +309,10 @@ def test_instance_exec_block_basic 1.times { assert_equal 12, o.instance_exec { @ivar } unless o.frozen? - assert_equal 13, o.instance_exec { @@cvar } - assert_equal 14, o.instance_exec { $gvar__eval } + if main_ractor? + assert_equal 13, o.instance_exec { @@cvar } + assert_equal 14, o.instance_exec { $gvar__eval } + end assert_equal 15, o.instance_exec { Const } } end @@ -346,14 +377,16 @@ def test_eval_orig assert(!eval('nil')) assert(!eval('false')) - $foo = 'assert(true)' - begin - eval $foo - rescue - assert(false) + if main_ractor? + $foo = 'assert(true)' + begin + eval $foo + rescue + assert(false) + end + assert_equal('assert(true)', eval("$foo")) end - assert_equal('assert(true)', eval("$foo")) assert_equal(true, eval("true")) i = i = 5 assert(eval("i == 5")) @@ -371,24 +404,26 @@ def test_eval_orig end assert(!bad) - # !! use class_eval to avoid nested definition - x = self.class.class_eval %q( - module EvTest - EVTEST1 = 25 - evtest2 = 125 - evtest2 = evtest2 - binding + unless multiple_ractors? + # !! use class_eval to avoid nested definition + x = self.class.class_eval %q( + module EvTest + EVTEST1 = 25 + evtest2 = 125 + evtest2 = evtest2 + binding + end + ) + assert_equal(25, eval("EVTEST1", x)) # constant in module + assert_equal(125, eval("evtest2", x)) # local var in module + bad = true + begin + eval("EVTEST1") + rescue NameError # must raise error + bad = false end - ) - assert_equal(25, eval("EVTEST1", x)) # constant in module - assert_equal(125, eval("evtest2", x)) # local var in module - bad = true - begin - eval("EVTEST1") - rescue NameError # must raise error - bad = false + assert(!bad) end - assert(!bad) x = binding eval "i = 1", x @@ -420,10 +455,11 @@ module EvTest self.class.class_eval do remove_const :EvTest - end + end unless multiple_ractors? end def test_nil_instance_eval_cvar + omit "class variable access" if non_main_ractor? def nil.test_binding binding end @@ -435,10 +471,12 @@ class << nil end def test_fixnum_instance_eval_cvar + omit "class variable access" if non_main_ractor? assert_raise(NameError, "[ruby-dev:24213]") { 1.instance_eval "@@a" } end def test_cvar_scope_with_instance_eval + omit "class variable read/write" if non_main_ractor? # TODO: check Integer.class_eval "@@test_cvar_scope_with_instance_eval = 1" # depends on [ruby-dev:24229] @@test_cvar_scope_with_instance_eval = 4 @@ -473,6 +511,7 @@ def test_define_method_block end def test_define_method_toplevel + omit "access TOPLEVEL_BINDING" if non_main_ractor? feature6609 = '[ruby-core:45715]' main = eval("self", TOPLEVEL_BINDING) assert_nothing_raised(NoMethodError, feature6609) do @@ -502,6 +541,7 @@ def test_eval_raise end def test_eval_with_toplevel_binding # [ruby-dev:37142] + omit "subprocess" unless main_ractor? ruby("-e", "x = 0; eval('p x', TOPLEVEL_BINDING)") do |f| f.close_write assert_equal("0", f.read.chomp) diff --git a/test/ruby/test_exception.rb b/test/ruby/test_exception.rb index 84581180b60958..4364eb62de298b 100644 --- a/test/ruby/test_exception.rb +++ b/test/ruby/test_exception.rb @@ -244,6 +244,7 @@ def test_uncaught_throw end def test_catch_throw_in_require + pend "Tempfile" bug7185 = '[ruby-dev:46234]' Tempfile.create(["dep", ".rb"]) {|t| t.puts("throw :extdep, 42") @@ -253,6 +254,7 @@ def test_catch_throw_in_require end def test_catch_throw_in_require_cant_be_rescued + pend "Tempfile" bug18562 = '[ruby-core:107403]' Tempfile.create(["dep", ".rb"]) {|t| t.puts("throw :extdep, 42") @@ -392,6 +394,7 @@ def test_raise_with_wrong_number_of_arguments end def test_type_error_message_encoding + omit "global side effects" if multiple_ractors? c = eval("Module.new do break class C\u{4032}; self; end; end") o = c.new assert_raise_with_message(TypeError, /C\u{4032}/) do @@ -444,6 +447,7 @@ def test_errat end def test_thread_signal_location + omit "subprocess" unless main_ractor? # pend('TODO: a known bug [Bug #14474]') _, stderr, _ = EnvUtil.invoke_ruby(%w"--disable-gems -d", <<-RUBY, false, true) Thread.start do @@ -559,6 +563,7 @@ def test_errno_constants end def test_too_many_args_in_eval + omit "TODO: freezes process" if multiple_ractors? bug5720 = '[ruby-core:41520]' arg_string = (0...140000).to_a.join(", ") assert_raise(SystemStackError, bug5720) {eval "raise(#{arg_string})"} @@ -665,7 +670,7 @@ def test_backtrace_by_exception assert_equal([__FILE__, line], [loc.path, loc.lineno]) end - Bug4438 = '[ruby-core:35364]' + Bug4438 = '[ruby-core:35364]'.freeze def test_rescue_single_argument assert_raise(TypeError, Bug4438) do @@ -1063,6 +1068,7 @@ def test_message_of_name_error end def capture_warning_warn(category: false) + omit "global side effects" if multiple_ractors? verbose = $VERBOSE categories = Warning.categories.to_h {|cat| [cat, Warning[cat]]} warning = [] @@ -1088,17 +1094,20 @@ def capture_warning_warn(category: false) return warning ensure - $VERBOSE = verbose - categories.each {|cat, flag| Warning[cat] = flag} - - ::Warning.class_eval do - remove_method :warn - alias_method :warn, :warn2 - remove_method :warn2 + if verbose + $VERBOSE = verbose + categories.each {|cat, flag| Warning[cat] = flag} + + ::Warning.class_eval do + remove_method :warn + alias_method :warn, :warn2 + remove_method :warn2 + end end end def test_warning_warn + omit "global variable access" if non_main_ractor? warning = capture_warning_warn {$asdfasdsda_test_warning_warn} assert_match(/global variable '\$asdfasdsda_test_warning_warn' not initialized/, warning[0]) @@ -1108,6 +1117,7 @@ def test_warning_warn end def test_warn_deprecated_backwards_compatibility_category + omit "accesses global variable" if non_main_ractor? (message, category), = capture_warning_warn(category: true) do $; = "www" $; = nil @@ -1149,6 +1159,7 @@ def test_warning_warn_invalid_argument end def test_warning_warn_circular_require_backtrace + omit "accesses $LOAD_PATH and $LOADED_FEATURES" if non_main_ractor? warning = nil path = nil Tempfile.create(%w[circular .rb]) do |t| @@ -1184,6 +1195,7 @@ def warn(message) end def test_warning_category + omit "global side effects" if multiple_ractors? assert_raise(TypeError) {Warning[nil]} assert_raise(ArgumentError) {Warning[:XXXX]} @@ -1304,12 +1316,14 @@ def test_full_message test_method = "def foo; raise 'testerror'; end" - out1, err1, status1 = EnvUtil.invoke_ruby(['-e', "#{test_method}; begin; foo; rescue => e; puts e.full_message; end"], '', true, true) - assert_predicate(status1, :success?) - assert_empty(err1, "expected nothing wrote to $stdout by #full_message") + if main_ractor? + out1, err1, status1 = EnvUtil.invoke_ruby(['-e', "#{test_method}; begin; foo; rescue => e; puts e.full_message; end"], '', true, true) + assert_predicate(status1, :success?) + assert_empty(err1, "expected nothing wrote to $stdout by #full_message") - _, err2, status1 = EnvUtil.invoke_ruby(['-e', "#{test_method}; begin; foo; end"], '', true, true) - assert_equal(err2, out1) + _, err2, status1 = EnvUtil.invoke_ruby(['-e', "#{test_method}; begin; foo; end"], '', true, true) + assert_equal(err2, out1) + end e = RuntimeError.new("a\n") message = assert_nothing_raised(ArgumentError, proc {e.pretty_inspect}) do @@ -1442,6 +1456,7 @@ def test_detailed_message def test_detailed_message_under_gc_compact_stress omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077 + omit "gc_compact_stress" if multiple_ractors? EnvUtil.under_gc_compact_stress do e = RuntimeError.new("foo\nbar\nbaz") assert_equal("foo (RuntimeError)\nbar\nbaz", e.detailed_message) diff --git a/test/ruby/test_fiber.rb b/test/ruby/test_fiber.rb index b7d2b71c196c38..d265c192122dd5 100644 --- a/test/ruby/test_fiber.rb +++ b/test/ruby/test_fiber.rb @@ -395,6 +395,7 @@ def test_prohibit_resume_to_transferring_fiber def test_fork_from_fiber omit 'fork not supported' unless Process.respond_to?(:fork) + omit "maybe fork not supported unless main ractor" unless main_ractor? pid = nil bug5700 = '[ruby-core:41456]' assert_nothing_raised(bug5700) do diff --git a/test/ruby/test_file.rb b/test/ruby/test_file.rb index a3d6221c0f924b..ba87278050da50 100644 --- a/test/ruby/test_file.rb +++ b/test/ruby/test_file.rb @@ -5,7 +5,6 @@ require_relative 'ut_eof' class TestFile < Test::Unit::TestCase - # I don't know Ruby's spec about "unlink-before-close" exactly. # This test asserts current behaviour. def test_unlink_before_close @@ -41,6 +40,7 @@ def open_file(content) include TestEOF::Seek def test_empty_file_bom + pend "Tempfile" unless main_ractor? bug6487 = '[ruby-core:45203]' Tempfile.create(__method__.to_s) {|f| assert_file.exist?(f.path) @@ -50,6 +50,7 @@ def test_empty_file_bom end def assert_bom(bytes, name) + pend "Tempfile" unless main_ractor? bug6487 = '[ruby-core:45203]' Tempfile.create(name.to_s) {|f| @@ -91,6 +92,7 @@ def test_bom_32le end def test_truncate_wbuf + pend "Tempfile" unless main_ractor? Tempfile.create("test-truncate") {|f| f.print "abc" f.truncate(0) @@ -101,6 +103,7 @@ def test_truncate_wbuf end def test_truncate_rbuf + pend "Tempfile" unless main_ractor? Tempfile.create("test-truncate") {|f| f.puts "abc" f.puts "def" @@ -112,6 +115,7 @@ def test_truncate_rbuf end def test_truncate_beyond_eof + pend "Tempfile" unless main_ractor? Tempfile.create("test-truncate") {|f| f.print "abc" f.truncate 10 @@ -120,6 +124,7 @@ def test_truncate_beyond_eof end def test_truncate_size + pend "Tempfile" unless main_ractor? Tempfile.create("test-truncate") do |f| q1 = Thread::Queue.new q2 = Thread::Queue.new @@ -147,6 +152,7 @@ def test_truncate_size end def test_read_all_extended_file + pend "Tempfile" unless main_ractor? [{}, {:textmode=>true}, {:binmode=>true}].each do |mode| Tempfile.create("test-extended-file", **mode) {|f| assert_nil(f.getc) @@ -158,6 +164,7 @@ def test_read_all_extended_file end def test_gets_extended_file + pend "Tempfile" unless main_ractor? [{}, {:textmode=>true}, {:binmode=>true}].each do |mode| Tempfile.create("test-extended-file", **mode) {|f| assert_nil(f.getc) @@ -169,6 +176,7 @@ def test_gets_extended_file end def test_gets_para_extended_file + pend "Tempfile" unless main_ractor? [{}, {:textmode=>true}, {:binmode=>true}].each do |mode| Tempfile.create("test-extended-file", **mode) {|f| assert_nil(f.getc) @@ -193,6 +201,7 @@ def test_each_char_extended_file end def test_each_byte_extended_file + pend "Tempfile" unless main_ractor? [{}, {:textmode=>true}, {:binmode=>true}].each do |mode| Tempfile.create("test-extended-file", **mode) {|f| assert_nil(f.getc) @@ -217,6 +226,7 @@ def test_getc_extended_file end def test_getbyte_extended_file + pend "Tempfile" unless main_ractor? [{}, {:textmode=>true}, {:binmode=>true}].each do |mode| Tempfile.create("test-extended-file", **mode) {|f| assert_nil(f.getc) @@ -233,6 +243,7 @@ def test_s_chown end def test_chown + pend "Tempfile" unless main_ractor? Tempfile.create("test-chown") {|f| assert_nothing_raised {f.chown(-1, -1)} assert_nothing_raised("[ruby-dev:27140]") {f.chown(nil, nil)} @@ -250,10 +261,14 @@ def test_realpath tst = realdir + (File::SEPARATOR*3 + ".") assert_equal(realdir, File.realpath(tst)) assert_equal(realdir, File.realpath(".", tst)) - assert_equal(realdir, Dir.chdir(realdir) {File.realpath(".")}) + if main_ractor? + assert_equal(realdir, Dir.chdir(realdir) {File.realpath(".")}) + end realpath = File.join(realdir, "test") File.write(realpath, "") - assert_equal(realpath, Dir.chdir(realdir) {File.realpath("test")}) + if main_ractor? + assert_equal(realpath, Dir.chdir(realdir) {File.realpath("test")}) + end if File::ALT_SEPARATOR bug2961 = '[ruby-core:28653]' assert_equal(realdir, File.realpath(realdir.tr(File::SEPARATOR, File::ALT_SEPARATOR)), bug2961) @@ -300,8 +315,10 @@ def test_realdirpath assert_equal(realdir, File.realdirpath(tst)) assert_equal(realdir, File.realdirpath(".", tst)) assert_equal(File.join(realdir, "foo"), File.realdirpath("foo", tst)) - assert_equal(realdir, Dir.chdir(realdir) {File.realdirpath(".")}) - assert_equal(File.join(realdir, "foo"), Dir.chdir(realdir) {File.realdirpath("foo")}) + if main_ractor? + assert_equal(realdir, Dir.chdir(realdir) {File.realdirpath(".")}) + assert_equal(File.join(realdir, "foo"), Dir.chdir(realdir) {File.realdirpath("foo")}) if main + end } begin result = File.realdirpath("bar", "//:/foo") @@ -314,6 +331,7 @@ def test_realdirpath end def test_realdirpath_junction + omit "Dir.chdir" unless main_ractor? Dir.mktmpdir('rubytest-realpath') {|tmpdir| Dir.chdir(tmpdir) do Dir.mkdir('foo') @@ -339,6 +357,7 @@ def test_utime_with_minus_time_segv end def test_utime + pend "Tempfile" unless main_ractor? bug6385 = '[ruby-core:44776]' mod_time_contents = Time.at 1306527039 @@ -372,6 +391,7 @@ def measure_time end def test_stat + pend "Tempfile" unless main_ractor? btime = Process.clock_gettime(Process::CLOCK_REALTIME) Tempfile.create("stat") {|file| btime = (btime + Process.clock_gettime(Process::CLOCK_REALTIME)) / 2 diff --git a/test/ruby/test_file_exhaustive.rb b/test/ruby/test_file_exhaustive.rb index b20b597256a125..7c905a037d62c1 100644 --- a/test/ruby/test_file_exhaustive.rb +++ b/test/ruby/test_file_exhaustive.rb @@ -7,7 +7,7 @@ class TestFileExhaustive < Test::Unit::TestCase ROOT_REGEXP = %r'\A(?:[a-z]:(?=(/))|//[^/]+/[^/]+)'i - DRIVE = Dir.pwd[ROOT_REGEXP] + DRIVE = Dir.pwd[ROOT_REGEXP].freeze POSIX = /cygwin|mswin|bccwin|mingw|emx/ !~ RUBY_PLATFORM NTFS = !(/mingw|mswin|bccwin/ !~ RUBY_PLATFORM) @@ -19,7 +19,7 @@ def assert_incompatible_encoding end def setup - @dir = Dir.mktmpdir("ruby-test") + @dir = Dir.mktmpdir("#{Ractor.current.object_id}") File.chown(-1, Process.gid, @dir) end @@ -268,7 +268,7 @@ def test_stat_drive_root end if DRIVE def test_stat_dotted_prefix - Dir.mktmpdir do |dir| + Dir.mktmpdir("#{Ractor.current.object_id}") do |dir| prefix = File.join(dir, "...a") Dir.mkdir(prefix) assert_file.exist?(prefix) @@ -277,7 +277,7 @@ def test_stat_dotted_prefix Dir.chdir(dir) do assert_nothing_raised { File.stat(File.basename(prefix)) } - end + end if main_ractor? end end if NTFS @@ -706,7 +706,7 @@ def test_utime File.write(path, "") rescue next assert_equal(1, File.utime(nil, nil, path)) end - end + end if main_ractor? end def test_utime_symlinkfile @@ -813,6 +813,7 @@ def test_rename end def test_umask + omit "global side effects" if multiple_ractors? prev = File.umask(0777) assert_equal(0777, File.umask) open(nofile, "w") { } @@ -874,6 +875,7 @@ def test_expand_path_absolute end def test_expand_path_memsize + pend "ObjectSpace.memsize_of not yet ractor safe" if non_main_ractor? bug9934 = '[ruby-core:63114] [Bug #9934]' require "objspace" path = File.expand_path("/foo") @@ -914,6 +916,7 @@ def test_expand_path_encoding end def test_expand_path_encoding_filesystem + omit "global side effects" if multiple_ractors? home = ENV["HOME"] ENV["HOME"] = "#{DRIVE}/UserHome" @@ -924,12 +927,13 @@ def test_expand_path_encoding_filesystem assert_equal fs, File.expand_path(path).encoding assert_equal fs, File.expand_path(path, dir).encoding ensure - ENV["HOME"] = home + ENV["HOME"] = home if home end UnknownUserHome = "~foo_bar_baz_unknown_user_wahaha".freeze def test_expand_path_home + omit "global side effects" if multiple_ractors? assert_kind_of(String, File.expand_path("~")) if ENV["HOME"] assert_raise(ArgumentError) { File.expand_path(UnknownUserHome) } assert_raise(ArgumentError) { File.expand_path(UnknownUserHome, "/") } @@ -948,14 +952,17 @@ def test_expand_path_home ENV["HOME"] = "." assert_raise(ArgumentError, bug3630) { File.expand_path("~") } ensure - ENV["HOME"] = home - ENV["HOMEDRIVE"] = home_drive - ENV["HOMEPATH"] = home_path - ENV["USERPROFILE"] = user_profile + if home + ENV["HOME"] = home + ENV["HOMEDRIVE"] = home_drive + ENV["HOMEPATH"] = home_path + ENV["USERPROFILE"] = user_profile + end end end def test_expand_path_home_dir_string + omit "global side effects" if multiple_ractors? home = ENV["HOME"] new_home = "#{DRIVE}/UserHome" ENV["HOME"] = new_home @@ -969,7 +976,7 @@ def test_expand_path_home_dir_string ENV["HOME"] = "#{DRIVE}UserHome" assert_raise(ArgumentError) { File.expand_path("~") } ensure - ENV["HOME"] = home + ENV["HOME"] = home if home end if /mswin|mingw/ =~ RUBY_PLATFORM @@ -1091,31 +1098,34 @@ def test_expand_path_converts_a_pathname_which_starts_with_a_slash_using_a_curre end def test_expand_path_converts_a_pathname_to_an_absolute_pathname_using_home_as_base + omit "global side effects" if multiple_ractors? old_home = ENV["HOME"] home = ENV["HOME"] = "#{DRIVE}/UserHome" assert_equal(home, File.expand_path("~")) assert_equal(home, File.expand_path("~", "C:/FooBar")) assert_equal(File.join(home, "a"), File.expand_path("~/a", "C:/FooBar")) ensure - ENV["HOME"] = old_home + ENV["HOME"] = old_home if old_home end def test_expand_path_converts_a_pathname_to_an_absolute_pathname_using_unc_home + omit "global side effects" if multiple_ractors? old_home = ENV["HOME"] unc_home = ENV["HOME"] = "//UserHome" assert_equal(unc_home, File.expand_path("~")) ensure - ENV["HOME"] = old_home + ENV["HOME"] = old_home if old_home end if DRIVE def test_expand_path_does_not_modify_a_home_string_argument + omit "global side effects" if multiple_ractors? old_home = ENV["HOME"] home = ENV["HOME"] = "#{DRIVE}/UserHome" str = "~/a" assert_equal("#{home}/a", File.expand_path(str)) assert_equal("~/a", str) ensure - ENV["HOME"] = old_home + ENV["HOME"] = old_home if old_home end def test_expand_path_raises_argument_error_for_any_supplied_username @@ -1135,11 +1145,12 @@ def test_expand_path_error_for_nonexistent_username end unless DRIVE def test_expand_path_error_for_non_absolute_home + omit "global side effects" if multiple_ractors? old_home = ENV["HOME"] ENV["HOME"] = "./UserHome" assert_raise_with_message(ArgumentError, /non-absolute home/) {File.expand_path("~")} ensure - ENV["HOME"] = old_home + ENV["HOME"] = old_home if old_home end def test_expand_path_raises_a_type_error_if_not_passed_a_string_type @@ -1187,6 +1198,7 @@ def test_expand_path_with_drive_letter if /darwin/ =~ RUBY_PLATFORM and Encoding.find("filesystem") == Encoding::UTF_8 def test_expand_path_compose + omit "Dir.chdir" unless main_ractor? pp = Object.new.extend(Test::Unit::Assertions) def pp.mu_pp(str) #:nodoc: str.dump @@ -1416,6 +1428,7 @@ def test_truncate def test_flock_exclusive omit "[Bug #18613]" if /freebsd/ =~ RUBY_PLATFORM + omit "subprocess" unless main_ractor? timeout = EnvUtil.apply_timeout_scale(1).to_s File.open(regular_file, "r+") do |f| @@ -1447,6 +1460,7 @@ def test_flock_exclusive def test_flock_shared omit "[Bug #18613]" if /freebsd/ =~ RUBY_PLATFORM + omit "subprocess" unless main_ractor? timeout = EnvUtil.apply_timeout_scale(1).to_s File.open(regular_file, "r+") do |f| diff --git a/test/ruby/test_flip.rb b/test/ruby/test_flip.rb index 9c58f5f497c0a9..42d063d39659c5 100644 --- a/test/ruby/test_flip.rb +++ b/test/ruby/test_flip.rb @@ -53,6 +53,7 @@ def test_shared_thread end def test_input_line_number_range + omit "Cannot access $." if non_main_ractor? bug12947 = '[ruby-core:78162] [Bug #12947]' ary = b1 = b2 = nil EnvUtil.suppress_warning do diff --git a/test/ruby/test_float.rb b/test/ruby/test_float.rb index b865d339a96341..c4487313ee8341 100644 --- a/test/ruby/test_float.rb +++ b/test/ruby/test_float.rb @@ -657,7 +657,7 @@ def (prec = Object.new).to_int; 2; end -18446744073709551616.8, -18446744073709551617.0, -18446744073709551618.0, - ] + ].freeze def test_truncate VS.each {|f| @@ -861,10 +861,13 @@ def o.to_f; inf = Float::INFINITY; inf/inf; end assert_raise(Encoding::CompatibilityError) {Float("0".encode("utf-32le"))} assert_raise(Encoding::CompatibilityError) {Float("0".encode("iso-2022-jp"))} - assert_raise_with_message(ArgumentError, /\u{1f4a1}/) {Float("\u{1f4a1}")} + EnvUtil.with_default_internal(Encoding::UTF_8) do + assert_raise_with_message(ArgumentError, /\u{1f4a1}/) {Float("\u{1f4a1}")} + end end def test_invalid_str + omit "under_gc_stress" if multiple_ractors? bug4310 = '[ruby-core:34820]' assert_raise(ArgumentError, bug4310) {under_gc_stress {Float('a'*10000)}} end diff --git a/test/ruby/test_gc.rb b/test/ruby/test_gc.rb index 5fc9ea508c7142..ffc5888fd8d1dc 100644 --- a/test/ruby/test_gc.rb +++ b/test/ruby/test_gc.rb @@ -9,6 +9,7 @@ def initialize(a) end def test_gc + omit "global side effects" if multiple_ractors? prev_stress = GC.stress GC.stress = false @@ -40,6 +41,7 @@ def use_rgengc? end def test_enable_disable + omit "global side effects" if multiple_ractors? EnvUtil.without_gc do GC.enable assert_equal(false, GC.enable) @@ -53,6 +55,7 @@ def test_enable_disable end def test_gc_config_full_mark_by_default + omit "races with other ractors" if multiple_ractors? config = GC.config assert_not_empty(config) assert_true(config[:rgengc_allow_full_mark]) @@ -63,6 +66,7 @@ def test_gc_config_invalid_args end def test_gc_config_setting_returns_updated_config_hash + omit "global side effects" if multiple_ractors? old_value = GC.config[:rgengc_allow_full_mark] assert_true(old_value) @@ -81,6 +85,7 @@ def test_gc_config_setting_returns_config_hash end def test_gc_config_disable_major + omit "global side effects" if multiple_ractors? GC.enable GC.start @@ -103,6 +108,7 @@ def test_gc_config_disable_major end def test_gc_config_disable_major_gc_start_always_works + omit "global side effects" if multiple_ractors? GC.config(full_mark: false) major_count = GC.stat[:major_gc_count] @@ -129,6 +135,7 @@ def test_gc_config_implementation_is_readonly def test_start_full_mark return unless use_rgengc? + omit "latest_gc_info could race" if multiple_ractors? omit 'stress' if GC.stress 3.times { GC.start } # full mark and next time it should be minor mark @@ -140,6 +147,7 @@ def test_start_full_mark end def test_start_immediate_sweep + omit "latest_gc_info could race" if multiple_ractors? omit 'stress' if GC.stress GC.start(immediate_sweep: false) @@ -156,6 +164,7 @@ def test_count end def test_stat + omit "global side effects" if multiple_ractors? res = GC.stat assert_equal(false, res.empty?) assert_kind_of(Integer, res[:count]) @@ -201,6 +210,7 @@ def test_stat_single def test_stat_constraints omit 'stress' if GC.stress + omit "racy" if multiple_ractors? stat = GC.stat # marking_time + sweeping_time could differ from time by 1 because they're stored in nanoseconds @@ -217,6 +227,7 @@ def test_stat_constraints def test_stat_heap omit 'stress' if GC.stress + omit "global side effects" if multiple_ractors? stat_heap = {} stat = {} @@ -273,6 +284,7 @@ def test_stat_heap_all def test_stat_heap_constraints omit 'stress' if GC.stress + omit "races with other ractors" if multiple_ractors? stat = GC.stat stat_heap = GC.stat_heap @@ -311,6 +323,7 @@ def test_measure_total_time def test_latest_gc_info omit 'stress' if GC.stress + omit "GC.stress=" if multiple_ractors? assert_separately([], __FILE__, __LINE__, <<-'RUBY') GC.start @@ -330,10 +343,12 @@ def test_latest_gc_info assert_equal true, h[:immediate_sweep] assert_equal true, h.key?(:need_major_by) - GC.stress = true - assert_equal :force, GC.latest_gc_info[:major_by] - ensure - GC.stress = false + begin + GC.stress = true + assert_equal :force, GC.latest_gc_info[:major_by] + ensure + GC.stress = false + end end def test_latest_gc_info_argument @@ -349,6 +364,7 @@ def test_latest_gc_info_argument def test_latest_gc_info_need_major_by return unless use_rgengc? omit 'stress' if GC.stress + omit "global side effects" if multiple_ractors? 3.times { GC.start } assert_nil GC.latest_gc_info(:need_major_by) @@ -596,6 +612,7 @@ def test_profiler_clear end def test_profiler_raw_data + omit "racy" if multiple_ractors? GC::Profiler.enable GC.start assert GC::Profiler.raw_data @@ -604,6 +621,7 @@ def test_profiler_raw_data end def test_profiler_total_time + omit "racy" if multiple_ractors? GC::Profiler.enable GC::Profiler.clear @@ -802,6 +820,7 @@ def test_gc_stress_at_startup end def test_gc_disabled_start + omit "global side effects" if multiple_ractors? EnvUtil.without_gc do c = GC.count GC.start @@ -881,12 +900,14 @@ def test_object_ids_never_repeat end def test_ast_node_buffer + omit "TODO: freezes process" if multiple_ractors? # https://github.com/ruby/ruby/pull/4416 Module.new.class_eval( (["# shareable_constant_value: literal"] + (0..100000).map {|i| "M#{ i } = {}" }).join("\n")) end def test_old_to_young_reference + pend "ObjectSpace.dump not yet ractor safe" unless main_ractor? EnvUtil.without_gc do require "objspace" diff --git a/test/ruby/test_gc_compact.rb b/test/ruby/test_gc_compact.rb index 3eaa93dfaea0bb..1c6127b649077a 100644 --- a/test/ruby/test_gc_compact.rb +++ b/test/ruby/test_gc_compact.rb @@ -18,6 +18,7 @@ module OmitUnlessCompactSupported def setup omit "GC compaction not supported on this platform" unless supports_compact? + omit "GC.auto_compact = true then setting back to prev is racy" if multiple_ractors? super end end diff --git a/test/ruby/test_hash.rb b/test/ruby/test_hash.rb index dbf041a7321252..85c9dfafe7dc88 100644 --- a/test/ruby/test_hash.rb +++ b/test/ruby/test_hash.rb @@ -62,17 +62,18 @@ def test_hash x.default = 5 assert_equal(5, x[23]) + z = nil x = Hash.new - def x.default(k) - $z = k + x.singleton_class.define_method(:default) do |k| + z = k self[k] = k*2 end - $z = 0 + z = 0 assert_equal(44, x[22]) - assert_equal(22, $z) - $z = 0 + assert_equal(22, z) + z = 0 assert_equal(44, x[22]) - assert_equal(0, $z) + assert_equal(0, z) end # From rubicon @@ -859,6 +860,7 @@ def test_to_h_block end def test_to_s + omit "Accesses global variable" if non_main_ractor? h = @cls[ 1 => 2, "cat" => "dog", 1.5 => :fred ] assert_equal(h.inspect, h.to_s) assert_deprecated_warning { $, = ":" } @@ -866,10 +868,11 @@ def test_to_s h = @cls[] assert_equal(h.inspect, h.to_s) ensure - $, = nil + $, = nil if main_ractor? end def test_inspect + omit "global side effects" if multiple_ractors? no_quote = '{a: 1, a!: 1, a?: 1}' quote0 = '{"": 1}' quote1 = '{"0": 1, "!": 1, "%": 1, "&": 1, "*": 1, "+": 1, "-": 1, "/": 1, "<": 1, ">": 1, "^": 1, "`": 1, "|": 1, "~": 1}' @@ -2001,6 +2004,7 @@ def o.to_hash; {3=>4} end end def test_AREF_fstring_key + omit "EnvUtil.without_gc" unless main_ractor? # warmup ObjectSpace.count_objects ObjectSpace.count_objects @@ -2137,6 +2141,7 @@ def hash_iter_recursion(h, level) end def test_iterlevel_in_ivar_bug19589 + pend "Ractor bug!" if non_main_ractor? # NOTE: we get stack level too deep within a ractor h = { a: nil } # Recursion level should be over 127 to actually test iterlevel being set in an instance variable, # but it should be under 131 not to overflow the stack under MN threads/ractors. @@ -2173,6 +2178,7 @@ def hash end def test_memory_size_after_delete + pend "ObjectSpace.memsize_of not yet ractor safe" if non_main_ractor? require 'objspace' h = {} 1000.times {|i| h[i] = true} @@ -2259,6 +2265,7 @@ def test_label_syntax end def test_broken_hash_value + omit "too many objects" if multiple_ractors? bug14218 = '[ruby-core:84395] [Bug #14218]' assert_equal(0, 1_000_000.times.count{a=Object.new.hash; b=Object.new.hash; a < 0 && b < 0 && a + b > 0}, bug14218) diff --git a/test/ruby/test_integer.rb b/test/ruby/test_integer.rb index fb7aabba358b21..a6b93724389246 100644 --- a/test/ruby/test_integer.rb +++ b/test/ruby/test_integer.rb @@ -7,7 +7,7 @@ class TestInteger < Test::Unit::TestCase LONG_MAX = RbConfig::LIMITS['LONG_MAX'] def test_aref - + pend "TODO: why taking too long" if multiple_ractors? [ *-16..16, *(FIXNUM_MIN-2)..(FIXNUM_MIN+2), @@ -158,7 +158,9 @@ def obj.to_i; "str"; end assert_raise(Encoding::CompatibilityError, bug6192) {Integer("0".encode("utf-32le"))} assert_raise(Encoding::CompatibilityError, bug6192) {Integer("0".encode("iso-2022-jp"))} - assert_raise_with_message(ArgumentError, /\u{1f4a1}/) {Integer("\u{1f4a1}")} + EnvUtil.with_default_internal(Encoding::UTF_8) do + assert_raise_with_message(ArgumentError, /\u{1f4a1}/) {Integer("\u{1f4a1}")} + end obj = Struct.new(:s).new(%w[42 not-an-integer]) def obj.to_str; s.shift; end diff --git a/test/ruby/test_integer_comb.rb b/test/ruby/test_integer_comb.rb index 150f45cfd7ddb7..e293fb3dc1f54f 100644 --- a/test/ruby/test_integer_comb.rb +++ b/test/ruby/test_integer_comb.rb @@ -104,7 +104,7 @@ class TestIntegerComb < Test::Unit::TestCase 0xffffffffffffffffffffffffffffffffffffffffffffffff, 0x1000000000000000000000000000000000000000000000000, 0x1000000000000000000000000000000000000000000000001 - ] + ].freeze #VS.map! {|v| 0x4000000000000000.coerce(v)[0] } #VS.concat VS.find_all {|v| Fixnum === v }.map {|v| 0x4000000000000000.coerce(v)[0] } diff --git a/test/ruby/test_io.rb b/test/ruby/test_io.rb index 3ec8726b5e45ce..feb1ee3f21ac7f 100644 --- a/test/ruby/test_io.rb +++ b/test/ruby/test_io.rb @@ -77,6 +77,7 @@ def with_read_pipe(content) end def mkcdtmpdir + omit "Dir.chdir" unless main_ractor? Dir.mktmpdir {|d| Dir.chdir(d) { yield @@ -114,6 +115,7 @@ def test_pipe end def test_binmode_pipe + omit "global side effects" if multiple_ractors? EnvUtil.with_default_internal(Encoding::UTF_8) do EnvUtil.with_default_external(Encoding::UTF_8) do begin @@ -999,6 +1001,7 @@ def test_copy_stream_socket6 end def test_copy_stream_socket7 + omit "Signal.trap not ractor safe" if non_main_ractor? if RUBY_PLATFORM =~ /mingw|mswin/ omit "pread(2) is not implemented." end @@ -1014,7 +1017,7 @@ def test_copy_stream_socket7 rescue Errno::EBADF omit "nonblocking IO for pipe is not implemented" end - trapping_usr2 do |rd| + trapping_usr2 do |rd| # not ractor safe nr = 30 begin pid = fork do @@ -1116,6 +1119,7 @@ def test_copy_stream_strio_to_io end def test_copy_stream_strio_to_tempfile + pend "Tempfile" if non_main_ractor? bug11015 = '[ruby-core:68676] [Bug #11015]' # StringIO to Tempfile src = StringIO.new("abcd") @@ -1127,7 +1131,7 @@ def test_copy_stream_strio_to_tempfile assert_equal("abcd", dst.read) assert_equal(4, pos, bug11015) ensure - dst.close! + dst&.close! end def test_copy_stream_pathname_to_pathname @@ -1142,6 +1146,7 @@ def test_copy_stream_pathname_to_pathname end def test_copy_stream_dup_buffer + pend "Tempfile" if non_main_ractor? bug21131 = '[ruby-core:120961] [Bug #21131]' mkcdtmpdir do dst_class = Class.new do @@ -1391,6 +1396,7 @@ def ruby(*args) end def test_try_convert + omit "non-shareable value" if non_main_ractor? assert_equal(STDOUT, IO.try_convert(STDOUT)) assert_equal(nil, IO.try_convert("STDOUT")) end @@ -1854,6 +1860,7 @@ def test_close_write_non_readable end def test_close_read_write_separately + pend "TODO: buggy with ractors" if multiple_ractors? bug = '[ruby-list:49598]' (1..10).each do |i| assert_nothing_raised(IOError, "#{bug} trying ##{i}") do @@ -1898,6 +1905,7 @@ def test_pid_after_close_read end def make_tempfile + pend "Tempfile" if non_main_ractor? t = Tempfile.new("test_io") t.binmode t.puts "foo" @@ -1936,6 +1944,7 @@ def test_set_lineno end def test_set_lineno_gets + omit "global variable access" if non_main_ractor? pipe(proc do |w| w.puts "foo" w.puts "bar" @@ -1986,6 +1995,7 @@ def test_readline_separators end def test_readline_separators_limits + pend "Tempfile" if non_main_ractor? t = Tempfile.open("readline_limit") str = "#" * 50 sep = "def" @@ -2017,6 +2027,7 @@ def test_readline_separators_limits end def test_readline_limit_without_separator + pend "Tempfile" if non_main_ractor? t = Tempfile.open("readline_limit") str = "#" * 50 sep = "\n" @@ -2093,6 +2104,7 @@ def test_readline_limit_nonascii end def test_set_lineno_readline + omit "global variable access" if non_main_ractor? pipe(proc do |w| w.puts "foo" w.puts "bar" @@ -2518,10 +2530,11 @@ def try_fdopen(fd, autoclose = true, level = 50) end def test_autoclose + pend "TODO: assert_raise fails sometimes under multiple ractors" if multiple_ractors? feature2250 = '[ruby-core:26222]' pre = 'ft2250' - Dir.mktmpdir {|d| + Dir.mktmpdir("#{Ractor.current.object_id}") {|d| t = open("#{d}/#{pre}", "w") f = IO.for_fd(t.fileno) assert_equal(true, f.autoclose?) @@ -2541,6 +2554,7 @@ def test_autoclose end def test_autoclose_true_closed_by_finalizer + pend "Tempfile" if non_main_ractor? feature2250 = '[ruby-core:26222]' pre = 'ft2250' t = Tempfile.new(pre) @@ -2560,6 +2574,7 @@ def test_autoclose_true_closed_by_finalizer end def test_autoclose_false_closed_by_finalizer + pend "Tempfile" if non_main_ractor? feature2250 = '[ruby-core:26222]' pre = 'ft2250' t = Tempfile.new(pre) @@ -2572,7 +2587,7 @@ def test_autoclose_false_closed_by_finalizer assert_nothing_raised(Errno::EBADF, feature2250) {t.close} end ensure - t.close! + t&.close! end def test_open_redirect @@ -2602,6 +2617,7 @@ def o.to_open(kw); kw; end end def test_open_pipe + omit "fork" unless main_ractor? assert_deprecated_warning(/Kernel#open with a leading '\|'/) do # https://bugs.ruby-lang.org/issues/19630 open("|" + EnvUtil.rubybin, "r+") do |f| f.puts "puts 'foo'" @@ -2805,22 +2821,25 @@ def test_reopen_opt_encoding bug11320 = '[ruby-core:69780] [Bug #11320]' ["UTF-8", "EUC-JP", "Shift_JIS"].each do |enc| - define_method("test_reopen_nonascii(#{enc})") do - mkcdtmpdir do - fname = "\u{30eb 30d3 30fc}".encode(enc) - File.write(fname, '') - assert_file.exist?(fname) - stdin = $stdin.dup - begin - assert_nothing_raised(Errno::ENOENT, "#{bug11320}: #{enc}") { - $stdin.reopen(fname, 'r') - } - ensure - $stdin.reopen(stdin) - stdin.close + class_eval <<-RUBY + def test_reopen_nonascii_#{enc.sub('-', '_')} + mkcdtmpdir do + enc = #{enc.inspect} + fname = "#{'\u{30eb 30d3 30fc}'}".encode(enc) + File.write(fname, '') + assert_file.exist?(fname) + stdin = $stdin.dup + begin + assert_nothing_raised(Errno::ENOENT, "#{bug11320}: #{enc}") { + $stdin.reopen(fname, 'r') + } + ensure + $stdin.reopen(stdin) + stdin.close + end end end - end + RUBY end def test_reopen_ivar @@ -2923,6 +2942,7 @@ def test_print end def test_print_separators + omit "global variable access" if non_main_ractor? EnvUtil.suppress_warning { $, = ':' $\ = "\n" @@ -2938,8 +2958,10 @@ def test_print_separators r.close end) ensure - $, = nil - $\ = nil + if main_ractor? + $, = nil + $\ = nil + end end def test_putc @@ -3139,6 +3161,7 @@ def test_DATA_binmode end def test_threaded_flush + omit "separate process" if non_main_ractor? bug3585 = '[ruby-core:31348]' src = "#{<<~"begin;"}\n#{<<~'end;'}" begin; @@ -3156,6 +3179,7 @@ def test_threaded_flush end def test_flush_in_finalizer1 + pend "Tempfile" if non_main_ractor? bug3910 = '[ruby-dev:42341]' tmp = Tempfile.open("bug3910") {|t| path = t.path @@ -3172,15 +3196,18 @@ def test_flush_in_finalizer1 t } ensure - ObjectSpace.each_object(File) {|f| - if f.instance_variables.include?(:@test_flush_in_finalizer1) - f.close - end - } - tmp.close! + if main_ractor? + ObjectSpace.each_object(File) {|f| + if f.instance_variables.include?(:@test_flush_in_finalizer1) + f.close + end + } + tmp.close! + end end def test_flush_in_finalizer2 + pend "Tempfile" if non_main_ractor? bug3910 = '[ruby-dev:42341]' Tempfile.create("bug3910") {|t| path = t.path @@ -3313,6 +3340,7 @@ def test_invalid_advise end def test_fcntl_lock_linux + pend "Tempfile" if non_main_ractor? pad = 0 Tempfile.create(self.class.name) do |f| r, w = IO.pipe @@ -3345,6 +3373,7 @@ def test_fcntl_lock_linux [nil].pack("p").bytesize == 8 # unless x32 platform. def test_fcntl_lock_freebsd + pend "Tempfile" if non_main_ractor? start = 12 len = 34 sysid = 0 @@ -3378,6 +3407,7 @@ def test_fcntl_lock_freebsd end if /freebsd/ =~ RUBY_PLATFORM # A binary form of struct flock depend on platform def test_fcntl_dupfd + pend "Tempfile" if non_main_ractor? Tempfile.create(self.class.name) do |f| fd = f.fcntl(Fcntl::F_DUPFD, 63) begin @@ -3529,6 +3559,7 @@ def test_s_binwrite end def test_race_between_read + pend "Tempfile" if non_main_ractor? Tempfile.create("test") {|file| begin path = file.path @@ -3611,7 +3642,7 @@ def test_ioctl_linux end if /^(?:i.?86|x86_64)-linux/ =~ RUBY_PLATFORM def test_ioctl_linux2 - return unless STDIN.tty? # stdin is not a terminal + return unless $stdin.tty? # stdin is not a terminal begin f = File.open('/dev/tty') rescue Errno::ENOENT, Errno::ENXIO => e @@ -3668,9 +3699,11 @@ def test_setpos end def test_std_fileno - assert_equal(0, STDIN.fileno) - assert_equal(1, STDOUT.fileno) - assert_equal(2, STDERR.fileno) + if main_ractor? + assert_equal(0, STDIN.fileno) + assert_equal(1, STDOUT.fileno) + assert_equal(2, STDERR.fileno) + end assert_equal(0, $stdin.fileno) assert_equal(1, $stdout.fileno) assert_equal(2, $stderr.fileno) @@ -3750,6 +3783,7 @@ def test_advise_pipe end if /linux/ =~ RUBY_PLATFORM def assert_buffer_not_raise_shared_string_error + pend "Tempfile" if non_main_ractor? bug6764 = '[ruby-core:46586]' bug9847 = '[ruby-core:62643] [Bug #9847]' size = 28 @@ -3768,7 +3802,7 @@ def assert_buffer_not_raise_shared_string_error end assert_equal(data, w.join(""), bug9847) ensure - t.close! + t&.close! end def test_read_buffer_not_raise_shared_string_error @@ -3962,6 +3996,7 @@ def test_sysread_unlocktmp_ensure end if /cygwin/ !~ RUBY_PLATFORM def test_exception_at_close + pend "TODO: assert_raise fails sometimes under multiple ractors" if multiple_ractors? bug10153 = '[ruby-core:64463] [Bug #10153] exception in close at the end of block' assert_raise(Errno::EBADF, bug10153) do IO.pipe do |r, w| @@ -4441,4 +4476,18 @@ def test_fork_close assert_predicate(status, :success?) RUBY end + + def test_no_fork_in_ractor + omit "fork is not supported" unless Process.respond_to?(:fork) + + assert_ractor(<<~'RUBY') + r = Ractor.new do + fork { } + end + end + assert_raise Ractor::IsolationError do + r.value + end + RUBY + end end diff --git a/test/ruby/test_io_buffer.rb b/test/ruby/test_io_buffer.rb index 62c46678882a10..afb57f01312c68 100644 --- a/test/ruby/test_io_buffer.rb +++ b/test/ruby/test_io_buffer.rb @@ -334,7 +334,7 @@ def test_zero_length_get_string end # We check that values are correctly round tripped. - RANGES = { + Ractor.make_shareable(RANGES = { :U8 => [0, 2**8-1], :S8 => [-2**7, 0, 2**7-1], @@ -355,7 +355,7 @@ def test_zero_length_get_string :F32 => [-1.0, 0.0, 0.5, 1.0, 128.0], :F64 => [-1.0, 0.0, 0.5, 1.0, 128.0], - } + }) def test_get_set_value buffer = IO::Buffer.new(128) @@ -461,6 +461,7 @@ def test_invalidation end def hello_world_tempfile(repeats = 1) + pend "Tempfile" if non_main_ractor? io = Tempfile.new repeats.times do io.write("Hello World") @@ -506,6 +507,7 @@ def test_read_with_length_and_offset end def test_write + pend "Tempfile" if non_main_ractor? io = Tempfile.new buffer = IO::Buffer.new(128) @@ -515,10 +517,11 @@ def test_write io.seek(0) assert_equal "Hello", io.read(5) ensure - io.close! + io&.close! end def test_write_with_length_and_offset + pend "Tempfile" if non_main_ractor? io = Tempfile.new buffer = IO::Buffer.new(5) @@ -528,10 +531,11 @@ def test_write_with_length_and_offset io.seek(0) assert_equal "ello", io.read(4) ensure - io.close! + io&.close! end def test_pread + pend "Tempfile" if non_main_ractor? io = Tempfile.new io.write("Hello World") io.seek(0) @@ -542,10 +546,11 @@ def test_pread assert_equal "World", buffer.get_string(0, 5) assert_equal 0, io.tell ensure - io.close! + io&.close! end def test_pread_offset + pend "Tempfile" if non_main_ractor? io = Tempfile.new io.write("Hello World") io.seek(0) @@ -556,10 +561,11 @@ def test_pread_offset assert_equal "World", buffer.get_string(6, 5) assert_equal 0, io.tell ensure - io.close! + io&.close! end def test_pwrite + pend "Tempfile" if non_main_ractor? io = Tempfile.new buffer = IO::Buffer.new(128) @@ -571,10 +577,11 @@ def test_pwrite io.seek(6) assert_equal "World", io.read(5) ensure - io.close! + io&.close! end def test_pwrite_offset + pend "Tempfile" if non_main_ractor? io = Tempfile.new buffer = IO::Buffer.new(128) @@ -586,7 +593,7 @@ def test_pwrite_offset io.seek(6) assert_equal "World", io.read(5) ensure - io.close! + io&.close! end def test_operators @@ -610,6 +617,7 @@ def test_inplace_operators end def test_shared + omit "fork" unless main_ractor? message = "Hello World" buffer = IO::Buffer.new(64, IO::Buffer::MAPPED | IO::Buffer::SHARED) @@ -625,6 +633,7 @@ def test_shared end def test_private + pend "Tempfile" if non_main_ractor? Tempfile.create(%w"buffer .txt") do |file| file.write("Hello World") @@ -697,6 +706,7 @@ def test_set_string_null_destination # https://bugs.ruby-lang.org/issues/21210 def test_bug_21210 omit "compaction is not supported on this platform" unless GC.respond_to?(:compact) + omit "verify_compaction_references" unless main_ractor? str = +"hello" buf = IO::Buffer.for(str) diff --git a/test/ruby/test_io_m17n.rb b/test/ruby/test_io_m17n.rb index b01d627d920d7e..72bd8d6c75181a 100644 --- a/test/ruby/test_io_m17n.rb +++ b/test/ruby/test_io_m17n.rb @@ -11,9 +11,10 @@ class TestIO_M17N < Test::Unit::TestCase Encoding::EUC_JP, Encoding::Shift_JIS, Encoding::UTF_8 - ] + ].freeze def with_tmpdir + omit "Dir.chdir" unless main_ractor? Dir.mktmpdir {|dir| Dir.chdir(dir) { yield dir @@ -404,18 +405,18 @@ def test_dup_undef end def test_stdin - assert_equal(Encoding.default_external, STDIN.external_encoding) - assert_equal(nil, STDIN.internal_encoding) + assert_equal(Encoding.default_external, $stdin.external_encoding) + assert_equal(nil, $stdin.internal_encoding) end def test_stdout - assert_equal(nil, STDOUT.external_encoding) - assert_equal(nil, STDOUT.internal_encoding) + assert_equal(nil, $stdout.external_encoding) + assert_equal(nil, $stdout.internal_encoding) end def test_stderr - assert_equal(nil, STDERR.external_encoding) - assert_equal(nil, STDERR.internal_encoding) + assert_equal(nil, $stderr.external_encoding) + assert_equal(nil, $stderr.internal_encoding) end def test_terminator_conversion @@ -464,6 +465,7 @@ def test_nonascii_terminator end def test_pipe_terminator_conversion + pend "Timeout" if non_main_ractor? rs = "\xA2\xA2".encode("utf-8", "euc-jp") pipe("euc-jp:utf-8", proc do |w| @@ -1326,6 +1328,7 @@ def test_stdin_external_encoding_with_reopen end unless /mswin|mingw/ =~ RUBY_PLATFORM # passing non-stdio fds is not supported def test_popen_r_enc + omit "subprocess" unless main_ractor? IO.popen("#{EnvUtil.rubybin} -e 'putc 255'", "r:ascii-8bit") {|f| assert_equal(Encoding::ASCII_8BIT, f.external_encoding) assert_equal(nil, f.internal_encoding) @@ -1336,6 +1339,7 @@ def test_popen_r_enc end def test_popen_r_enc_in_opt + omit "subprocess" unless main_ractor? IO.popen("#{EnvUtil.rubybin} -e 'putc 255'", "r", encoding: "ascii-8bit") {|f| assert_equal(Encoding::ASCII_8BIT, f.external_encoding) assert_equal(nil, f.internal_encoding) @@ -1346,6 +1350,7 @@ def test_popen_r_enc_in_opt end def test_popen_r_enc_in_opt2 + omit "subprocess" unless main_ractor? IO.popen("#{EnvUtil.rubybin} -e 'putc 255'", "r", external_encoding: "ascii-8bit") {|f| assert_equal(Encoding::ASCII_8BIT, f.external_encoding) assert_equal(nil, f.internal_encoding) @@ -1356,6 +1361,7 @@ def test_popen_r_enc_in_opt2 end def test_popen_r_enc_enc + omit "subprocess" unless main_ractor? IO.popen("#{EnvUtil.rubybin} -e 'putc 0xa1'", "r:shift_jis:euc-jp") {|f| assert_equal(Encoding::Shift_JIS, f.external_encoding) assert_equal(Encoding::EUC_JP, f.internal_encoding) @@ -1366,6 +1372,7 @@ def test_popen_r_enc_enc end def test_popen_r_enc_enc_in_opt + omit "subprocess" unless main_ractor? IO.popen("#{EnvUtil.rubybin} -e 'putc 0xa1'", "r", encoding: "shift_jis:euc-jp") {|f| assert_equal(Encoding::Shift_JIS, f.external_encoding) assert_equal(Encoding::EUC_JP, f.internal_encoding) @@ -1376,6 +1383,7 @@ def test_popen_r_enc_enc_in_opt end def test_popen_r_enc_enc_in_opt2 + omit "subprocess" unless main_ractor? IO.popen("#{EnvUtil.rubybin} -e 'putc 0xa1'", "r", external_encoding: "shift_jis", internal_encoding: "euc-jp") {|f| assert_equal(Encoding::Shift_JIS, f.external_encoding) assert_equal(Encoding::EUC_JP, f.internal_encoding) @@ -1386,6 +1394,7 @@ def test_popen_r_enc_enc_in_opt2 end def test_popenv_r_enc_enc_in_opt2 + omit "subprocess" unless main_ractor? IO.popen([EnvUtil.rubybin, "-e", "putc 0xa1"], "r", external_encoding: "shift_jis", internal_encoding: "euc-jp") {|f| assert_equal(Encoding::Shift_JIS, f.external_encoding) assert_equal(Encoding::EUC_JP, f.internal_encoding) @@ -1396,6 +1405,7 @@ def test_popenv_r_enc_enc_in_opt2 end def test_open_pipe_r_enc + omit "racy" if multiple_ractors? EnvUtil.suppress_warning do # https://bugs.ruby-lang.org/issues/19630 open("|#{EnvUtil.rubybin} -e 'putc 255'", "r:ascii-8bit") {|f| assert_equal(Encoding::ASCII_8BIT, f.external_encoding) @@ -1408,6 +1418,7 @@ def test_open_pipe_r_enc end def test_open_pipe_r_enc2 + omit "racy" if multiple_ractors? EnvUtil.suppress_warning do # https://bugs.ruby-lang.org/issues/19630 open("|#{EnvUtil.rubybin} -e 'putc \"\\u3042\"'", "r:UTF-8") {|f| assert_equal(Encoding::UTF_8, f.external_encoding) @@ -1657,18 +1668,17 @@ def test_textmode_decode_universal_newline_utf16 } end - SYSTEM_NEWLINE = [] def system_newline - return SYSTEM_NEWLINE.first if !SYSTEM_NEWLINE.empty? + return @_system_newline if defined?(@_system_newline) with_tmpdir { open("newline", "wt") {|f| f.print "\n" } open("newline", "rb") {|f| - SYSTEM_NEWLINE << f.read + @_system_newline = f.read } } - SYSTEM_NEWLINE.first + @_system_newline end def test_textmode_encode_newline @@ -2168,31 +2178,34 @@ def test_w_xml_attr end %w/UTF-8 UTF-16BE UTF-16LE UTF-32BE UTF-32LE/.each do |name| - define_method("test_strip_bom:#{name}") do - path = "#{name}-bom.txt" - with_tmpdir { - text = "\uFEFF\u0100a" - stripped = "\u0100a" - content = text.encode(name) - generate_file(path, content) - result = File.read(path, mode: 'rb:BOM|UTF-8') - assert_equal(Encoding.find(name), result.encoding, name) - assert_equal(content[1..-1].b, result.b, name) - %w[rb rt r].each do |mode| - message = "#{name}, mode: #{mode.dump}" - result = File.read(path, mode: "#{mode}:BOM|UTF-8:UTF-8") - assert_equal(Encoding::UTF_8, result.encoding, message) - assert_equal(stripped, result, message) - end + class_eval <<-RUBY + def test_strip_bom_#{name.sub('-', '_')} + name = #{name.inspect} + path = "#{name}-bom.txt" + with_tmpdir { + text = "#{'\uFEFF\u0100a'}" + stripped = "#{'\u0100a'}" + content = text.encode(name) + generate_file(path, content) + result = File.read(path, mode: 'rb:BOM|UTF-8') + assert_equal(Encoding.find(name), result.encoding, name) + assert_equal(content[1..-1].b, result.b, name) + %w[rb rt r].each do |mode| + message = #{name.inspect} + ", mode: \#{mode.dump}" + result = File.read(path, mode: "\#{mode}:BOM|UTF-8:UTF-8") + assert_equal(Encoding::UTF_8, result.encoding, message) + assert_equal(stripped, result, message) + end - File.open(path, "rb") {|f| - assert_equal(Encoding.find(name), f.set_encoding_by_bom) - } - File.open(path, "rb", encoding: "iso-8859-1") {|f| - assert_raise(ArgumentError) {f.set_encoding_by_bom} + File.open(path, "rb") {|f| + assert_equal(Encoding.find(name), f.set_encoding_by_bom) + } + File.open(path, "rb", encoding: "iso-8859-1") {|f| + assert_raise(ArgumentError) {f.set_encoding_by_bom} + } } - } - end + end + RUBY end def test_strip_bom_no_conv @@ -2289,12 +2302,14 @@ def test_bom_non_utf assert_equal(Encoding::US_ASCII, enc) tlhInganHol = "\u{f8e4 f8d9 f8d7 f8dc f8d0 f8db} \u{f8d6 f8dd f8d9}" - assert_warn(/#{tlhInganHol}/) { - EnvUtil.with_default_internal(nil) { - open(IO::NULL, "w:bom|#{tlhInganHol}") {|f| enc = f.external_encoding} + if main_ractor? + assert_warn(/#{tlhInganHol}/) { + EnvUtil.with_default_internal(nil) { + open(IO::NULL, "w:bom|#{tlhInganHol}") {|f| enc = f.external_encoding} + } } - } - assert_nil(enc) + assert_nil(enc) + end end def test_bom_non_reading @@ -2794,6 +2809,7 @@ def test_read_with_buf_broken_ascii_only end def test_each_codepoint_need_more + pend "Tempfile" unless main_ractor? bug11444 = '[ruby-core:70379] [Bug #11444]' tests = [ ["incomplete multibyte", "\u{1f376}".b[0,3], [], ["invalid byte sequence in UTF-8"]], diff --git a/test/ruby/test_iseq.rb b/test/ruby/test_iseq.rb index 45223c89da5927..9a72617d33d67b 100644 --- a/test/ruby/test_iseq.rb +++ b/test/ruby/test_iseq.rb @@ -4,6 +4,10 @@ class TestISeq < Test::Unit::TestCase ISeq = RubyVM::InstructionSequence + def setup + omit "not ractor safe" unless main_ractor? + end + def test_no_linenum bug5894 = '[ruby-dev:45130]' assert_normal_exit('p RubyVM::InstructionSequence.compile("1", "mac", "", 0).to_a', bug5894) @@ -348,6 +352,7 @@ def initialize_dup(_) end def test_frozen_string_literal_compile_option + omit "global variable access" if non_main_ractor? $f = 'f' line = __LINE__ + 2 code = <<-'EOS' @@ -693,8 +698,8 @@ def test_to_binary_line_info class P def p; end def q; end - E = "" - N = "#{E}" + E = "".freeze + N = "#{E}".freeze attr_reader :i end end; diff --git a/test/ruby/test_keyword.rb b/test/ruby/test_keyword.rb index 4563308fa2ec97..2dfa46b084edfc 100644 --- a/test/ruby/test_keyword.rb +++ b/test/ruby/test_keyword.rb @@ -42,7 +42,7 @@ def test_f3 end - define_method(:f4) {|str: "foo", num: 424242| [str, num] } + define_method(:f4, &Ractor.make_shareable(proc {|str: "foo", num: 424242| [str, num] })) def test_f4 assert_equal(["foo", 424242], f4) @@ -54,7 +54,7 @@ def test_f4 end - define_method(:f5) {|str: "foo", num: 424242, **h| [str, num, h] } + define_method(:f5, &Ractor.make_shareable(proc {|str: "foo", num: 424242, **h| [str, num, h] })) def test_f5 assert_equal(["foo", 424242, {}], f5) @@ -98,9 +98,9 @@ def test_f7 # [ruby-core:41772] assert_equal([[1, 2, 3], "bar", 424242, {}], f7(1, 2, 3, str: "bar")) end - define_method(:f8) { |opt = :ion, *rest, key: :word| + define_method(:f8, &Ractor.make_shareable(proc { |opt = :ion, *rest, key: :word| [opt, rest, key] - } + })) def test_f8 assert_equal([:ion, [], :word], f8) @@ -912,6 +912,7 @@ def test_lambda_method_kwsplat_call end def test_Thread_new_kwsplat + omit "global side effects" if multiple_ractors? Thread.report_on_exception = false kw = {} h = {:a=>1} diff --git a/test/ruby/test_literal.rb b/test/ruby/test_literal.rb index dbff3c4734275d..15de867ea1d9ca 100644 --- a/test/ruby/test_literal.rb +++ b/test/ruby/test_literal.rb @@ -537,7 +537,7 @@ def test_hash_key_tampering assert_equal(100, h['a']) end - FOO = "foo" + FOO = "foo".freeze def test_hash_value_omission x = 1 diff --git a/test/ruby/test_m17n.rb b/test/ruby/test_m17n.rb index b0e2e9f849eeeb..9cc9b94dc31d1f 100644 --- a/test/ruby/test_m17n.rb +++ b/test/ruby/test_m17n.rb @@ -186,6 +186,7 @@ def test_string_inspect_invalid end def test_string_inspect_encoding + omit "suppress_warning is racy" if multiple_ractors? EnvUtil.suppress_warning do begin orig_int = Encoding.default_internal @@ -246,6 +247,7 @@ def test_utf_without_bom_valid end def test_object_utf16_32_inspect + omit "suppress_warning is racy" if multiple_ractors? EnvUtil.suppress_warning do begin orig_int = Encoding.default_internal diff --git a/test/ruby/test_m17n_comb.rb b/test/ruby/test_m17n_comb.rb index e48a1948beaa1c..2a554457874b0f 100644 --- a/test/ruby/test_m17n_comb.rb +++ b/test/ruby/test_m17n_comb.rb @@ -25,7 +25,7 @@ def assert_strenc(bytes, enc, actual, message=nil) assert_equal(b(bytes), b(actual), message) end - STRINGS = [ + STRINGS = Ractor.make_shareable([ b(""), e(""), s(""), u(""), b("a"), e("a"), s("a"), u("a"), b("."), e("."), s("."), u("."), @@ -53,13 +53,13 @@ def assert_strenc(bytes, enc, actual, message=nil) # for transitivity test u("\xe0\xa0\xa1"), e("\xe0\xa0\xa1"), s("\xe0\xa0\xa1"), # [ruby-dev:32693] e("\xa1\xa1"), b("\xa1\xa1"), s("\xa1\xa1"), # [ruby-dev:36484] - ] + ]) - WSTRINGS = [ + WSTRINGS = Ractor.make_shareable([ "aa".force_encoding("utf-16be"), "aaaa".force_encoding("utf-32be"), "aaa".force_encoding("utf-32be"), - ] + ]) def combination(*args, &b) AllPairs.each(*args, &b) @@ -177,12 +177,12 @@ def each_slice_call } end - ASCII_INCOMPATIBLE_ENCODINGS = %w[ + ASCII_INCOMPATIBLE_ENCODINGS = Ractor.make_shareable(%w[ UTF-16BE UTF-16LE UTF-32BE UTF-32LE - ] + ]) def str_enc_compatible?(*strs) encs = [] ascii_incompatible_encodings = {} diff --git a/test/ruby/test_marshal.rb b/test/ruby/test_marshal.rb index eb669948017d98..3155cda8097016 100644 --- a/test/ruby/test_marshal.rb +++ b/test/ruby/test_marshal.rb @@ -72,23 +72,27 @@ def test_marshal_cloned_class end def test_inconsistent_struct - TestMarshal.const_set :StructOrNot, Struct.new(:a) - s = Marshal.dump(StructOrNot.new(1)) - TestMarshal.instance_eval { remove_const :StructOrNot } - TestMarshal.const_set :StructOrNot, Class.new + const_name = "StructOrNot#{Ractor.current.object_id}".to_sym + TestMarshal.const_set const_name, Struct.new(:a) + s = Marshal.dump(TestMarshal.const_get(const_name).new(1)) + TestMarshal.instance_eval { remove_const const_name } + TestMarshal.const_set const_name, Class.new assert_raise(TypeError, "[ruby-dev:31709]") { Marshal.load(s) } ensure - TestMarshal.instance_eval { remove_const :StructOrNot } + TestMarshal.instance_eval { remove_const const_name } end def test_struct_invalid_members - TestMarshal.const_set :StructInvalidMembers, Struct.new(:a) - assert_raise(TypeError, "[ruby-dev:31759]") { - Marshal.load("\004\bIc&TestMarshal::StructInvalidMembers\006:\020__members__\"\bfoo") - TestMarshal::StructInvalidMembers.members - } - ensure - TestMarshal.instance_eval { remove_const :StructInvalidMembers } + omit "global side effects" if multiple_ractors? + begin + TestMarshal.const_set :StructInvalidMembers, Struct.new(:a) + assert_raise(TypeError, "[ruby-dev:31759]") { + Marshal.load("\004\bIc&TestMarshal::StructInvalidMembers\006:\020__members__\"\bfoo") + TestMarshal::StructInvalidMembers.members + } + ensure + TestMarshal.instance_eval { remove_const :StructInvalidMembers } + end end def test_load_range_as_struct @@ -187,6 +191,8 @@ def test_modify_array_during_dump end def test_change_class_name + omit "global side effects" if multiple_ractors? + run_ensure = true self.class.__send__(:remove_const, :C3) if self.class.const_defined?(:C3) eval("class C3; def _dump(s); 'foo'; end; end") m = Marshal.dump(C3.new) @@ -195,10 +201,14 @@ def test_change_class_name eval("C3 = nil") assert_raise(TypeError) { Marshal.load(m) } ensure - self.class.__send__(:remove_const, :C3) if self.class.const_defined?(:C3) + if run_ensure + self.class.__send__(:remove_const, :C3) if self.class.const_defined?(:C3) + end end def test_change_struct + omit "global side effects" if multiple_ractors? + run_ensure = true self.class.__send__(:remove_const, :C3) if self.class.const_defined?(:C3) eval("C3 = Struct.new(:foo, :bar)") m = Marshal.dump(C3.new("FOO", "BAR")) @@ -209,7 +219,9 @@ def test_change_struct eval("C3 = Struct.new(:foo, :baz)") assert_raise(TypeError) { Marshal.load(m) } ensure - self.class.__send__(:remove_const, :C3) if self.class.const_defined?(:C3) + if run_ensure + self.class.__send__(:remove_const, :C3) if self.class.const_defined?(:C3) + end end class C4 @@ -334,11 +346,11 @@ def test_regexp2 class DumpTest def marshal_dump - @@block.call(:marshal_dump) + @block.call(:marshal_dump) end def dump_each(&block) - @@block = block + @block = block Marshal.dump(self) end end @@ -357,6 +369,7 @@ def self.load_each(m, &block) end def test_context_switch + omit "access class variables" if non_main_ractor? o = DumpTest.new e = o.enum_for(:dump_each) assert_equal(:marshal_dump, e.next) @@ -404,14 +417,14 @@ def test_marshal_dump class C6 def initialize - @stdin = STDIN + @stdin = $stdin end attr_reader :stdin def marshal_dump 1 end def marshal_load(x) - @stdin = STDIN + @stdin = $stdin end end def test_marshal_dump_extra_iv @@ -421,7 +434,7 @@ def test_marshal_dump_extra_iv m = Marshal.dump(o) } o2 = Marshal.load(m) - assert_equal(STDIN, o2.stdin) + assert_equal($stdin, o2.stdin) end def test_marshal_string_encoding @@ -662,28 +675,28 @@ def test_continuation end def test_undumpable_message - c = Module.new {break module_eval("class IO\u{26a1} < IO;self;end")} - assert_raise_with_message(TypeError, /IO\u{26a1}/) { + c = Module.new {break module_eval("class IO#{Ractor.current.object_id}\u{26a1} < IO;self;end")} + assert_raise_with_message(TypeError, /IO#{Ractor.current.object_id}\u{26a1}/) { Marshal.dump(c.new(0, autoclose: false)) } end def test_undumpable_data - c = Module.new {break module_eval("class T\u{23F0 23F3} do + MethodInMethodClass_Setup = Ractor.make_shareable(proc do remove_const :MethodInMethodClass if defined? MethodInMethodClass class MethodInMethodClass @@ -1568,7 +1576,7 @@ def m2 end private end - end + end) def test_method_in_method_visibility_should_be_public MethodInMethodClass_Setup.call @@ -1724,6 +1732,7 @@ def test_umethod_bind_call end def test_method_list + pend "ObjectSpace.each_object doesn't work with ractors right now" unless main_ractor? # chkbuild lists all methods. # The following code emulate this listing. diff --git a/test/ruby/test_module.rb b/test/ruby/test_module.rb index 9a21113fe06741..c8461ce180e105 100644 --- a/test/ruby/test_module.rb +++ b/test/ruby/test_module.rb @@ -87,13 +87,13 @@ def user3 private :user3 end - OtherSetup = -> do + OtherSetup = Ractor.make_shareable(proc do remove_const :Other if defined? ::TestModule::Other module Other def other end end - end + end) class AClass def AClass.cm1 @@ -225,6 +225,7 @@ def test_ancestors @@class_eval = 'b' def test_class_eval + omit "class variable access" if non_main_ractor? OtherSetup.call Other.class_eval("CLASS_EVAL = 1") @@ -260,7 +261,7 @@ def test_const_defined? assert_raise(EncodingError) do Math.const_defined?("\xC3") end - end + end unless multiple_ractors? end def each_bad_constants(m, &b) @@ -309,6 +310,7 @@ def n.count; @count; end end def test_nested_get + omit "global side effects" if multiple_ractors? OtherSetup.call assert_equal Other, Object.const_get([self.class, 'Other'].join('::')) @@ -319,6 +321,7 @@ def test_nested_get end def test_nested_get_symbol + omit "global side effects" if multiple_ractors? OtherSetup.call const = [self.class, Other].join('::').to_sym @@ -347,6 +350,7 @@ def test_nested_get_bad_class end def test_nested_defined + omit "global side effects" if multiple_ractors? OtherSetup.call assert_send([Object, :const_defined?, [self.class.name, 'Other'].join('::')]) @@ -356,6 +360,7 @@ def test_nested_defined end def test_nested_defined_symbol + omit "global side effects" if multiple_ractors? OtherSetup.call const = [self.class, Other].join('::').to_sym @@ -383,6 +388,7 @@ def test_nested_defined_bad_class end def test_const_set + omit "class ivars" if non_main_ractor? OtherSetup.call assert_not_operator(Other, :const_defined?, :KOALA) @@ -426,6 +432,7 @@ def test_initialize_copy end def test_initialize_copy_empty + omit "module instance variable access" if non_main_ractor? m = Module.new do def x end @@ -471,6 +478,7 @@ def initialize(key:) end def test_module_subclass_initialize + omit "module instance variable access" if non_main_ractor? mod = Bug18185.new c = Class.new(Bug18185::Foo) do include mod @@ -493,6 +501,7 @@ def test_module_collected_extended_object end def test_dup + omit "global side effects" if multiple_ractors? OtherSetup.call bug6454 = '[ruby-core:45132]' @@ -850,8 +859,9 @@ def test_method_defined_without_include_super assert User.method_defined?(:user, false) assert !User.method_defined?(:mixin, false) assert Mixin.method_defined?(:mixin, false) + const_name = "FOO#{Ractor.current.object_id}" - User.const_set(:FOO, c = Class.new) + User.const_set(const_name, c = Class.new) c.prepend(User) assert !c.method_defined?(:user, false) @@ -868,7 +878,7 @@ def test_method_defined_without_include_super # cleanup User.class_eval do - remove_const :FOO + remove_const const_name end end @@ -882,6 +892,7 @@ def module_exec_aux_2(&block) end def test_module_exec + omit "global side effects" if multiple_ractors? User.module_exec do def dynamically_added_method_1; end end @@ -911,6 +922,7 @@ def dynamically_added_method_4; end end def test_module_eval + omit "global side effects" if multiple_ractors? User.module_eval("MODULE_EVAL = 1") assert_equal(1, User::MODULE_EVAL) assert_include(User.constants, :MODULE_EVAL) @@ -960,15 +972,16 @@ def test_classpath assert_match(/::N$/, m::N.name) assert_match(/\A#::O\z/, m::O.name) assert_match(/\A#::C\z/, m::C.name) - self.class.const_set(:M, m) - prefix = self.class.name + "::M::" + m_name = "M#{Ractor.current.object_id}" + self.class.const_set(m_name, m) + prefix = self.class.name + "::#{m_name}::" assert_equal(prefix+"N", m.const_get(:N).name) assert_equal(prefix+"O", m.const_get(:O).name) assert_equal(prefix+"C", m.const_get(:C).name) c = m.class_eval("Bug15891 = Class.new.freeze") assert_equal(prefix+"Bug15891", c.name) ensure - self.class.class_eval {remove_const(:M)} + self.class.class_eval {remove_const(m_name)} end def test_private_class_method @@ -1124,6 +1137,7 @@ def bar; end end def test_s_constants + omit "global side effects" unless main_ractor? c1 = Module.constants Object.module_eval "WALTER = 99" c2 = Module.constants @@ -1164,6 +1178,7 @@ module M2 end def test_s_nesting + omit "global variable access" if non_main_ractor? assert_equal([], $m0) assert_equal([TestModule::M1, TestModule], $m1) assert_equal([TestModule::M1::M2, @@ -1195,6 +1210,7 @@ def foo; end end def test_attr_obsoleted_flag + omit "class ivars" if non_main_ractor? c = Class.new do extend Test::Unit::Assertions extend Test::Unit::CoreAssertions @@ -1217,6 +1233,7 @@ def initialize end def test_attr_public_at_toplevel + omit "TOPLEVEL_BINDING" if non_main_ractor? s = Object.new TOPLEVEL_BINDING.eval(<<-END).call(s.singleton_class) proc do |c| @@ -1291,8 +1308,11 @@ def test_const_set_invalid_name assert_raise(NameError) { c1.const_set("X\u{3042}".encode("utf-16le"), :foo) } assert_raise(NameError) { c1.const_set("X\u{3042}".encode("utf-32be"), :foo) } assert_raise(NameError) { c1.const_set("X\u{3042}".encode("utf-32le"), :foo) } + cx = EnvUtil.labeled_class("X\u{3042}") - assert_raise_with_message(TypeError, /X\u{3042}/) { c1.const_set(cx, :foo) } + EnvUtil.with_default_internal(Encoding::UTF_8) do + assert_raise_with_message(TypeError, /X\u{3042}/) { c1.const_set(cx, :foo) } + end end def test_const_get_invalid_name @@ -1363,6 +1383,7 @@ module X; end end def test_class_variable_get + omit "class variables" if non_main_ractor? c = Class.new c.class_eval('@@foo = :foo') assert_equal(:foo, c.class_variable_get(:@@foo)) @@ -1381,6 +1402,7 @@ def n.count; @count; end end def test_class_variable_set + omit "class variables" if non_main_ractor? c = Class.new c.class_variable_set(:@@foo, :foo) assert_equal(:foo, c.class_eval('@@foo')) @@ -1399,6 +1421,7 @@ def n.count; @count; end end def test_class_variable_defined + omit "class variables" if non_main_ractor? c = Class.new c.class_eval('@@foo = :foo') assert_equal(true, c.class_variable_defined?(:@@foo)) @@ -1416,6 +1439,7 @@ def n.count; @count; end end def test_remove_class_variable + omit "class variables" if non_main_ractor? c = Class.new c.class_eval('@@foo = :foo') c.class_eval { remove_class_variable(:@@foo) } @@ -1742,18 +1766,20 @@ def test_send def test_nonascii_name - c = eval("class ::C\u{df}; self; end") - assert_equal("C\u{df}", c.name, '[ruby-core:24600]') - c = eval("class C\u{df}; self; end") - assert_equal("TestModule::C\u{df}", c.name, '[ruby-core:24600]') + c_name = "C#{Ractor.current.object_id}" + c = eval("class ::#{c_name}\u{df}; self; end") + assert_equal("#{c_name}\u{df}", c.name, '[ruby-core:24600]') + c = eval("class #{c_name}\u{df}; self; end") + assert_equal("TestModule::#{c_name}\u{df}", c.name, '[ruby-core:24600]') c = Module.new.module_eval("class X\u{df} < Module; self; end") assert_match(/::X\u{df}:/, c.new.to_s) ensure - Object.send(:remove_const, "C\u{df}") + Object.send(:remove_const, "#{c_name}\u{df}") end def test_const_added + omit "class ivars" if non_main_ractor? eval(<<~RUBY) module TestConstAdded @memo = [] @@ -1993,6 +2019,7 @@ def foo end def test_uninitialized_toplevel_constant + omit "TOPLEVEL_BINDING" if non_main_ractor? bug3123 = '[ruby-dev:40951]' e = assert_raise(NameError) {eval("Bug3123", TOPLEVEL_BINDING)} assert_not_match(/Object::/, e.message, bug3123) @@ -2021,7 +2048,7 @@ def test_attr_writer_with_no_arguments def test_private_constant_in_class c = Class.new - c.const_set(:FOO, "foo") + c.const_set(:FOO, "foo".freeze) assert_equal("foo", c::FOO) c.private_constant(:FOO) e = assert_raise(NameError) {c::FOO} @@ -2030,7 +2057,7 @@ def test_private_constant_in_class assert_equal("foo", c.class_eval("FOO")) assert_equal("foo", c.const_get("FOO")) $VERBOSE, verbose = nil, $VERBOSE - c.const_set(:FOO, "foo") + c.const_set(:FOO, "foo".freeze) $VERBOSE = verbose e = assert_raise(NameError) {c::FOO} assert_equal(c, e.receiver) @@ -2044,7 +2071,7 @@ def test_private_constant_in_class def test_private_constant_in_module m = Module.new - m.const_set(:FOO, "foo") + m.const_set(:FOO, "foo".freeze) assert_equal("foo", m::FOO) m.private_constant(:FOO) e = assert_raise(NameError) {m::FOO} @@ -2053,7 +2080,7 @@ def test_private_constant_in_module assert_equal("foo", m.class_eval("FOO")) assert_equal("foo", m.const_get("FOO")) $VERBOSE, verbose = nil, $VERBOSE - m.const_set(:FOO, "foo") + m.const_set(:FOO, "foo".freeze) $VERBOSE = verbose e = assert_raise(NameError) {m::FOO} assert_equal(m, e.receiver) @@ -2072,8 +2099,8 @@ def test_private_constant_in_module def test_private_constant2 c = Class.new - c.const_set(:FOO, "foo") - c.const_set(:BAR, "bar") + c.const_set(:FOO, "foo".freeze) + c.const_set(:BAR, "bar".freeze) assert_equal("foo", c::FOO) assert_equal("bar", c::BAR) c.private_constant(:FOO, :BAR) @@ -2093,6 +2120,7 @@ class X end def test_private_constant_const_missing + omit "can't access ivars of singleton class" if non_main_ractor? c = Class.new c.const_set(:FOO, "foo") c.private_constant(:FOO) @@ -2112,21 +2140,22 @@ class PrivateClass private_constant :PrivateClass def test_define_module_under_private_constant + const_name = "TestModule#{Ractor.current.object_id}" assert_raise(NameError) do eval %q{class TestModule::PrivateClass; end} end assert_raise(NameError) do - eval %q{module TestModule::PrivateClass::TestModule; end} + eval %Q{module TestModule::PrivateClass::#{const_name}; end} end eval %q{class PrivateClass; end} - eval %q{module PrivateClass::TestModule; end} - assert_instance_of(Module, PrivateClass::TestModule) - PrivateClass.class_eval { remove_const(:TestModule) } + eval %Q{module PrivateClass::#{const_name}; end} + assert_instance_of(Module, PrivateClass.const_get(const_name)) + PrivateClass.class_eval { remove_const(const_name) } end def test_public_constant c = Class.new - c.const_set(:FOO, "foo") + c.const_set(:FOO, "foo".freeze) assert_equal("foo", c::FOO) c.private_constant(:FOO) assert_raise(NameError) { c::FOO } @@ -2136,8 +2165,9 @@ def test_public_constant end def test_deprecate_constant + omit "Setting Warning[]" if multiple_ractors? c = Class.new - c.const_set(:FOO, "foo") + c.const_set(:FOO, "foo".freeze) c.deprecate_constant(:FOO) assert_warn(/deprecated/) do Warning[:deprecated] = true @@ -2802,6 +2832,7 @@ def wrapped end def test_class_variables + omit "class variable access" if non_main_ractor? m = Module.new m.class_variable_set(:@@foo, 1) m2 = Module.new @@ -2814,6 +2845,7 @@ def test_class_variables end def test_class_variable_in_dup_class + omit "class variable access" if non_main_ractor? a = Class.new do @@a = 'A' def a=(x) @@ -2829,9 +2861,10 @@ def a assert_equal 'A', a.new.a, '[ruby-core:17019]' end - Bug6891 = '[ruby-core:47241]' + Bug6891 = '[ruby-core:47241]'.freeze def test_extend_module_with_protected_method + omit "class ivars" if non_main_ractor? list = [] x = Class.new { @@ -2944,6 +2977,7 @@ def test_uninitialized_attr end def test_uninitialized_attr_class + omit "class ivars" if non_main_ractor? assert_warning '' do assert_nil(AttrTest.cattr) end @@ -3002,6 +3036,7 @@ module PrivateConstantReopen end def test_private_constant_reopen + omit "TOPLEVEL_BINDING" if non_main_ractor? assert_raise(NameError) do eval <<-EOS, TOPLEVEL_BINDING module TestModule::PrivateConstantReopen::PRIVATE_CONSTANT @@ -3246,7 +3281,7 @@ def foo; bar; end } end - ConstLocation = [__FILE__, __LINE__] + ConstLocation = Ractor.make_shareable([__FILE__, __LINE__]) def test_const_source_location assert_equal(ConstLocation, self.class.const_source_location(:ConstLocation)) diff --git a/test/ruby/test_namespace.rb b/test/ruby/test_namespace.rb index cd593068675de6..1bfef49dd8ca30 100644 --- a/test/ruby/test_namespace.rb +++ b/test/ruby/test_namespace.rb @@ -472,6 +472,7 @@ def test_add_constants_in_namespace end def test_global_variables + omit "global variable access" if non_main_ractor? default_l = $-0 default_f = $, @@ -509,7 +510,7 @@ def test_global_variables EnvUtil.suppress_warning do $-0 = default_l $, = default_f - end + end if main_ractor? end def test_load_path_and_loaded_features diff --git a/test/ruby/test_numeric.rb b/test/ruby/test_numeric.rb index cf408fac0af411..3bf93ef20dc0bd 100644 --- a/test/ruby/test_numeric.rb +++ b/test/ruby/test_numeric.rb @@ -18,20 +18,24 @@ def test_coerce assert_raise_with_message(TypeError, /can't be coerced into /) {1|:foo} assert_raise_with_message(TypeError, /can't be coerced into /) {1^:foo} - assert_raise_with_message(TypeError, /:\u{3042}/) {1+:"\u{3042}"} - assert_raise_with_message(TypeError, /:\u{3042}/) {1&:"\u{3042}"} - assert_raise_with_message(TypeError, /:\u{3042}/) {1|:"\u{3042}"} - assert_raise_with_message(TypeError, /:\u{3042}/) {1^:"\u{3042}"} + EnvUtil.with_default_internal(Encoding::UTF_8) do + assert_raise_with_message(TypeError, /:\u{3042}/) {1+:"\u{3042}"} + assert_raise_with_message(TypeError, /:\u{3042}/) {1&:"\u{3042}"} + assert_raise_with_message(TypeError, /:\u{3042}/) {1|:"\u{3042}"} + assert_raise_with_message(TypeError, /:\u{3042}/) {1^:"\u{3042}"} + + assert_raise_with_message(TypeError, /:\u{3044}/) {1+"\u{3044}".to_sym} + assert_raise_with_message(TypeError, /:\u{3044}/) {1&"\u{3044}".to_sym} + assert_raise_with_message(TypeError, /:\u{3044}/) {1|"\u{3044}".to_sym} + assert_raise_with_message(TypeError, /:\u{3044}/) {1^"\u{3044}".to_sym} + end + EnvUtil.with_default_internal(Encoding::US_ASCII) do assert_raise_with_message(TypeError, /:"\\u3042"/) {1+:"\u{3042}"} assert_raise_with_message(TypeError, /:"\\u3042"/) {1&:"\u{3042}"} assert_raise_with_message(TypeError, /:"\\u3042"/) {1|:"\u{3042}"} assert_raise_with_message(TypeError, /:"\\u3042"/) {1^:"\u{3042}"} end - assert_raise_with_message(TypeError, /:\u{3044}/) {1+"\u{3044}".to_sym} - assert_raise_with_message(TypeError, /:\u{3044}/) {1&"\u{3044}".to_sym} - assert_raise_with_message(TypeError, /:\u{3044}/) {1|"\u{3044}".to_sym} - assert_raise_with_message(TypeError, /:\u{3044}/) {1^"\u{3044}".to_sym} bug10711 = '[ruby-core:67405] [Bug #10711]' exp = "1.2 can't be coerced into Integer" diff --git a/test/ruby/test_object.rb b/test/ruby/test_object.rb index 9074e54df5ed50..f9c7c006e93738 100644 --- a/test/ruby/test_object.rb +++ b/test/ruby/test_object.rb @@ -339,6 +339,9 @@ def test_remove_instance_variable 'T_CLASS,T_MODULE' => Class.new(Object), 'generic ivar' => '', }.each do |desc, o| + if o.is_a?(Class) && non_main_ractor? + next + end e = assert_raise(NameError, "#{desc} iv removal raises before set") do o.remove_instance_variable(:@foo) end @@ -373,14 +376,14 @@ def c = @c o1.instance_variable_set(:@a, 0) o1.instance_variable_set(:@b, 1) o1.instance_variable_set(:@c, 2) - refute_includes ObjectSpace.dump(o1), '"embedded":true' + refute_includes ObjectSpace.dump(o1), '"embedded":true' if main_ractor? o1.remove_instance_variable(:@foo) - assert_includes ObjectSpace.dump(o1), '"embedded":true' + assert_includes ObjectSpace.dump(o1), '"embedded":true' if main_ractor? o2.instance_variable_set(:@a, 0) o2.instance_variable_set(:@b, 1) o2.instance_variable_set(:@c, 2) - assert_includes ObjectSpace.dump(o2), '"embedded":true' + assert_includes ObjectSpace.dump(o2), '"embedded":true' if main_ractor? assert_equal(0, o1.a) assert_equal(1, o1.b) @@ -1056,7 +1059,7 @@ def test_bad_initialize_copy assert_not_initialize_copy {Enumerator::Yielder.new {}} assert_not_initialize_copy {File.stat(__FILE__)} assert_not_initialize_copy {open(__FILE__)}.each(&:close) - assert_not_initialize_copy {ARGF.class.new} + assert_not_initialize_copy {ARGF.class.new} if main_ractor? assert_not_initialize_copy {Random.new} assert_not_initialize_copy {//} assert_not_initialize_copy {/.*/.match("foo")} diff --git a/test/ruby/test_object_id.rb b/test/ruby/test_object_id.rb index adb819febce57c..368826480ca233 100644 --- a/test/ruby/test_object_id.rb +++ b/test/ruby/test_object_id.rb @@ -12,6 +12,7 @@ def test_dup_new_id end def test_dup_with_ivar_and_id + omit "class ivars" if @obj.is_a?(Module) && !main_ractor? id = @obj.object_id @obj.instance_variable_set(:@foo, 42) @@ -21,6 +22,7 @@ def test_dup_with_ivar_and_id end def test_dup_with_id_and_ivar + omit "class ivars" if @obj.is_a?(Module) && !main_ractor? @obj.instance_variable_set(:@foo, 42) id = @obj.object_id @@ -30,6 +32,7 @@ def test_dup_with_id_and_ivar end def test_dup_with_id_and_ivar_and_frozen + omit "class ivars" if @obj.is_a?(Module) && !main_ractor? @obj.instance_variable_set(:@foo, 42) @obj.freeze id = @obj.object_id @@ -46,6 +49,7 @@ def test_clone_new_id end def test_clone_with_ivar_and_id + omit "class ivars" if @obj.is_a?(Module) && !main_ractor? id = @obj.object_id @obj.instance_variable_set(:@foo, 42) @@ -55,6 +59,7 @@ def test_clone_with_ivar_and_id end def test_clone_with_id_and_ivar + omit "class ivars" if @obj.is_a?(Module) && !main_ractor? @obj.instance_variable_set(:@foo, 42) id = @obj.object_id @@ -64,6 +69,7 @@ def test_clone_with_id_and_ivar end def test_clone_with_id_and_ivar_and_frozen + omit "class ivars" if @obj.is_a?(Module) && !main_ractor? @obj.instance_variable_set(:@foo, 42) @obj.freeze id = @obj.object_id @@ -76,6 +82,7 @@ def test_clone_with_id_and_ivar_and_frozen def test_marshal_new_id return pass if @obj.is_a?(Module) + omit "class ivars" if @obj.is_a?(Module) && !main_ractor? id = @obj.object_id refute_equal id, Marshal.load(Marshal.dump(@obj)).object_id @@ -117,6 +124,7 @@ def test_marshal_with_id_and_ivar_and_frozen end def test_object_id_need_resize + omit "class ivars" if !main_ractor? && @obj.is_a?(Module) (3 - @obj.instance_variables.size).times do |i| @obj.instance_variable_set("@a_#{i}", "[Bug #21445]") end @@ -165,6 +173,7 @@ class TooComplex < Module end def setup + omit "class ivars" unless main_ractor? if defined?(RubyVM::Shape::SHAPE_MAX_VARIATIONS) assert_equal 8, RubyVM::Shape::SHAPE_MAX_VARIATIONS end diff --git a/test/ruby/test_objectspace.rb b/test/ruby/test_objectspace.rb index a479547599a03a..be8c6138a14682 100644 --- a/test/ruby/test_objectspace.rb +++ b/test/ruby/test_objectspace.rb @@ -7,10 +7,11 @@ def self.deftest_id2ref(obj) file = $` line = $1.to_i code = <<"End" - define_method("test_id2ref_#{line}") {\ + define_method("test_id2ref_#{line}", &Ractor.make_shareable(proc {\ + omit "id2ref" if non_main_ractor? o = EnvUtil.suppress_warning { ObjectSpace._id2ref(obj.object_id) } assert_same(obj, o, "didn't round trip: \#{obj.inspect}");\ - } + })) End eval code, binding, file, line end @@ -29,7 +30,7 @@ def self.deftest_id2ref(obj) deftest_id2ref(:a) deftest_id2ref(:abcdefghijilkjl) deftest_id2ref(:==) - deftest_id2ref(Object.new) + deftest_id2ref(Object.new.freeze) deftest_id2ref(self) deftest_id2ref(true) deftest_id2ref(false) @@ -56,6 +57,7 @@ def test_id2ref_liveness end def test_id2ref_invalid_argument + omit "id2ref" if non_main_ractor? msg = /no implicit conversion/ assert_raise_with_message(TypeError, msg) { EnvUtil.suppress_warning { ObjectSpace._id2ref(nil) } } assert_raise_with_message(TypeError, msg) { EnvUtil.suppress_warning { ObjectSpace._id2ref(false) } } @@ -66,6 +68,7 @@ def test_id2ref_invalid_argument end def test_id2ref_invalid_symbol_id + omit "id2ref" if non_main_ractor? # RB_STATIC_SYM_P checks for static symbols by checking that the bottom # 8 bits of the object is equal to RUBY_SYMBOL_FLAG, so we need to make # sure that the bottom 8 bits remain unchanged. @@ -74,6 +77,7 @@ def test_id2ref_invalid_symbol_id end def test_count_objects + omit "count_objects" if non_main_ractor? h = {} ObjectSpace.count_objects(h) assert_kind_of(Hash, h) @@ -235,6 +239,7 @@ def test_finalizer_thread_raise end def test_each_object + omit "each_object" if non_main_ractor? klass = Class.new new_obj = klass.new @@ -248,6 +253,7 @@ def test_each_object end def test_each_object_enumerator + omit "each_object" if non_main_ractor? klass = Class.new new_obj = klass.new diff --git a/test/ruby/test_optimization.rb b/test/ruby/test_optimization.rb index e39eafa5e50bb9..98732e5e9c6977 100644 --- a/test/ruby/test_optimization.rb +++ b/test/ruby/test_optimization.rb @@ -252,6 +252,7 @@ def test_trace_optimized_methods end def test_string_freeze_saves_memory + pend "ObjectSpace.memsize_of" if non_main_ractor? # TODO: memsize_of should be safe n = 16384 data = '.'.freeze r, w = IO.pipe @@ -396,6 +397,7 @@ def self.tailcall(klass, src, file = nil, path = nil, line = nil, tailcall: true end def tailcall(*args) + pend "tailcall" if non_main_ractor? self.class.tailcall(singleton_class, *args) end @@ -519,6 +521,7 @@ def post_arg(_a = 1, _b) = ret_const end def test_tailcall_interrupted_by_sigint + omit "in a subprocess" if non_main_ractor? bug12576 = 'ruby-core:76327' script = "#{<<-"begin;"}\n#{<<~'end;'}" begin; @@ -1222,6 +1225,7 @@ def test_opt_new_with_safe_navigation end def test_opt_new + omit "RubyVM::Iseq.compile/eval not working across multiple ractors" if multiple_ractors? pos_initialize = " def initialize a, b @a = a diff --git a/test/ruby/test_parse.rb b/test/ruby/test_parse.rb index 98e95b98afaf77..72e7c6cff7344b 100644 --- a/test/ruby/test_parse.rb +++ b/test/ruby/test_parse.rb @@ -135,6 +135,7 @@ def t.baz(*r) end def test_mlhs_node + omit "class ivars" if non_main_ractor? c = Class.new class << c attr_accessor :foo, :bar, :Foo, :Bar @@ -364,6 +365,7 @@ def test_words end def test_dstr + omit "class variables" if non_main_ractor? @@foo = 1 assert_equal("foo 1 bar", "foo #@@foo bar") "1" =~ /(.)/ @@ -897,6 +899,7 @@ def test_float end def test_global_variable + omit "global variable access" if non_main_ractor? assert_equal(nil, assert_warning(/not initialized/) {eval('$-x')}) assert_equal(nil, eval('alias $preserve_last_match $&')) assert_equal(nil, eval('alias $& $test_parse_foobarbazqux')) @@ -1136,6 +1139,7 @@ def test_unused_variable end def test_parsing_begin_statement_inside_method_definition + omit "global side effects" if multiple_ractors? assert_equal :bug_20234, eval("def (begin;end).bug_20234; end") NilClass.remove_method(:bug_20234) assert_equal :bug_20234, eval("def (begin;rescue;end).bug_20234; end") @@ -1449,11 +1453,11 @@ def test_command_def_cmdarg end; end - NONASCII_CONSTANTS = [ + NONASCII_CONSTANTS = Ractor.make_shareable([ *%W"\u{00de} \u{00C0}".flat_map {|c| [c, c.encode("iso-8859-15")]}, "\u{1c4}", "\u{1f2}", "\u{1f88}", "\u{370}", *%W"\u{391} \u{ff21}".flat_map {|c| [c, c.encode("cp932"), c.encode("euc-jp")]}, - ] + ]) def assert_nonascii_const assert_all_assertions_foreach("NONASCII_CONSTANTS", *NONASCII_CONSTANTS) do |n| @@ -1544,6 +1548,7 @@ def test_shareable_constant_value_ignored end def test_shareable_constant_value_simple + omit "can't access unshareables" if non_main_ractor? obj = [['unsharable_value']] a, b, c = eval_separately("#{<<~"begin;"}\n#{<<~'end;'}") begin; @@ -1610,6 +1615,7 @@ def test_shareable_constant_value_literal_const_refs end def test_shareable_constant_value_nested + omit "can't access unshareables" if non_main_ractor? a, b = eval_separately("#{<<~"begin;"}\n#{<<~'end;'}") begin; # shareable_constant_value: none diff --git a/test/ruby/test_pattern_matching.rb b/test/ruby/test_pattern_matching.rb index 92a3244fc2ae88..5d7efa76e2282e 100644 --- a/test/ruby/test_pattern_matching.rb +++ b/test/ruby/test_pattern_matching.rb @@ -430,19 +430,21 @@ def test_pin_operator_value_pattern end end - assert_block do - @@TestPatternMatching = /a/ - case 'abc' - in ^@@TestPatternMatching - true + if main_ractor? + assert_block do + @@TestPatternMatching = /a/ + case 'abc' + in ^@@TestPatternMatching + true + end end - end - assert_block do - $TestPatternMatching = /a/ - case 'abc' - in ^$TestPatternMatching - true + assert_block do + $TestPatternMatching = /a/ + case 'abc' + in ^$TestPatternMatching + true + end end end end @@ -883,6 +885,7 @@ def test_find_pattern end def test_hash_pattern + omit "class ivars" if non_main_ractor? assert_block do [{}, C.new({})].all? do |i| case i @@ -1324,6 +1327,7 @@ def test_deconstruct end def test_deconstruct_keys + omit "can't access class ivars" if non_main_ractor? assert_raise(TypeError) do case CTypeError.new in {} diff --git a/test/ruby/test_primitive.rb b/test/ruby/test_primitive.rb index f1db934000dc23..782c09c48dc8d3 100644 --- a/test/ruby/test_primitive.rb +++ b/test/ruby/test_primitive.rb @@ -26,7 +26,7 @@ def test_lvar assert_equal 4, c end - C_Setup = -> do + C_Setup = Ractor.make_shareable(proc do remove_const :C if defined? ::TestRubyPrimitive::C remove_const :A if defined? ::TestRubyPrimitive::A @@ -46,9 +46,10 @@ def const (1..2).map { A::B::C::Const } - end + end) def test_constant + omit "global side effects" if multiple_ractors? C_Setup.call assert_equal 1, C @@ -109,6 +110,7 @@ class A4 end def test_constant_cache3 + omit "global variable access" unless main_ractor? assert_equal 7, $test_ruby_primitive_constant_cache3 end @@ -120,6 +122,7 @@ class A5 end def test_constatant_cache4 + omit "global variable access" unless main_ractor? assert_equal 8, $test_ruby_primitive_constant_cache4 end @@ -138,10 +141,12 @@ class C6 < B6 $test_ruby_primitive_constant_cache5 = [A6.foo, B6.foo, C6.foo] def test_constant_cache5 + omit "global variable access" unless main_ractor? assert_equal [0, 1, 2], $test_ruby_primitive_constant_cache5 end def test_gvar + omit "global variable access" unless main_ractor? $test_ruby_primitive_gvar = 7 assert_equal 7, $test_ruby_primitive_gvar assert_equal 7, $test_ruby_primitive_gvar @@ -164,6 +169,7 @@ def m end def test_cvar_from_instance_method + omit "class variables" unless main_ractor? A7_Setup.call assert_equal 2, A7.new.m @@ -185,6 +191,7 @@ def m end def test_cvar_from_singleton_method + omit "class variables" unless main_ractor? A8_Setup.call assert_equal 2, A8.m @@ -204,6 +211,7 @@ def self.m end def test_cvar_from_singleton_method2 + omit "class variables" unless main_ractor? A9_Setup.call assert_equal 2, A9.m @@ -225,18 +233,20 @@ def test_opassign assert_equal 4, @iv # init @@cv - @@cv = nil - - @@cv ||= 1 - assert_equal 1, @@cv - @@cv &&= 2 - assert_equal 2, @@cv - @@cv ||= 99 - assert_equal 2, @@cv - - $gv = 3 - $gv += 4 - assert_equal 7, $gv + if main_ractor? + @@cv = nil + + @@cv ||= 1 + assert_equal 1, @@cv + @@cv &&= 2 + assert_equal 2, @@cv + @@cv ||= 99 + assert_equal 2, @@cv + + $gv = 3 + $gv += 4 + assert_equal 7, $gv + end obj = A10.new obj.a = 9 diff --git a/test/ruby/test_proc.rb b/test/ruby/test_proc.rb index 2cd97ca32464ab..f1d47195e6306e 100644 --- a/test/ruby/test_proc.rb +++ b/test/ruby/test_proc.rb @@ -172,11 +172,12 @@ def test_hash_equal assert_equal p1.hash, p2.hash - # symbol backed proc - p1 = :hello.to_proc - p2 = :hello.to_proc - - assert_equal p1.hash, p2.hash + if main_ractor? + # symbol backed proc + p1 = :hello.to_proc + p2 = :hello.to_proc + assert_equal p1.hash, p2.hash + end end def test_hash_uniqueness @@ -513,7 +514,7 @@ def test_binding_source_location file, lineno = method(:source_location_test).to_proc.binding.source_location assert_match(/^#{ Regexp.quote(__FILE__) }$/, file) - assert_equal(@@line_of_source_location_test[0], lineno, 'Bug #2427') + assert_equal(LINE_OF_SOURCE_LOCATION_TEST[0], lineno, 'Bug #2427') end def test_binding_error_unless_ruby_frame @@ -1499,7 +1500,7 @@ def test_to_s assert_include(EnvUtil.labeled_class(name, Proc).new {}.to_s, name) end - @@line_of_source_location_test = [__LINE__ + 1, 2, __LINE__ + 3, 5] + LINE_OF_SOURCE_LOCATION_TEST = [__LINE__ + 1, 2, __LINE__ + 3, 5].freeze def source_location_test a=1, b=2 end @@ -1507,16 +1508,16 @@ def source_location_test a=1, def test_source_location file, *loc = method(:source_location_test).source_location assert_match(/^#{ Regexp.quote(__FILE__) }$/, file) - assert_equal(@@line_of_source_location_test, loc, 'Bug #2427') + assert_equal(LINE_OF_SOURCE_LOCATION_TEST, loc, 'Bug #2427') file, *loc = self.class.instance_method(:source_location_test).source_location assert_match(/^#{ Regexp.quote(__FILE__) }$/, file) - assert_equal(@@line_of_source_location_test, loc, 'Bug #2427') + assert_equal(LINE_OF_SOURCE_LOCATION_TEST, loc, 'Bug #2427') end - @@line_of_attr_reader_source_location_test = __LINE__ + 3 - @@line_of_attr_writer_source_location_test = __LINE__ + 3 - @@line_of_attr_accessor_source_location_test = __LINE__ + 3 + LINE_OF_ATTR_READER_SOURCE_LOCATION_TEST = __LINE__ + 3 + LINE_OF_ATTR_WRITER_SOURCE_LOCATION_TEST = __LINE__ + 3 + LINE_OF_ATTR_ACCESSOR_SOURCE_LOCATION_TEST = __LINE__ + 3 attr_reader :attr_reader_source_location_test attr_writer :attr_writer_source_location_test attr_accessor :attr_accessor_source_location_test @@ -1524,19 +1525,19 @@ def test_source_location def test_attr_source_location file, lineno = method(:attr_reader_source_location_test).source_location assert_match(/^#{ Regexp.quote(__FILE__) }$/, file) - assert_equal(@@line_of_attr_reader_source_location_test, lineno) + assert_equal(LINE_OF_ATTR_READER_SOURCE_LOCATION_TEST, lineno) file, lineno = method(:attr_writer_source_location_test=).source_location assert_match(/^#{ Regexp.quote(__FILE__) }$/, file) - assert_equal(@@line_of_attr_writer_source_location_test, lineno) + assert_equal(LINE_OF_ATTR_WRITER_SOURCE_LOCATION_TEST, lineno) file, lineno = method(:attr_accessor_source_location_test).source_location assert_match(/^#{ Regexp.quote(__FILE__) }$/, file) - assert_equal(@@line_of_attr_accessor_source_location_test, lineno) + assert_equal(LINE_OF_ATTR_ACCESSOR_SOURCE_LOCATION_TEST, lineno) file, lineno = method(:attr_accessor_source_location_test=).source_location assert_match(/^#{ Regexp.quote(__FILE__) }$/, file) - assert_equal(@@line_of_attr_accessor_source_location_test, lineno) + assert_equal(LINE_OF_ATTR_ACCESSOR_SOURCE_LOCATION_TEST, lineno) end def block_source_location_test(*args, &block) diff --git a/test/ruby/test_process.rb b/test/ruby/test_process.rb index f1894ab0c30f8a..9982ec9e9670ea 100644 --- a/test/ruby/test_process.rb +++ b/test/ruby/test_process.rb @@ -6,14 +6,14 @@ require 'rbconfig' class TestProcess < Test::Unit::TestCase - RUBY = EnvUtil.rubybin + RUBY = EnvUtil.rubybin.freeze def setup - Process.waitall + Process.waitall unless multiple_ractors? end def teardown - Process.waitall + Process.waitall unless multiple_ractors? end def windows? @@ -24,6 +24,7 @@ def self.windows? end def with_tmpchdir + omit "Dir.chdir" if multiple_ractors? Dir.mktmpdir {|d| d = File.realpath(d) Dir.chdir(d) { @@ -33,6 +34,7 @@ def with_tmpchdir end def run_in_child(str) # should be called in a temporary directory + omit "Process.spawn" unless main_ractor? File.write("test-script", str) Process.wait spawn(RUBY, "test-script") $? @@ -114,14 +116,19 @@ def test_rlimit_name } assert_raise(ArgumentError) { Process.getrlimit(:FOO) } assert_raise(ArgumentError) { Process.getrlimit("FOO") } - assert_raise_with_message(ArgumentError, /\u{30eb 30d3 30fc}/) { Process.getrlimit("\u{30eb 30d3 30fc}") } + + EnvUtil.with_default_internal(Encoding::UTF_8) do + assert_raise_with_message(ArgumentError, /\u{30eb 30d3 30fc}/) { Process.getrlimit("\u{30eb 30d3 30fc}") } + end end def test_rlimit_value return unless rlimit_exist? assert_raise(ArgumentError) { Process.setrlimit(:FOO, 0) } assert_raise(ArgumentError) { Process.setrlimit(:CORE, :FOO) } - assert_raise_with_message(ArgumentError, /\u{30eb 30d3 30fc}/) { Process.setrlimit("\u{30eb 30d3 30fc}", 0) } + EnvUtil.with_default_internal(Encoding::UTF_8) do + assert_raise_with_message(ArgumentError, /\u{30eb 30d3 30fc}/) { Process.setrlimit("\u{30eb 30d3 30fc}", 0) } + end assert_raise_with_message(ArgumentError, /\u{30eb 30d3 30fc}/) { Process.setrlimit(:CORE, "\u{30eb 30d3 30fc}") } with_tmpchdir do s = run_in_child(<<-'End') @@ -147,9 +154,10 @@ def test_rlimit_value end end - TRUECOMMAND = [RUBY, '-e', ''] + TRUECOMMAND = Ractor.make_shareable([RUBY, '-e', '']) def test_execopts_opts + omit "spawn" unless main_ractor? assert_nothing_raised { Process.wait Process.spawn(*TRUECOMMAND, {}) } @@ -163,6 +171,7 @@ def test_execopts_opts def test_execopts_pgroup omit "system(:pgroup) is not supported" if windows? + omit "system" unless main_ractor? assert_nothing_raised { system(*TRUECOMMAND, :pgroup=>false) } io = IO.popen([RUBY, "-e", "print Process.getpgrp"]) @@ -191,6 +200,7 @@ def test_execopts_pgroup end def test_execopts_rlimit + omit "IO.popen" unless main_ractor? return unless rlimit_exist? assert_raise(ArgumentError) { system(*TRUECOMMAND, :rlimit_foo=>0) } assert_raise(ArgumentError) { system(*TRUECOMMAND, :rlimit_NOFILE=>0) } @@ -290,9 +300,10 @@ def test_overwrite_ENV if e = RbConfig::CONFIG['PRELOADENV'] and !e.empty? MANDATORY_ENVS << e end - PREENVARG = ['-e', "%w[#{MANDATORY_ENVS.join(' ')}].each{|e|ENV.delete(e)}"] - ENVARG = ['-e', 'ENV.each {|k,v| puts "#{k}=#{v}" }'] - ENVCOMMAND = [RUBY].concat(PREENVARG).concat(ENVARG) + Ractor.make_shareable(MANDATORY_ENVS) + PREENVARG = Ractor.make_shareable(['-e', "%w[#{MANDATORY_ENVS.join(' ')}].each{|e|ENV.delete(e)}"]) + ENVARG = Ractor.make_shareable(['-e', 'ENV.each {|k,v| puts "#{k}=#{v}" }']) + ENVCOMMAND = Ractor.make_shareable([RUBY].concat(PREENVARG).concat(ENVARG)) def test_execopts_env assert_raise(ArgumentError) { @@ -331,7 +342,7 @@ def test_execopts_env } with_tmpchdir {|d| - system({"fofo"=>"haha"}, *ENVCOMMAND, STDOUT=>"out") + system({"fofo"=>"haha"}, *ENVCOMMAND, $stdout=>"out") assert_match(/^fofo=haha$/, File.read("out").chomp) } @@ -362,6 +373,7 @@ def test_execopts_env end def test_execopt_env_path + omit "spawn" unless main_ractor? bug8004 = '[ruby-core:53103] [Bug #8004]' Dir.mktmpdir do |d| File.write("#{d}/tmp_script.cmd", ": ;\n", perm: 0o755) @@ -372,6 +384,7 @@ def test_execopt_env_path end def _test_execopts_env_popen(cmd) + omit "ENV change" if multiple_ractors? message = cmd.inspect IO.popen({"FOO"=>"BAR"}, cmd) {|io| assert_equal('FOO=BAR', io.read[/^FOO=.*/], message) @@ -440,6 +453,7 @@ def test_execopts_env_single_word end def test_execopts_unsetenv_others + omit "ENV change" if multiple_ractors? h = {} MANDATORY_ENVS.each {|k| e = ENV[k] and h[k] = e} IO.popen([h, *ENVCOMMAND, :unsetenv_others=>true]) {|io| @@ -450,7 +464,7 @@ def test_execopts_unsetenv_others } end - PWD = [RUBY, '-e', 'puts Dir.pwd'] + PWD = Ractor.make_shareable([RUBY, '-e', 'puts Dir.pwd']) def test_execopts_chdir with_tmpchdir {|d| @@ -506,7 +520,7 @@ def test_execopts_open_failure } end - UMASK = [RUBY, '-e', 'printf "%04o\n", File.umask'] + UMASK = Ractor.make_shareable([RUBY, '-e', 'printf "%04o\n", File.umask']) def test_execopts_umask omit "umask is not supported" if windows? @@ -543,49 +557,49 @@ def with_pipes(n) end end - ECHO = lambda {|arg| [RUBY, '-e', "puts #{arg.dump}; STDOUT.flush"] } - SORT = [RUBY, '-e', "puts ARGF.readlines.sort"] - CAT = [RUBY, '-e', "IO.copy_stream STDIN, STDOUT"] + ECHO = Ractor.make_shareable(lambda {|arg| [RUBY, '-e', "puts #{arg.dump}; $stdout.flush"] }) + SORT = Ractor.make_shareable([RUBY, '-e', "puts ARGF.readlines.sort"]) + CAT = Ractor.make_shareable([RUBY, '-e', "IO.copy_stream $stdin, $stdout"]) def test_execopts_redirect_fd with_tmpchdir {|d| - Process.wait Process.spawn(*ECHO["a"], STDOUT=>["out", File::WRONLY|File::CREAT|File::TRUNC, 0644]) + Process.wait Process.spawn(*ECHO["a"], $stdout=>["out", File::WRONLY|File::CREAT|File::TRUNC, 0644]) assert_equal("a", File.read("out").chomp) if windows? # currently telling to child the file modes is not supported. File.write("out", "0\n", mode: "a") else - Process.wait Process.spawn(*ECHO["0"], STDOUT=>["out", File::WRONLY|File::CREAT|File::APPEND, 0644]) + Process.wait Process.spawn(*ECHO["0"], $stdout=>["out", File::WRONLY|File::CREAT|File::APPEND, 0644]) assert_equal("a\n0\n", File.read("out")) end - Process.wait Process.spawn(*SORT, STDIN=>["out", File::RDONLY, 0644], - STDOUT=>["out2", File::WRONLY|File::CREAT|File::TRUNC, 0644]) + Process.wait Process.spawn(*SORT, $stdin=>["out", File::RDONLY, 0644], + $stdout=>["out2", File::WRONLY|File::CREAT|File::TRUNC, 0644]) assert_equal("0\na\n", File.read("out2")) - Process.wait Process.spawn(*ECHO["b"], [STDOUT, STDERR]=>["out", File::WRONLY|File::CREAT|File::TRUNC, 0644]) + Process.wait Process.spawn(*ECHO["b"], [$stdout, $stderr]=>["out", File::WRONLY|File::CREAT|File::TRUNC, 0644]) assert_equal("b", File.read("out").chomp) # problem occur with valgrind - #Process.wait Process.spawn(*ECHO["a"], STDOUT=>:close, STDERR=>["out", File::WRONLY|File::CREAT|File::TRUNC, 0644]) + #Process.wait Process.spawn(*ECHO["a"], $stdout=>:close, $stderr=>["out", File::WRONLY|File::CREAT|File::TRUNC, 0644]) #p File.read("out") #assert_not_empty(File.read("out")) # error message such as "-e:1:in `flush': Bad file descriptor (Errno::EBADF)" - Process.wait Process.spawn(*ECHO["c"], STDERR=>STDOUT, STDOUT=>["out", File::WRONLY|File::CREAT|File::TRUNC, 0644]) + Process.wait Process.spawn(*ECHO["c"], $stderr=>$stdout, $stdout=>["out", File::WRONLY|File::CREAT|File::TRUNC, 0644]) assert_equal("c", File.read("out").chomp) File.open("out", "w") {|f| - Process.wait Process.spawn(*ECHO["d"], STDOUT=>f) + Process.wait Process.spawn(*ECHO["d"], $stdout=>f) assert_equal("d", File.read("out").chomp) } - opts = {STDOUT=>["out", File::WRONLY|File::CREAT|File::TRUNC, 0644]} - opts.merge(3=>STDOUT, 4=>STDOUT, 5=>STDOUT, 6=>STDOUT, 7=>STDOUT) unless windows? + opts = {$stdout=>["out", File::WRONLY|File::CREAT|File::TRUNC, 0644]} + opts.merge(3=>$stdout, 4=>$stdout, 5=>$stdout, 6=>$stdout, 7=>$stdout) unless windows? Process.wait Process.spawn(*ECHO["e"], opts) assert_equal("e", File.read("out").chomp) - opts = {STDOUT=>["out", File::WRONLY|File::CREAT|File::TRUNC, 0644]} - opts.merge(3=>0, 4=>:in, 5=>STDIN, 6=>1, 7=>:out, 8=>STDOUT, 9=>2, 10=>:err, 11=>STDERR) unless windows? + opts = {$stdout=>["out", File::WRONLY|File::CREAT|File::TRUNC, 0644]} + opts.merge(3=>0, 4=>:in, 5=>$stdin, 6=>1, 7=>:out, 8=>$stdout, 9=>2, 10=>:err, 11=>$stderr) unless windows? Process.wait Process.spawn(*ECHO["ee"], opts) assert_equal("ee", File.read("out").chomp) unless windows? # passing non-stdio fds is not supported on Windows File.open("out", "w") {|f| - h = {STDOUT=>f, f=>STDOUT} - 3.upto(30) {|i| h[i] = STDOUT if f.fileno != i } + h = {$stdout=>f, f=>$stdout} + 3.upto(30) {|i| h[i] = $stdout if f.fileno != i } Process.wait Process.spawn(*ECHO["f"], h) assert_equal("f", File.read("out").chomp) } @@ -597,14 +611,14 @@ def test_execopts_redirect_fd Process.wait Process.spawn(*ECHO["f"], [Process]=>1) } assert_raise(ArgumentError) { - Process.wait Process.spawn(*ECHO["f"], [1, STDOUT]=>2) + Process.wait Process.spawn(*ECHO["f"], [1, $stdout]=>2) } assert_raise(ArgumentError) { Process.wait Process.spawn(*ECHO["f"], -1=>2) } - Process.wait Process.spawn(*ECHO["hhh\nggg\n"], STDOUT=>"out") + Process.wait Process.spawn(*ECHO["hhh\nggg\n"], $stdout=>"out") assert_equal("hhh\nggg\n", File.read("out")) - Process.wait Process.spawn(*SORT, STDIN=>"out", STDOUT=>"out2") + Process.wait Process.spawn(*SORT, $stdin=>"out", $stdout=>"out2") assert_equal("ggg\nhhh\n", File.read("out2")) unless windows? @@ -615,9 +629,9 @@ def test_execopts_redirect_fd assert_equal("", File.read("err")) end - system(*ECHO["bb\naa\n"], STDOUT=>["out", "w"]) + system(*ECHO["bb\naa\n"], $stdout=>["out", "w"]) assert_equal("bb\naa\n", File.read("out")) - system(*SORT, STDIN=>["out"], STDOUT=>"out2") + system(*SORT, $stdin=>["out"], $stdout=>"out2") assert_equal("aa\nbb\n", File.read("out2")) } end @@ -731,9 +745,10 @@ def test_execopts_redirect_open_fifo_interrupt_print end unless windows? # does not support fifo def test_execopts_redirect_pipe + omit "spawn" unless main_ractor? with_pipe {|r1, w1| with_pipe {|r2, w2| - opts = {STDIN=>r1, STDOUT=>w2} + opts = {$stdin=>r1, $stdout=>w2} opts.merge(w1=>:close, r2=>:close) unless windows? pid = spawn(*SORT, opts) r1.close @@ -846,30 +861,30 @@ def test_execopts_redirect_to_out_and_err def test_execopts_redirect_dup2_child with_tmpchdir {|d| Process.wait spawn(RUBY, "-e", "STDERR.print 'err'; STDOUT.print 'out'", - STDOUT=>"out", STDERR=>[:child, STDOUT]) + $stdout=>"out", $stderr=>[:child, $stdout]) assert_equal("errout", File.read("out")) Process.wait spawn(RUBY, "-e", "STDERR.print 'err'; STDOUT.print 'out'", - STDERR=>"out", STDOUT=>[:child, STDERR]) + $stderr=>"out", $stdout=>[:child, $stderr]) assert_equal("errout", File.read("out")) omit "inheritance of fd other than stdin,stdout and stderr is not supported" if windows? Process.wait spawn(RUBY, "-e", "STDERR.print 'err'; STDOUT.print 'out'", - STDOUT=>"out", - STDERR=>[:child, 3], + $stdout=>"out", + $stderr=>[:child, 3], 3=>[:child, 4], - 4=>[:child, STDOUT] + 4=>[:child, $stdout] ) assert_equal("errout", File.read("out")) - IO.popen([RUBY, "-e", "STDERR.print 'err'; STDOUT.print 'out'", STDERR=>[:child, STDOUT]]) {|io| + IO.popen([RUBY, "-e", "STDERR.print 'err'; STDOUT.print 'out'", $stderr=>[:child, $stdout]]) {|io| assert_equal("errout", io.read) } - assert_raise(ArgumentError) { Process.wait spawn(*TRUECOMMAND, STDOUT=>[:child, STDOUT]) } + assert_raise(ArgumentError) { Process.wait spawn(*TRUECOMMAND, $stdout=>[:child, $stdout]) } assert_raise(ArgumentError) { Process.wait spawn(*TRUECOMMAND, 3=>[:child, 4], 4=>[:child, 3]) } assert_raise(ArgumentError) { Process.wait spawn(*TRUECOMMAND, 3=>[:child, 4], 4=>[:child, 5], 5=>[:child, 3]) } - assert_raise(ArgumentError) { Process.wait spawn(*TRUECOMMAND, STDOUT=>[:child, 3]) } + assert_raise(ArgumentError) { Process.wait spawn(*TRUECOMMAND, $stdout=>[:child, 3]) } } end @@ -893,13 +908,13 @@ def test_execopts_popen def test_execopts_popen_stdio with_tmpchdir {|d| assert_raise(ArgumentError) { - IO.popen([*ECHO["qux"], STDOUT=>STDOUT]) {|io| } + IO.popen([*ECHO["qux"], $stdout=>$stdout]) {|io| } } - IO.popen([*ECHO["hoge"], STDERR=>STDOUT]) {|io| + IO.popen([*ECHO["hoge"], $stderr=>$stdout]) {|io| assert_equal("hoge\n", io.read) } assert_raise(ArgumentError) { - IO.popen([*ECHO["fuga"], STDOUT=>"out"]) {|io| } + IO.popen([*ECHO["fuga"], $stdout=>"out"]) {|io| } } } end @@ -924,6 +939,7 @@ def test_execopts_popen_extra_fd if Process.respond_to?(:fork) def test_popen_fork + omit "popen fork" unless main_ractor? IO.popen("-") do |io| if !io puts "fooo" @@ -934,9 +950,10 @@ def test_popen_fork end def test_popen_fork_ensure + omit "popen fork" unless main_ractor? IO.popen("-") do |io| if !io - STDERR.reopen(STDOUT) + $stderr.reopen($stdout) # issue is here raise "fooo" else assert_empty io.read @@ -949,6 +966,7 @@ def test_popen_fork_ensure def test_fd_inheritance omit "inheritance of fd other than stdin,stdout and stderr is not supported" if windows? + omit "spawn" unless main_ractor? with_pipe {|r, w| system(RUBY, '-e', 'IO.new(ARGV[0].to_i, "w").puts(:ba)', w.fileno.to_s, w=>w) w.close @@ -1093,6 +1111,7 @@ def test_execopts_redirect_self end unless windows? # passing non-stdio fds is not supported on Windows def test_execopts_redirect_tempfile + pend "Tempfile" if non_main_ractor? bug6269 = '[ruby-core:44181]' Tempfile.create("execopts") do |tmp| pid = assert_nothing_raised(ArgumentError, bug6269) do @@ -1106,12 +1125,13 @@ def test_execopts_redirect_tempfile def test_execopts_duplex_io IO.popen("#{RUBY} -e ''", "r+") {|duplex| - assert_raise(ArgumentError) { system("#{RUBY} -e ''", duplex=>STDOUT) } - assert_raise(ArgumentError) { system("#{RUBY} -e ''", STDOUT=>duplex) } + assert_raise(ArgumentError) { system("#{RUBY} -e ''", duplex=>$stdout) } + assert_raise(ArgumentError) { system("#{RUBY} -e ''", $stdout=>duplex) } } end def test_execopts_modification + omit "spawn" unless main_ractor? h = {} Process.wait spawn(*TRUECOMMAND, h) assert_equal({}, h) @@ -1409,12 +1429,12 @@ def test_argv0 def with_stdin(filename) File.open(filename) {|f| begin - old = STDIN.dup + old = $stdin.dup begin - STDIN.reopen(filename) + $stdin.reopen(filename) yield ensure - STDIN.reopen(old) + $stdin.reopen(old) end ensure old.close @@ -1456,6 +1476,7 @@ def test_argv0_keep_alive end def test_argv0_frozen + omit "global variable access" if non_main_ractor? assert_predicate Process.argv0, :frozen? assert_predicate $0, :frozen? end @@ -1662,6 +1683,7 @@ def test_seteuid end def test_seteuid_name + pend "unsafe Etc method" if non_main_ractor? user = (Etc.getpwuid(Process.euid).name rescue ENV["USER"]) or return assert_nothing_raised(TypeError) {Process.euid = user} rescue NotImplementedError @@ -1679,8 +1701,10 @@ def test_setegid if Process::UID.respond_to?(:from_name) def test_uid_from_name - if u = Etc.getpwuid(Process.uid) - assert_equal(Process.uid, Process::UID.from_name(u.name), u.name) + if main_ractor? # ractor unsafe Etc method + if u = Etc.getpwuid(Process.uid) + assert_equal(Process.uid, Process::UID.from_name(u.name), u.name) + end end exc = assert_raise_kind_of(ArgumentError, SystemCallError) { Process::UID.from_name("\u{4e0d 5b58 5728}") @@ -1691,8 +1715,10 @@ def test_uid_from_name if Process::GID.respond_to?(:from_name) && !RUBY_PLATFORM.include?("android") def test_gid_from_name - if g = Etc.getgrgid(Process.gid) - assert_equal(Process.gid, Process::GID.from_name(g.name), g.name) + if main_ractor? # ractor unsafe Etc method + if g = Etc.getgrgid(Process.gid) + assert_equal(Process.gid, Process::GID.from_name(g.name), g.name) + end end exc = assert_raise_kind_of(ArgumentError, SystemCallError) do Process::GID.from_name("\u{4e0d 5b58 5728}") # fu son zai ("absent" in Kanji) @@ -1809,7 +1835,7 @@ def assert_fail_too_long_path((cmd, sep), mesg) exs = [Errno::ENOENT] exs << Errno::EINVAL if windows? exs << Errno::E2BIG if defined?(Errno::E2BIG) - opts = {[STDOUT, STDERR]=>File::NULL} + opts = {[$stdout, $stderr]=>File::NULL} if defined?(Process::RLIMIT_NPROC) opts[:rlimit_nproc] = /openbsd/i =~ RUBY_PLATFORM ? 64 : 128 end @@ -1839,6 +1865,7 @@ def assert_fail_too_long_path((cmd, sep), mesg) def test_system_sigpipe return if windows? + pend "Timeout" if non_main_ractor? pid = 0 @@ -1856,6 +1883,7 @@ def test_system_sigpipe if Process.respond_to?(:daemon) def test_daemon_default + omit "fork" unless main_ractor? data = IO.popen("-", "r+") do |f| break f.read if f Process.daemon @@ -1865,6 +1893,7 @@ def test_daemon_default end def test_daemon_noclose + omit "fork" unless main_ractor? data = IO.popen("-", "r+") do |f| break f.read if f Process.daemon(false, true) @@ -1874,6 +1903,7 @@ def test_daemon_noclose end def test_daemon_nochdir_noclose + omit "fork" unless main_ractor? data = IO.popen("-", "r+") do |f| break f.read if f Process.daemon(true, true) @@ -1883,18 +1913,20 @@ def test_daemon_nochdir_noclose end def test_daemon_readwrite + omit "fork" unless main_ractor? data = IO.popen("-", "r+") do |f| if f f.puts "ok?" break f.read end Process.daemon(true, true) - puts STDIN.gets + puts $stdin.gets end assert_equal("ok?\n", data) end def test_daemon_pid + omit "fork" unless main_ractor? cpid, dpid = IO.popen("-", "r+") do |f| break f.pid, Integer(f.read) if f Process.daemon(false, true) @@ -1904,6 +1936,7 @@ def test_daemon_pid end def test_daemon_detached + omit "fork" unless main_ractor? IO.popen("-", "r+") do |f| if f assert_equal(f.pid, Process.wait(f.pid)) @@ -1927,6 +1960,7 @@ def test_daemon_detached if File.directory?("/proc/self/task") && /netbsd[a-z]*[1-6]/ !~ RUBY_PLATFORM def test_daemon_no_threads + omit "fork" unless main_ractor? pid, data = IO.popen("-", "r+") do |f| break f.pid, f.readlines if f Process.daemon(true, true) @@ -1938,6 +1972,7 @@ def test_daemon_no_threads end else # darwin def test_daemon_no_threads + omit "fork" unless main_ractor? data = EnvUtil.timeout(3) do IO.popen("-") do |f| break f.readlines.map(&:chomp) if f @@ -1999,6 +2034,7 @@ def test_popen_reopen def test_execopts_new_pgroup return unless windows? + omit "system" unless main_ractor? assert_nothing_raised { system(*TRUECOMMAND, :new_pgroup=>true) } assert_nothing_raised { system(*TRUECOMMAND, :new_pgroup=>false) } @@ -2008,6 +2044,7 @@ def test_execopts_new_pgroup def test_execopts_uid omit "root can use uid option of Kernel#system on Android platform" if RUBY_PLATFORM =~ /android/ + omit "system" unless main_ractor? feature6975 = '[ruby-core:47414]' [30000, [Process.uid, ENV["USER"]]].each do |uid, user| @@ -2040,6 +2077,7 @@ def test_execopts_uid def test_execopts_gid omit "Process.groups not implemented on Windows platform" if windows? omit "root can use Process.groups on Android platform" if RUBY_PLATFORM =~ /android/ + omit "system" unless main_ractor? feature6975 = '[ruby-core:47414]' groups = Process.groups.map do |g| @@ -2125,7 +2163,7 @@ def test_setsid assert_equal(Marshal.load(io), Process.getsid(io.pid)) ensure Process.kill(:KILL, io.pid) rescue nil - Process.wait(io.pid) + Process.wait(io.pid) rescue nil end end end @@ -2394,6 +2432,7 @@ def test_deadlock_by_signal_at_forking end if defined?(fork) def test_process_detach + omit "fork" unless main_ractor? pid = fork {} th = Process.detach(pid) assert_equal pid, th.pid @@ -2457,6 +2496,7 @@ def test_exec_close_reserved_fd end def test_signals_work_after_exec_fail + pend "Timeout" if non_main_ractor? r, w = IO.pipe pid = status = nil EnvUtil.timeout(30) do @@ -2491,6 +2531,7 @@ def test_signals_work_after_exec_fail end if defined?(fork) def test_threading_works_after_exec_fail + pend "Timeout" if non_main_ractor? r, w = IO.pipe pid = status = nil EnvUtil.timeout(90) do @@ -2546,6 +2587,7 @@ def test_many_args end def test_to_hash_on_arguments + omit "separate process" if non_main_ractor? all_assertions do |a| %w[Array String].each do |type| a.for(type) do @@ -2582,17 +2624,20 @@ def test_initgroups end def test_last_status + omit "spawn" unless main_ractor? Process.wait spawn(RUBY, "-e", "exit 13") assert_same(Process.last_status, $?) end def test_last_status_failure + omit "system" unless main_ractor? assert_nil system("sad") assert_not_predicate $?, :success? assert_equal $?.exitstatus, 127 end def test_exec_failure_leaves_no_child + omit "spawn" unless main_ractor? assert_raise(Errno::ENOENT) do spawn('inexistent_command') end @@ -2600,6 +2645,7 @@ def test_exec_failure_leaves_no_child end def test__fork + omit "_fork" unless main_ractor? r, w = IO.pipe pid = Process._fork if pid == 0 @@ -2619,6 +2665,7 @@ def test__fork end if Process.respond_to?(:_fork) def test__fork_pid_cache + omit "_fork" unless main_ractor? _parent_pid = Process.pid r, w = IO.pipe pid = Process._fork @@ -2779,6 +2826,7 @@ def test_warmup_frees_pages end def test_concurrent_group_and_pid_wait + pend "Timeout" if non_main_ractor? # Use a pair of pipes that will make long_pid exit when this test exits, to avoid # leaking temp processes. long_rpipe, long_wpipe = IO.pipe diff --git a/test/ruby/test_rand.rb b/test/ruby/test_rand.rb index f177664943ae9e..866f12567d8c8d 100644 --- a/test/ruby/test_rand.rb +++ b/test/ruby/test_rand.rb @@ -268,6 +268,7 @@ def test_random_equal end def test_fork_shuffle + omit "fork" unless main_ractor? pid = fork do (1..10).to_a.shuffle raise 'default seed is not set' if srand == 0 @@ -278,13 +279,14 @@ def test_fork_shuffle end def assert_fork_status(n, mesg, &block) + pend "ractor_confirm_belonging issue with fork" if non_main_ractor? IO.pipe do |r, w| (1..n).map do st = desc = nil IO.pipe do |re, we| p1 = fork { re.close - STDERR.reopen(we) + $stderr.reopen(we) w.puts(block.call.to_s) } we.close diff --git a/test/ruby/test_range.rb b/test/ruby/test_range.rb index f875c0ab40c5e4..9449ff3f4f8464 100644 --- a/test/ruby/test_range.rb +++ b/test/ruby/test_range.rb @@ -1173,6 +1173,7 @@ def test_cyclic_range_inspect end def test_comparison_when_recursive + pend "Timeout" if non_main_ractor? x = CyclicRange.allocate; x.send(:initialize, x, 1) y = CyclicRange.allocate; y.send(:initialize, y, 1) Timeout.timeout(1) { diff --git a/test/ruby/test_rational.rb b/test/ruby/test_rational.rb index 89bb7b20a8c696..e0edbde4637c44 100644 --- a/test/ruby/test_rational.rb +++ b/test/ruby/test_rational.rb @@ -117,9 +117,13 @@ def test_conv assert_equal(Rational(111, 1000), Rational('1.11e-1')) assert_raise(TypeError){Rational(nil)} assert_raise(ArgumentError){Rational('')} - assert_raise_with_message(ArgumentError, /\u{221a 2668}/) { - Rational("\u{221a 2668}") - } + + EnvUtil.with_default_internal(Encoding::UTF_8) do + assert_raise_with_message(ArgumentError, /\u{221a 2668}/) { + Rational("\u{221a 2668}") + } + end + assert_warning('') { assert_predicate(Rational('1e-99999999999999999999'), :zero?) } diff --git a/test/ruby/test_readpartial.rb b/test/ruby/test_readpartial.rb index bc22556cd4e9e3..ff3b9bb65ec007 100644 --- a/test/ruby/test_readpartial.rb +++ b/test/ruby/test_readpartial.rb @@ -47,6 +47,7 @@ def test_closed_pipe end def test_open_pipe + pend "Timeout" if non_main_ractor? pipe {|r, w| w << 'abc' assert_equal('ab', r.readpartial(2)) @@ -58,6 +59,7 @@ def test_open_pipe end def test_with_stdio + pend "Timeout" if non_main_ractor? pipe {|r, w| w << "abc\ndef\n" assert_equal("abc\n", r.gets) diff --git a/test/ruby/test_refinement.rb b/test/ruby/test_refinement.rb index 6ce434790be13b..1e118a1c193f3b 100644 --- a/test/ruby/test_refinement.rb +++ b/test/ruby/test_refinement.rb @@ -225,6 +225,7 @@ def pow(*) end end def test_method_should_use_refinements + omit "binding" if non_main_ractor? omit if Test::Unit::Runner.current_repeat_count > 0 foo = Foo.new @@ -248,6 +249,7 @@ def abs end end def test_instance_method_should_use_refinements + omit "binding" if non_main_ractor? omit if Test::Unit::Runner.current_repeat_count > 0 foo = Foo.new @@ -314,6 +316,7 @@ def /(other) quo(other) end end def test_override_builtin_method + omit "binding" if non_main_ractor? assert_equal(0, 1 / 2) assert_equal(Rational(1, 2), eval_using(IntegerSlashExt, "1 / 2")) assert_equal(0, 1 / 2) @@ -327,6 +330,7 @@ def +(other) "overridden" end end def test_override_builtin_method_with_method_added + omit "binding" if non_main_ractor? assert_equal(3, 1 + 2) assert_equal("overridden", eval_using(IntegerPlusExt, "1 + 2")) assert_equal(3, 1 + 2) @@ -356,6 +360,7 @@ def baz; return "baz" end end def test_refine_same_class_twice + omit "binding" if non_main_ractor? assert_equal("foo", eval_using(RefineSameClass, "1.foo")) assert_equal("bar", eval_using(RefineSameClass, "1.bar")) assert_equal(RefineSameClass::REFINEMENT1, RefineSameClass::REFINEMENT2) @@ -369,6 +374,7 @@ def foo; "foo"; end end def test_respond_to_should_use_refinements + omit "binding" if non_main_ractor? assert_equal(false, 1.respond_to?(:foo)) assert_equal(true, eval_using(IntegerFooExt, "1.respond_to?(:foo)")) end @@ -390,6 +396,7 @@ def each end def test_builtin_method_no_local_rebinding + omit "binding" if non_main_ractor? assert_equal(false, eval_using(StringCmpExt, '"1" >= "2"')) assert_equal(1, eval_using(ArrayEachExt, "[1, 2, 3].min")) end @@ -419,6 +426,7 @@ def foo end def test_refine_prepended_class + omit "binding" if non_main_ractor? x = eval_using(RefinePrependedClass::M2, "TestRefinement::RefinePrependedClass::C.new.foo") assert_equal([:c, :m1, :m2], x) @@ -541,6 +549,7 @@ def foo end def test_main_using_is_private + omit "binding" if non_main_ractor? assert_raise(NoMethodError) do eval("recv = self; recv.using Module.new", Sandbox::BINDING) end @@ -556,6 +565,7 @@ class UsingClass end def test_module_using_class + omit "binding" if non_main_ractor? assert_raise(TypeError) do eval("using TestRefinement::UsingClass", Sandbox::BINDING) end @@ -638,6 +648,7 @@ def foo end def test_redefine_refined_method + omit "binding" if non_main_ractor? x = eval_using(RedefineRefinedMethod::M, "TestRefinement::RedefineRefinedMethod::C.new.foo") assert_equal("refined", x) @@ -687,6 +698,7 @@ def recursive_length end def test_refine_recursion + omit "binding" if non_main_ractor? x = eval_using(StringRecursiveLength, "'foo'.recursive_length") assert_equal(3, x) end @@ -706,6 +718,7 @@ def to_json; "{" + map { |k, v| k.to_s.dump + ":" + v.to_json }.join(",") + "}" end def test_refine_mutual_recursion + omit "binding" if non_main_ractor? x = eval_using(ToJSON, "[{1=>2}, {3=>4}].to_json") assert_equal('[{"1":2},{"3":4}]', x) end @@ -719,6 +732,7 @@ def test_refine_with_proc end def test_using_in_module + omit "binding" if non_main_ractor? assert_raise(RuntimeError) do eval(<<-EOF, Sandbox::BINDING) $main = self @@ -732,6 +746,7 @@ module M2 end def test_using_in_method + omit "binding" if non_main_ractor? assert_raise(RuntimeError) do eval(<<-EOF, Sandbox::BINDING) $main = self @@ -831,6 +846,7 @@ def test_prepend_after_refine_wb_miss end def test_prepend_after_refine + omit "binding" if non_main_ractor? x = eval_using(PrependAfterRefine::M, "TestRefinement::PrependAfterRefine::C.new.foo") assert_equal("refined", x) @@ -860,6 +876,7 @@ def foo(*args) end def test_super_in_block + omit "binding" if non_main_ractor? bug7925 = '[ruby-core:52750] [Bug #7925]' x = eval_using(SuperInBlock::R, "TestRefinement:: SuperInBlock::C.new.foo(#{bug7925.dump})") @@ -918,6 +935,7 @@ def test_module_using_in_method end def test_module_using_invalid_self + omit "binding" if non_main_ractor? assert_raise(RuntimeError) do eval <<-EOF, Sandbox::BINDING module TestRefinement::TestModuleUsingInvalidSelf @@ -1766,21 +1784,21 @@ def in_ref_c module Foo using RefB - USED_MODS = Module.used_modules - USED_REFS = Module.used_refinements + USED_MODS = Ractor.make_shareable(Module.used_modules) + USED_REFS = Ractor.make_shareable(Module.used_refinements) end module Bar using RefC - USED_MODS = Module.used_modules - USED_REFS = Module.used_refinements + USED_MODS = Ractor.make_shareable(Module.used_modules) + USED_REFS = Ractor.make_shareable(Module.used_refinements) end module Combined using RefA using RefB - USED_MODS = Module.used_modules - USED_REFS = Module.used_refinements + USED_MODS = Ractor.make_shareable(Module.used_modules) + USED_REFS = Ractor.make_shareable(Module.used_refinements) end end @@ -1894,6 +1912,7 @@ def bar end def test_refine_alias_in_subclass + omit "binding" if non_main_ractor? assert_equal(:refined, eval_using(AliasInSubclass::M, "AliasInSubclass::D.new.bar")) end @@ -2409,6 +2428,7 @@ def foo end def test_refine_frozen_class + omit "class ivar" if non_main_ractor? verbose_bak, $VERBOSE = $VERBOSE, nil singleton_class.instance_variable_set(:@x, self) class << self @@ -2601,7 +2621,7 @@ def foo end module B - BAR = "bar" + BAR = "bar".freeze def bar "#{foo}:#{BAR}" @@ -2662,6 +2682,8 @@ def to_s = :R end def test_inline_cache_invalidation + # class has no constant associated and is belonging to this ractor, in theory it could be allowed + pend "class ivar" if non_main_ractor? klass = Class.new do def cached_foo_callsite = foo diff --git a/test/ruby/test_regexp.rb b/test/ruby/test_regexp.rb index 9f1e03e6499782..3afc1fb8b57519 100644 --- a/test/ruby/test_regexp.rb +++ b/test/ruby/test_regexp.rb @@ -1012,6 +1012,7 @@ def test_regsub_no_memory_leak end def test_ignorecase + omit "global variable access" unless main_ractor? v = assert_deprecated_warning(/variable \$= is no longer effective/) { $= } assert_equal(false, v) assert_deprecated_warning(/variable \$= is no longer effective; ignored/) { $= = nil } @@ -1068,6 +1069,7 @@ def test_last_match end def test_getter + omit "global variable access" unless main_ractor? alias $__REGEXP_TEST_LASTMATCH__ $& alias $__REGEXP_TEST_PREMATCH__ $` alias $__REGEXP_TEST_POSTMATCH__ $' @@ -1630,8 +1632,12 @@ def test_unicode_age_16_0 "WHITE CROSS MARK..TOP LEFT JUSTIFIED LOWER RIGHT QUARTER BLACK CIRCLE") end - UnicodeAgeRegexps = Hash.new do |h, age| - h[age] = [/\A\p{age=#{age}}+\z/u, /\A\P{age=#{age}}+\z/u].freeze + def unicode_age_regexps + @unicode_age_regexps ||= begin + Hash.new do |h, age| + h[age] = [/\A\p{age=#{age}}+\z/u, /\A\P{age=#{age}}+\z/u] + end + end end def assert_unicode_age(char, mesg = nil, matches: @matches, unmatches: @unmatches) @@ -1640,13 +1646,13 @@ def assert_unicode_age(char, mesg = nil, matches: @matches, unmatches: @unmatche end matches.each do |age| - pos, neg = UnicodeAgeRegexps[age] + pos, neg = unicode_age_regexps[age] assert_match(pos, char, mesg) assert_not_match(neg, char, mesg) end unmatches.each do |age| - pos, neg = UnicodeAgeRegexps[age] + pos, neg = unicode_age_regexps[age] assert_not_match(pos, char, mesg) assert_match(neg, char, mesg) end @@ -1975,6 +1981,7 @@ def test_s_timeout_memory_leak end def test_bug_20453 + pend "Timeout" unless main_ractor? re = Regexp.new("^(a*)x$", timeout: 0.001) assert_raise(Regexp::TimeoutError) do @@ -1983,6 +1990,7 @@ def test_bug_20453 end def test_bug_20886 + pend "Timeout" unless main_ractor? re = Regexp.new("d()*+|a*a*bc", timeout: 0.02) assert_raise(Regexp::TimeoutError) do re === "b" + "a" * 1000 diff --git a/test/ruby/test_require.rb b/test/ruby/test_require.rb index 13e707639123e9..3c083755f56fc2 100644 --- a/test/ruby/test_require.rb +++ b/test/ruby/test_require.rb @@ -6,6 +6,7 @@ class TestRequire < Test::Unit::TestCase def test_load_error_path + pend "Tempfile" if non_main_ractor? Tempfile.create(["should_not_exist", ".rb"]) {|t| filename = t.path t.close @@ -30,6 +31,7 @@ def test_load_error_path end def test_require_invalid_shared_object + pend "Tempfile" if non_main_ractor? Tempfile.create(["test_ruby_test_require", ".so"]) {|t| t.puts "dummy" t.close @@ -105,6 +107,7 @@ def self.ospath_encoding(path) end def prepare_require_path(dir, encoding) + omit "global variable access" if non_main_ractor? require 'enc/trans/single_byte' Dir.mktmpdir {|tmp| begin @@ -168,6 +171,7 @@ def test_require_path_home_2 end def test_require_path_home_3 + pend "Tempfile" if non_main_ractor? env_rubypath, env_home = ENV["RUBYPATH"], ENV["HOME"] Tempfile.create(["test_ruby_test_require", ".rb"]) {|t| @@ -187,6 +191,7 @@ def test_require_path_home_3 end def test_require_with_unc + pend "Tempfile" if non_main_ractor? Tempfile.create(["test_ruby_test_require", ".rb"]) {|t| t.puts "puts __FILE__" t.close @@ -217,6 +222,7 @@ def test_require_twice end def assert_syntax_error_backtrace + omit "global variable access" if non_main_ractor? loaded_features = $LOADED_FEATURES.dup Dir.mktmpdir do |tmp| req = File.join(tmp, "test.rb") @@ -228,7 +234,7 @@ def assert_syntax_error_backtrace assert_not_empty(bt.find_all {|b| b.start_with? __FILE__}, proc {bt.inspect}) end ensure - $LOADED_FEATURES.replace loaded_features + $LOADED_FEATURES.replace loaded_features if main_ractor? end def test_require_syntax_error @@ -340,6 +346,7 @@ class Socket < BasicSocket; end end def test_load + pend "Tempfile" if non_main_ractor? Tempfile.create(["test_ruby_test_require", ".rb"]) {|t| t.puts "module Foo; end" t.puts "at_exit { p :wrap_end }" @@ -371,6 +378,7 @@ def test_require_in_wrapped_load end def test_public_in_wrapped_load + pend "Tempfile" if non_main_ractor? Tempfile.create(["test_public_in_wrapped_load", ".rb"]) do |t| t.puts "def foo; end", "public :foo" t.close @@ -381,6 +389,7 @@ def test_public_in_wrapped_load end def test_private_in_wrapped_load + pend "Tempfile" if non_main_ractor? Tempfile.create(["test_private_in_wrapped_load", ".rb"]) do |t| t.puts "def foo; end", "private :foo" t.close @@ -391,6 +400,7 @@ def test_private_in_wrapped_load end def test_load_scope + pend "Tempfile" if non_main_ractor? bug1982 = '[ruby-core:25039] [Bug #1982]' Tempfile.create(["test_ruby_test_require", ".rb"]) {|t| t.puts "Hello = 'hello'" @@ -406,6 +416,7 @@ def test_load_scope end def test_load_into_module + pend "Tempfile" if non_main_ractor? Tempfile.create(["test_ruby_test_require", ".rb"]) {|t| t.puts "def b; 1 end" t.puts "class Foo" @@ -460,6 +471,7 @@ def test_load_ospath end def test_relative + omit "global variable access" if non_main_ractor? load_path = $:.dup loaded_featrures = $LOADED_FEATURES.dup @@ -481,11 +493,14 @@ def test_relative end end ensure - $:.replace(load_path) if load_path - $LOADED_FEATURES.replace loaded_featrures + if main_ractor? + $:.replace(load_path) if load_path + $LOADED_FEATURES.replace loaded_featrures + end end def test_relative_symlink + omit "Dir.chdir" if multiple_ractors? Dir.mktmpdir {|tmp| Dir.chdir(tmp) { Dir.mkdir "a" @@ -505,6 +520,7 @@ def test_relative_symlink end def test_relative_symlink_realpath + omit "Dir.chdir" if multiple_ractors? Dir.mktmpdir {|tmp| Dir.chdir(tmp) { Dir.mkdir "a" @@ -538,6 +554,7 @@ def test_frozen_loaded_features end def test_race_exception + pend "Tempfile" if non_main_ractor? bug5754 = '[ruby-core:41618]' path = nil stderr = $stderr @@ -602,12 +619,15 @@ class << (output = "") assert_equal([:pre, :post], scratch, bug5754) } ensure - $VERBOSE = verbose - $stderr = stderr - $".delete(path) + if main_ractor? + $VERBOSE = verbose + $stderr = stderr + $".delete(path) + end end def test_loaded_features_encoding + omit "global variable access" if non_main_ractor? bug6377 = '[ruby-core:44750]' loadpath = $:.dup features = $".dup @@ -620,8 +640,10 @@ def test_loaded_features_encoding assert_send([Encoding, :compatible?, tmp, $"[0]], bug6377) } ensure - $:.replace(loadpath) - $".replace(features) + if main_ractor? + $:.replace(loadpath) + $".replace(features) + end end def test_default_loaded_features_encoding @@ -647,6 +669,7 @@ def test_default_loaded_features_encoding end def test_require_changed_current_dir + omit "Dir.chdir" if multiple_ractors? bug7158 = '[ruby-core:47970]' Dir.mktmpdir {|tmp| Dir.chdir(tmp) { @@ -672,6 +695,7 @@ def test_require_changed_current_dir end def test_require_not_modified_load_path + omit "Dir.chdir" if multiple_ractors? bug7158 = '[ruby-core:47970]' Dir.mktmpdir {|tmp| Dir.chdir(tmp) { @@ -693,6 +717,7 @@ def a.to_str end def test_require_changed_home + omit "Dir.chdir" if multiple_ractors? bug7158 = '[ruby-core:47970]' Dir.mktmpdir {|tmp| Dir.chdir(tmp) { @@ -713,6 +738,7 @@ def test_require_changed_home end def test_require_to_path_redefined_in_load_path + omit "Dir.chdir" if multiple_ractors? bug7158 = '[ruby-core:47970]' Dir.mktmpdir {|tmp| Dir.chdir(tmp) { @@ -741,6 +767,7 @@ def a.to_path end def test_require_to_str_redefined_in_load_path + omit "Dir.chdir" if multiple_ractors? bug7158 = '[ruby-core:47970]' Dir.mktmpdir {|tmp| Dir.chdir(tmp) { @@ -769,6 +796,7 @@ def a.to_str end def assert_require_with_shared_array_modified(add, del) + omit "Dir.chdir" if multiple_ractors? bug7383 = '[ruby-core:49518]' Dir.mktmpdir {|tmp| Dir.chdir(tmp) { @@ -806,6 +834,7 @@ def test_require_with_array_shift end def test_require_local_var_on_toplevel + omit "Dir.chdir" if multiple_ractors? bug7536 = '[ruby-core:50701]' Dir.mktmpdir {|tmp| Dir.chdir(tmp) { @@ -820,6 +849,7 @@ def test_require_local_var_on_toplevel end def test_require_with_loaded_features_pop + pend "Tempfile" if non_main_ractor? bug7530 = '[ruby-core:50645]' Tempfile.create(%w'bug-7530- .rb') {|script| script.close @@ -843,6 +873,7 @@ def test_require_with_loaded_features_pop end def test_loading_fifo_threading_raise + pend "Tempfile" if non_main_ractor? Tempfile.create(%w'fifo .rb') {|f| f.close File.unlink(f.path) @@ -860,6 +891,7 @@ def test_loading_fifo_threading_raise def test_loading_fifo_threading_success omit "[Bug #18613]" if /freebsd/=~ RUBY_PLATFORM + pend "Tempfile" if non_main_ractor? Tempfile.create(%w'fifo .rb') {|f| f.close @@ -888,6 +920,7 @@ def test_loading_fifo_threading_success def test_loading_fifo_fd_leak omit if RUBY_PLATFORM =~ /android/ # https://rubyci.org/logs/rubyci.s3.amazonaws.com/android29-x86_64/ruby-master/log/20200419T124100Z.fail.html.gz + pend "Tempfile" if non_main_ractor? Tempfile.create(%w'fifo .rb') {|f| f.close @@ -913,6 +946,7 @@ def test_loading_fifo_fd_leak end if File.respond_to?(:mkfifo) and defined?(Process::RLIMIT_NOFILE) def test_throw_while_loading + pend "Tempfile" if non_main_ractor? Tempfile.create(%w'bug-11404 .rb') do |f| f.puts 'sleep' f.close @@ -957,6 +991,7 @@ def test_symlink_load_path end def test_provide_in_required_file + omit "global variable access" if non_main_ractor? paths, loaded = $:.dup, $".dup Dir.mktmpdir do |tmp| provide = File.realdirpath("provide.rb", tmp) @@ -969,12 +1004,15 @@ def test_provide_in_required_file assert_equal($".pop, "target.rb") end ensure - $:.replace(paths) - $".replace(loaded) + if main_ractor? + $:.replace(paths) + $".replace(loaded) + end end if defined?($LOAD_PATH.resolve_feature_path) def test_resolve_feature_path + pend "Tempfile" if non_main_ractor? paths, loaded = $:.dup, $".dup Dir.mktmpdir do |tmp| Tempfile.create(%w[feature .rb], tmp) do |file| @@ -988,11 +1026,14 @@ def test_resolve_feature_path end end ensure - $:.replace(paths) - $".replace(loaded) + if main_ractor? + $:.replace(paths) + $".replace(loaded) + end end def test_resolve_feature_path_with_missing_feature + omit "global variable access" if non_main_ractor? assert_nil($LOAD_PATH.resolve_feature_path("superkalifragilisticoespialidoso")) end end diff --git a/test/ruby/test_require_lib.rb b/test/ruby/test_require_lib.rb index 44dfbcf9ec27a5..522444b2a30ab6 100644 --- a/test/ruby/test_require_lib.rb +++ b/test/ruby/test_require_lib.rb @@ -15,6 +15,10 @@ class TestRequireLib < Test::Unit::TestCase # skip some problems scripts -= %w[bundler bundled_gems rubygems mkmf set/sorted_set] + def setup + omit "separate process" if non_main_ractor? + end + scripts.each do |lib| define_method "test_thread_size:#{lib}" do assert_separately(['-W0'], "#{<<~"begin;"}\n#{<<~"end;"}", timeout: 60) diff --git a/test/ruby/test_rubyoptions.rb b/test/ruby/test_rubyoptions.rb index b6c76ac73a662e..c64c7c73adc34b 100644 --- a/test/ruby/test_rubyoptions.rb +++ b/test/ruby/test_rubyoptions.rb @@ -43,6 +43,10 @@ def with_tmpchdir } end + def setup + omit "separate process" unless main_ractor? + end + def test_source_file assert_in_out_err([], "", [], []) end diff --git a/test/ruby/test_settracefunc.rb b/test/ruby/test_settracefunc.rb index fac6dd818533d0..f469180dd25da7 100644 --- a/test/ruby/test_settracefunc.rb +++ b/test/ruby/test_settracefunc.rb @@ -4,6 +4,7 @@ class TestSetTraceFunc < Test::Unit::TestCase def setup + omit "Tracepoint not working in ractors" unless main_ractor? if defined?(RubyVM) @original_compile_option = RubyVM::InstructionSequence.compile_option RubyVM::InstructionSequence.compile_option = { @@ -1535,6 +1536,7 @@ class C9759 end def test_define_method_on_exception + pend "ractor bug?" if non_main_ractor? events = [] obj = C9759.new TracePoint.new(:call, :return){|tp| @@ -1563,12 +1565,12 @@ def test_define_method_on_exception end class C11492 - define_method(:foo_return){ + define_method(:foo_return, &Ractor.make_shareable(proc{ return true - } - define_method(:foo_break){ + })) + define_method(:foo_break, &Ractor.make_shareable(proc{ break true - } + })) end def test_define_method_on_return @@ -2103,29 +2105,29 @@ def test_return_value_with_rescue '[Bug #13369]' end - define_method(:f_last_defined) do + define_method(:f_last_defined, &Ractor.make_shareable(proc do :f_last_defined - end + end)) - define_method(:f_return_defined) do + define_method(:f_return_defined, &Ractor.make_shareable(proc do return :f_return_defined - end + end)) - define_method(:f_break_defined) do + define_method(:f_break_defined, &Ractor.make_shareable(proc do break :f_break_defined - end + end)) - define_method(:f_raise_defined) do + define_method(:f_raise_defined, &Ractor.make_shareable(proc do raise rescue return :f_raise_defined - end + end)) - define_method(:f_break_in_rescue_defined) do + define_method(:f_break_in_rescue_defined, &Ractor.make_shareable(proc do raise rescue break :f_break_in_rescue_defined - end + end)) def test_return_value_with_rescue_and_defined_methods assert_equal [[:b_return, :f_last_defined, :f_last_defined], @@ -2154,13 +2156,13 @@ def test_return_value_with_rescue_and_defined_methods '[Bug #13369]' end - define_method(:just_yield) do |&block| + define_method(:just_yield, &Ractor.make_shareable(proc do |&block| block.call - end + end)) - define_method(:unwind_multiple_bmethods) do + define_method(:unwind_multiple_bmethods, &Ractor.make_shareable(proc do just_yield { return :unwind_multiple_bmethods } - end + end)) def test_non_local_return_across_multiple_define_methods assert_equal [[:b_return, :unwind_multiple_bmethods, nil], diff --git a/test/ruby/test_shapes.rb b/test/ruby/test_shapes.rb index 77bba6421baee0..de484a9e576425 100644 --- a/test/ruby/test_shapes.rb +++ b/test/ruby/test_shapes.rb @@ -125,6 +125,7 @@ def test_too_complex end def test_ordered_alloc_is_not_complex + pend "ObjectSpace.dump" if non_main_ractor? 5.times { OrderedAlloc.new.add_ivars } obj = JSON.parse(ObjectSpace.dump(OrderedAlloc)) assert_operator obj["variation_count"], :<, RubyVM::Shape::SHAPE_MAX_VARIATIONS @@ -147,6 +148,8 @@ class Hi; end end def test_too_many_ivs_on_class + # could be safe due to not having a constant attached + pend "class ivars" obj = Class.new obj.instance_variable_set(:@test_too_many_ivs_on_class, 1) @@ -160,6 +163,8 @@ def test_too_many_ivs_on_class end def test_removing_when_too_many_ivs_on_class + # could be safe due to not having a constant attached + pend "class ivars" obj = Class.new (MANY_IVS + 2).times do @@ -173,6 +178,8 @@ def test_removing_when_too_many_ivs_on_class end def test_removing_when_too_many_ivs_on_module + # could be safe due to not having a constant attached + pend "module ivars" if non_main_ractor? obj = Module.new (MANY_IVS + 2).times do diff --git a/test/ruby/test_signal.rb b/test/ruby/test_signal.rb index a2bdf02b88522f..3e1cb4173c91b7 100644 --- a/test/ruby/test_signal.rb +++ b/test/ruby/test_signal.rb @@ -5,6 +5,7 @@ class TestSignal < Test::Unit::TestCase def test_signal + omit "signals run in main ractor" if non_main_ractor? begin x = 0 oldtrap = Signal.trap(:INT) {|sig| x = 2 } @@ -26,6 +27,7 @@ def test_signal end if Process.respond_to?(:kill) def test_signal_process_group + omit "Process.spawn" unless main_ractor? bug4362 = '[ruby-dev:43169]' assert_nothing_raised(bug4362) do cmd = [ EnvUtil.rubybin, '--disable=gems' '-e', 'sleep 10' ] @@ -39,6 +41,7 @@ def test_signal_process_group Process.respond_to?(:pgroup) # for mswin32 def test_exit_action + pend "Timeout" if non_main_ractor? if Signal.list[sig = "USR1"] term = :TERM else @@ -97,6 +100,7 @@ def test_interrupt end def test_signal2 + pend "Timeout" if non_main_ractor? begin x = false oldtrap = Signal.trap(:INT) {|sig| x = true } @@ -132,6 +136,7 @@ def o.to_str; "SIGINT"; end end if Process.respond_to?(:kill) def test_trap + omit "not ractor safe" unless main_ractor? begin oldtrap = Signal.trap(:INT) {|sig| } @@ -169,11 +174,11 @@ def o.to_str; "SIGINT"; end end end if Process.respond_to?(:kill) - %w"KILL STOP".each do |sig| + Ractor.make_shareable(%w"KILL STOP").each do |sig| if Signal.list.key?(sig) - define_method("test_trap_uncatchable_#{sig}") do + define_method("test_trap_uncatchable_#{sig}", &Ractor.make_shareable(proc do assert_raise(Errno::EINVAL, "SIG#{sig} is not allowed to be caught") { Signal.trap(sig) {} } - end + end)) end end @@ -260,6 +265,7 @@ def test_trap_puts end if Process.respond_to?(:kill) def test_hup_me + pend "Timeout" if non_main_ractor? # [Bug #7951] [ruby-core:52864] # This is MRI specific spec. ruby has no guarantee # that signal will be deliverd synchronously. @@ -312,6 +318,7 @@ def test_signal_list_dedupe_keys def test_self_stop omit unless Process.respond_to?(:fork) omit unless defined?(Process::WUNTRACED) + omit "fork" unless main_ractor? # Make a process that stops itself child_pid = fork do diff --git a/test/ruby/test_sprintf_comb.rb b/test/ruby/test_sprintf_comb.rb index 41131130309fdd..715cb414af2b9d 100644 --- a/test/ruby/test_sprintf_comb.rb +++ b/test/ruby/test_sprintf_comb.rb @@ -115,6 +115,10 @@ def self.combination(*args, &b) AllPairs.each(*args, &b) end + def setup + omit "unshareable procs" if non_main_ractor? + end + def emu_int(format, v) /\A%( )?(\#)?(\+)?(-)?(0)?(\d+)?(?:\.(\d*))?(.)\z/ =~ format sp = $1 diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb index c7e4b0c1ec7fee..c3fabd9bbd2dbd 100644 --- a/test/ruby/test_string.rb +++ b/test/ruby/test_string.rb @@ -5,7 +5,7 @@ class TestString < Test::Unit::TestCase WIDE_ENCODINGS = [ Encoding::UTF_16BE, Encoding::UTF_16LE, Encoding::UTF_32BE, Encoding::UTF_32LE, - ] + ].freeze def initialize(*args) @cls = String @@ -399,7 +399,7 @@ def test_capitalize! end - Bug2463 = '[ruby-dev:39856]' + Bug2463 = '[ruby-dev:39856]'.freeze def test_center assert_equal(S("hello"), S("hello").center(4)) assert_equal(S(" hello "), S("hello").center(11)) @@ -408,6 +408,8 @@ def test_center end def test_chomp + omit "$/ set" if multiple_ractors? + run_ensure = true verbose, $VERBOSE = $VERBOSE, nil assert_equal(S("hello"), S("hello").chomp("\n")) @@ -474,11 +476,15 @@ def test_chomp s = "foo\r" assert_equal("foo", s.chomp("\n")) ensure - $/ = save - $VERBOSE = verbose + if run_ensure + $/ = save + $VERBOSE = verbose + end end def test_chomp! + omit "$/ set " if multiple_ractors? + run_ensure = true verbose, $VERBOSE = $VERBOSE, nil a = S("hello") @@ -598,8 +604,10 @@ def o.to_str assert_raise(ArgumentError) {String.new.chomp!("", "")} ensure - $/ = save - $VERBOSE = verbose + if run_ensure + $/ = save + $VERBOSE = verbose + end end def test_chop @@ -673,6 +681,7 @@ def test_concat_literals def test_string_interpolations_across_heaps_get_embedded omit if GC::INTERNAL_CONSTANTS[:HEAP_COUNT] == 1 + omit "ObjectSpace.dump" if non_main_ractor? require 'objspace' base_slot_size = GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE] @@ -738,12 +747,15 @@ def test_crypt assert_raise(ArgumentError) {S("mypassword".encode(enc)).crypt(S("aa"))} end - @cls == String and + #pend "String#crypt unsafe?" + if main_ractor? + @cls == String and assert_no_memory_leak([], "s = ''; salt_proc = proc{#{(crypt_supports_des_crypt? ? '..' : good_salt).inspect}}", "#{<<~"begin;"}\n#{<<~'end;'}") - begin; - 1000.times { s.crypt(-salt_proc.call).clear } - end; + begin; + 1000.times { s.crypt(-salt_proc.call).clear } + end; + end end def test_delete @@ -943,6 +955,8 @@ def test_ivar_set_after_frozen_dup end def test_each + omit "set $/" if multiple_ractors? + run_ensure = true verbose, $VERBOSE = $VERBOSE, nil save = $/ @@ -963,8 +977,10 @@ def test_each assert_equal(S("hello!"), res[0]) assert_equal(S("world"), res[1]) ensure - $/ = save - $VERBOSE = verbose + if run_ensure + $/ = save + $VERBOSE = verbose + end end def test_each_byte @@ -1134,6 +1150,8 @@ def test_byteslice_grapheme_clusters end def test_each_line + omit "set $/" if multiple_ractors? + run_ensure = true verbose, $VERBOSE = $VERBOSE, nil save = $/ @@ -1181,8 +1199,10 @@ def test_each_line S("\n\u0100").each_line("\n") {} end ensure - $/ = save - $VERBOSE = verbose + if run_ensure + $/ = save + $VERBOSE = verbose + end end def test_each_line_chomp @@ -1804,6 +1824,7 @@ def test_slice! end def test_split + omit "global variable access" if non_main_ractor? fs, $; = $;, nil assert_equal([S("a"), S("b"), S("c")], S(" a b\t c ").split) assert_equal([S("a"), S("b"), S("c")], S(" a b\t c ").split(S(" "))) @@ -1827,10 +1848,11 @@ def test_split assert_equal([], S("").split(//, 1)) ensure - EnvUtil.suppress_warning {$; = fs} + EnvUtil.suppress_warning {$; = fs} if main_ractor? end def test_split_with_block + omit "global variable access" if non_main_ractor? fs, $; = $;, nil result = []; S(" a b\t c ").split {|s| result << s} assert_equal([S("a"), S("b"), S("c")], result) @@ -1877,10 +1899,11 @@ def test_split_with_block end } ensure - EnvUtil.suppress_warning {$; = fs} + EnvUtil.suppress_warning {$; = fs} if main_ractor? end def test_fs + omit "global variable access" if non_main_ractor? return unless @cls == String assert_raise_with_message(TypeError, /\$;/) { @@ -3391,10 +3414,12 @@ def test_uplus_minus assert_same(str, +str) assert_not_same(str, -str) - require 'objspace' - str = "test_uplus_minus_str".freeze - assert_includes ObjectSpace.dump(str), '"fstring":true' + if main_ractor? + require 'objspace' + + assert_includes ObjectSpace.dump(str), '"fstring":true' + end assert_predicate(str, :frozen?) assert_not_predicate(+str, :frozen?) @@ -3403,8 +3428,10 @@ def test_uplus_minus assert_not_same(str, +str) assert_same(str, -str) - bar = -%w(test uplus minus str).join('_') - assert_same(str, bar, "uminus deduplicates [Feature #13077] str: #{ObjectSpace.dump(str)} bar: #{ObjectSpace.dump(bar)}") + if main_ractor? + bar = -%w(test uplus minus str).join('_') + assert_same(str, bar, "uminus deduplicates [Feature #13077] str: #{ObjectSpace.dump(str)} bar: #{ObjectSpace.dump(bar)}") + end end def test_uminus_dedup_in_place @@ -3415,6 +3442,7 @@ def test_uminus_dedup_in_place def test_uminus_frozen return unless @cls == String + omit "not always same" if multiple_ractors? # embedded str1 = ("foobar" * 3).freeze @@ -3722,6 +3750,7 @@ def test_chilled_string end def test_chilled_string_setivar + omit "monkey patch" if multiple_ractors? deprecated = Warning[:deprecated] Warning[:deprecated] = false diff --git a/test/ruby/test_string_memory.rb b/test/ruby/test_string_memory.rb index a93a3bd54afcea..ac260a818b55b1 100644 --- a/test/ruby/test_string_memory.rb +++ b/test/ruby/test_string_memory.rb @@ -3,6 +3,10 @@ require 'objspace' class TestStringMemory < Test::Unit::TestCase + def setup + omit "ObjectSpace.trace_object_allocations" if non_main_ractor? + end + def capture_allocations(klass) allocations = [] diff --git a/test/ruby/test_stringchar.rb b/test/ruby/test_stringchar.rb index e13beef69c1883..aa8983f31dafb0 100644 --- a/test/ruby/test_stringchar.rb +++ b/test/ruby/test_stringchar.rb @@ -41,9 +41,11 @@ def test_string assert_match(/foo(?=(bar)|(baz))/, "foobar") assert_match(/foo(?=(bar)|(baz))/, "foobaz") - $foo = "abc" - assert_equal("abc = abc", "#$foo = abc") - assert_equal("abc = abc", "#{$foo} = abc") + if main_ractor? + $foo = "abc" + assert_equal("abc = abc", "#$foo = abc") + assert_equal("abc = abc", "#{$foo} = abc") + end foo = "abc" assert_equal("abc = abc", "#{foo} = abc") diff --git a/test/ruby/test_struct.rb b/test/ruby/test_struct.rb index db591c306e556e..662269dd521ca3 100644 --- a/test/ruby/test_struct.rb +++ b/test/ruby/test_struct.rb @@ -5,6 +5,7 @@ module TestStruct def test_struct + omit "constant redef" if multiple_ractors? struct_test = @Struct.new("Test", :foo, :bar) assert_equal(@Struct::Test, struct_test) @@ -99,6 +100,7 @@ def test_set end def test_struct_new + omit "global side effects" if multiple_ractors? assert_raise(NameError) { @Struct.new("foo") } assert_nothing_raised { @Struct.new("Foo") } @Struct.instance_eval { remove_const(:Foo) } @@ -114,6 +116,7 @@ def test_struct_new_with_hash end def test_struct_new_with_keyword_init + omit "constant redef" if multiple_ractors? @Struct.new("KeywordInitTrue", :a, :b, keyword_init: true) @Struct.new("KeywordInitFalse", :a, :b, keyword_init: false) @@ -203,10 +206,12 @@ def test_inspect o.a = o assert_match(/^#:...>>$/, o.inspect) - @Struct.new("Foo", :a) - o = @Struct::Foo.new(1) - assert_equal("#", o.inspect) - @Struct.instance_eval { remove_const(:Foo) } + unless multiple_ractors? + @Struct.new("Foo", :a) + o = @Struct::Foo.new(1) + assert_equal("#", o.inspect) + @Struct.instance_eval { remove_const(:Foo) } + end klass = @Struct.new(:a, :b) o = klass.new(1, 2) @@ -359,6 +364,7 @@ def test_error end def test_redefinition_warning + omit "constant redef" unless main_ractor? @Struct.new(name = "RedefinitionWarning") e = EnvUtil.verbose_warning do @Struct.new("RedefinitionWarning") @@ -382,6 +388,7 @@ def test_keyword_args_warning end def test_nonascii + omit "constant redef" if multiple_ractors? struct_test = @Struct.new(name = "R\u{e9}sum\u{e9}", :"r\u{e9}sum\u{e9}") assert_equal(@Struct.const_get("R\u{e9}sum\u{e9}"), struct_test, '[ruby-core:24849]') a = struct_test.new(42) @@ -399,6 +406,7 @@ def test_nonascii end def test_junk + omit "global side effects" if multiple_ractors? struct_test = @Struct.new("Foo", "a\000") o = struct_test.new(1) assert_equal(1, o.send("a\000")) @@ -406,6 +414,7 @@ def test_junk end def test_comparison_when_recursive + pend "Timeout" if non_main_ractor? klass1 = @Struct.new(:a, :b, :c) x = klass1.new(1, 2, nil); x.c = x diff --git a/test/ruby/test_super.rb b/test/ruby/test_super.rb index 8e973b0f7f4a08..905800161680c4 100644 --- a/test/ruby/test_super.rb +++ b/test/ruby/test_super.rb @@ -214,11 +214,13 @@ def obj.reverse str.reverse end - assert_nothing_raised('[ruby-core:27230]') do - mid=Indexed.new - mid.instance_eval(&Overlaid) - mid.subseq - mid.subseq + if main_ractor? + assert_nothing_raised('[ruby-core:27230]') do + mid=Indexed.new + mid.instance_eval(&Overlaid) + mid.subseq + mid.subseq + end end end @@ -427,9 +429,9 @@ def foo(*args) end class Y < X - define_method(:foo) do |*args| + define_method(:foo, &Ractor.make_shareable(proc do |*args| super(*args) - end + end)) end def test_super_splat @@ -539,6 +541,7 @@ def foo(result) # [Bug #18329] def test_super_missing_prepended_module + omit "GC.stress" if multiple_ractors? a = Module.new do def probe(*methods) prepend(probing_module(methods)) @@ -620,6 +623,7 @@ def foo end def test_public_zsuper_with_prepend + pend "Timeout" if non_main_ractor? bug12876 = '[ruby-core:77784] [Bug #12876]' m = EnvUtil.labeled_module("M") c = EnvUtil.labeled_class("C") {prepend m; public :initialize} diff --git a/test/ruby/test_symbol.rb b/test/ruby/test_symbol.rb index c50febf5d1c6fa..c24b8049648bf8 100644 --- a/test/ruby/test_symbol.rb +++ b/test/ruby/test_symbol.rb @@ -214,14 +214,17 @@ def hoge end } def test_to_proc_arg_with_refinements + omit "ractor_confirm_belonging issue" if non_main_ractor? assert_equal(:hoge, _test_to_proc_arg_with_refinements_call(&:hoge)) end def test_to_proc_lambda_with_refinements + omit "ractor_confirm_belonging issue" if non_main_ractor? assert_predicate(_test_to_proc_with_refinements_call(&:hoge), :lambda?) end def test_to_proc_arity_with_refinements + omit "ractor_confirm_belonging issue" if non_main_ractor? assert_equal(-2, _test_to_proc_with_refinements_call(&:hoge).arity) end @@ -492,10 +495,10 @@ def test_singleton_method assert_raise(TypeError) { a = :foo; def a.foo; end } end - SymbolsForEval = [ + SymbolsForEval = Ractor.make_shareable([ :foo, "dynsym_#{Random.rand(10000)}_#{Time.now}".to_sym - ] + ]) def test_instance_eval bug11086 = '[ruby-core:68961] [Bug #11086]' diff --git a/test/ruby/test_syntax.rb b/test/ruby/test_syntax.rb index b7e021a4ff4976..2f257ae98b7f25 100644 --- a/test/ruby/test_syntax.rb +++ b/test/ruby/test_syntax.rb @@ -32,6 +32,7 @@ def test_defined_empty_argument end def test_must_ascii_compatible + pend "Tempfile" unless main_ractor? require 'tempfile' f = Tempfile.new("must_ac_") Encoding.list.each do |enc| @@ -49,6 +50,7 @@ def test_must_ascii_compatible end def test_script_lines + pend "Tempfile" unless main_ractor? require 'tempfile' f = Tempfile.new("bug4361_") bug4361 = '[ruby-dev:43168]' @@ -220,7 +222,11 @@ def test_newline_in_block_parameters m = m.tr_s('()', ' ').strip if n3 == 'do' name = "test_#{n3}_block_after_blockcall_#{n1}_#{n2}_arg" code = "#{blockcall}#{c}#{m} #{b}" - define_method(name) {assert_valid_syntax(code, bug6115)} + class_eval <<-RUBY + def #{name} + assert_valid_syntax(#{code.inspect}, #{bug6115.inspect}) + end + RUBY end end @@ -314,8 +320,8 @@ def o.kw(**a) a end assert_equal({foo: 1, bar: 2}, o.kw(foo: 1, bar: 2), bug5989) EnvUtil.under_gc_stress do eval("def o.m(k: 0) k end") - end - assert_equal(42, o.m(k: 42), '[ruby-core:45744]') + assert_equal(42, o.m(k: 42), '[ruby-core:45744]') + end unless multiple_ractors? bug7922 = '[ruby-core:52744] [Bug #7922]' def o.bug7922(**) end assert_nothing_raised(ArgumentError, bug7922) {o.bug7922(foo: 42)} @@ -830,6 +836,7 @@ def test_reserved_method_no_args end def test_unassignable + omit "global variable access" unless main_ractor? gvar = global_variables %w[self nil true false __FILE__ __LINE__ __ENCODING__].each do |kwd| assert_syntax_error("#{kwd} = nil", /Can't .* #{kwd}$/) @@ -837,7 +844,7 @@ def test_unassignable end end - Bug7559 = '[ruby-dev:46737]' + Bug7559 = '[ruby-dev:46737]'.freeze def test_lineno_command_call_quote expected = __LINE__ + 1 @@ -1481,6 +1488,7 @@ def test_brace_after_literal_argument end def test_return_toplevel + pend "Tempfile" unless main_ractor? feature4840 = '[ruby-core:36785] [Feature #4840]' line = __LINE__+2 code = "#{<<~"begin;"}#{<<~'end;'}" @@ -1530,6 +1538,7 @@ def test_return_toplevel end def test_eval_return_toplevel + pend "Tempfile" unless main_ractor? feature4840 = '[ruby-core:36785] [Feature #4840]' line = __LINE__+2 code = "#{<<~"begin;"}#{<<~'end;'}" diff --git a/test/ruby/test_system.rb b/test/ruby/test_system.rb index 3fcdaa6aada73e..2566f06d6105e0 100644 --- a/test/ruby/test_system.rb +++ b/test/ruby/test_system.rb @@ -118,6 +118,7 @@ def test_system_redirect_win if /mswin|mingw/ !~ RUBY_PLATFORM return end + omit "Dir.chdir" if multiple_ractors? Dir.mktmpdir("ruby_script_tmp") do |tmpdir| cmd = nil diff --git a/test/ruby/test_thread.rb b/test/ruby/test_thread.rb index 12ba1165ed8817..9fdc4d6d29c738 100644 --- a/test/ruby/test_thread.rb +++ b/test/ruby/test_thread.rb @@ -6,20 +6,22 @@ class TestThread < Test::Unit::TestCase class Thread < ::Thread - Threads = [] + def self.Threads + Ractor.current[:__THREADS] ||= [] + end def self.new(*) th = super - Threads << th + (Ractor.current[:__THREADS] ||= []) << th th end end def setup - Thread::Threads.clear + (Ractor.current[:__THREADS] ||= []).clear end def teardown - Thread::Threads.each do |t| + Thread.Threads.each do |t| t.kill if t.alive? begin t.join @@ -148,6 +150,7 @@ def test_mutex_synchronize_yields_no_block_params end def test_local_barrier + omit "global variable access" if non_main_ractor? dir = File.dirname(__FILE__) lbtest = File.join(dir, "lbtest.rb") $:.unshift File.join(File.dirname(dir), 'ruby') @@ -255,12 +258,14 @@ def test_join_argument_conversion { 'FIXNUM_MAX' => RbConfig::LIMITS['FIXNUM_MAX'], 'UINT64_MAX' => RbConfig::LIMITS['UINT64_MAX'], - 'INFINITY' => Float::INFINITY + 'INFINITY' => 'Float::INFINITY' }.each do |name, limit| - define_method("test_join_limit_#{name}") do - t = Thread.new {} - assert_same t, t.join(limit), "limit=#{limit.inspect}" - end + class_eval <<-RUBY + def test_join_limit_#{name} + t = Thread.new {} + assert_same t, t.join(#{limit}), %q(limit=#{limit.inspect}) + end + RUBY end { 'minus_1' => -1, @@ -269,7 +274,8 @@ def test_join_argument_conversion 'INT64_MIN' => RbConfig::LIMITS['INT64_MIN'], 'minus_INFINITY' => -Float::INFINITY }.each do |name, limit| - define_method("test_join_limit_negative_#{name}") do + define_method("test_join_limit_negative_#{name}", &Ractor.make_shareable(proc do + pend "Timeout" if non_main_ractor? t = Thread.new { sleep } begin assert_nothing_raised(Timeout::Error) do @@ -280,7 +286,7 @@ def test_join_argument_conversion ensure t.kill end - end + end)) end def test_kill_main_thread @@ -924,6 +930,7 @@ def test_handle_interrupted? end def test_thread_timer_and_ensure + pend "Timeout" if non_main_ractor? assert_normal_exit(<<_eom, 'r36492', timeout: 10) flag = false t = Thread.new do @@ -976,6 +983,7 @@ def test_backtrace def test_thread_timer_and_interrupt omit "[Bug #18613]" if /freebsd/ =~ RUBY_PLATFORM + pend "Timeout" if non_main_ractor? bug5757 = '[ruby-dev:44985]' pid = nil @@ -1210,6 +1218,7 @@ def test_machine_stack_size end unless /mswin|mingw/ =~ RUBY_PLATFORM def test_blocking_mutex_unlocked_on_fork + omit "fork" unless main_ractor? bug8433 = '[ruby-core:55102] [Bug #8433]' mutex = Thread::Mutex.new @@ -1235,11 +1244,12 @@ def test_blocking_mutex_unlocked_on_fork end if Process.respond_to?(:fork) def test_fork_in_thread + omit "fork" unless main_ractor? bug9751 = '[ruby-core:62070] [Bug #9751]' f = nil th = Thread.start do unless f = IO.popen("-") - STDERR.reopen(STDOUT) + $stderr.reopen($stdout) exit end Process.wait2(f.pid) @@ -1256,6 +1266,7 @@ def test_fork_in_thread end if Process.respond_to?(:fork) def test_fork_value + omit "fork" unless main_ractor? bug18902 = "[Bug #18902]" th = Thread.start { sleep 2 } begin @@ -1271,6 +1282,7 @@ def test_fork_value end if Process.respond_to?(:fork) def test_fork_while_locked + omit "fork" unless main_ractor? m = Thread::Mutex.new thrs = [] 3.times do |i| @@ -1283,6 +1295,7 @@ def test_fork_while_locked def test_fork_while_parent_locked omit 'needs fork' unless Process.respond_to?(:fork) + omit "fork" unless main_ractor? m = Thread::Mutex.new nr = 1 thrs = [] @@ -1304,6 +1317,7 @@ def test_fork_while_parent_locked def test_fork_while_mutex_locked_by_forker omit 'needs fork' unless Process.respond_to?(:fork) + pend "Timeout" if non_main_ractor? m = Thread::Mutex.new m.synchronize do pid = fork do @@ -1448,6 +1462,7 @@ def test_thread_native_thread_id end def test_thread_native_thread_id_across_fork_on_linux + omit "fork" unless main_ractor? begin require '-test-/thread/id' rescue LoadError @@ -1480,6 +1495,7 @@ def test_thread_native_thread_id_across_fork_on_linux end def test_thread_interrupt_for_killed_thread + pend "Timeout" if non_main_ractor? opts = { timeout: 5, timeout_error: nil } assert_normal_exit(<<-_end, '[Bug #8996]', **opts) diff --git a/test/ruby/test_thread_cv.rb b/test/ruby/test_thread_cv.rb index eb88b9606cebf1..7abf44428ed150 100644 --- a/test/ruby/test_thread_cv.rb +++ b/test/ruby/test_thread_cv.rb @@ -55,6 +55,7 @@ def test_condvar_wait_exception_handling end def test_condvar_wait_and_broadcast + pend "Timeout" if non_main_ractor? nr_threads = 3 threads = Array.new mutex = Thread::Mutex.new @@ -84,8 +85,8 @@ def test_condvar_wait_and_broadcast assert_equal ["C1", "C1", "C1", "P1", "P2", "C2", "C2", "C2"], result ensure - threads.each(&:kill) - threads.each(&:join) + threads&.each(&:kill) + threads&.each(&:join) end def test_condvar_wait_deadlock @@ -109,6 +110,7 @@ def test_condvar_wait_deadlock end def test_condvar_wait_deadlock_2 + pend "Timeout" if non_main_ractor? nr_threads = 3 threads = Array.new mutex = Thread::Mutex.new @@ -220,6 +222,7 @@ def test_dump end def test_condvar_fork + omit "fork" unless main_ractor? mutex = Thread::Mutex.new condvar = Thread::ConditionVariable.new thrs = (1..10).map do diff --git a/test/ruby/test_thread_queue.rb b/test/ruby/test_thread_queue.rb index 9485528977e599..86295fe81f20f4 100644 --- a/test/ruby/test_thread_queue.rb +++ b/test/ruby/test_thread_queue.rb @@ -317,6 +317,7 @@ def test_sized_queue_throttle end def test_queue_thread_raise + pend "Timeout" if non_main_ractor? q = Thread::Queue.new th1 = Thread.new do begin @@ -681,6 +682,7 @@ def test_queue_with_trap end def test_fork_while_queue_waiting + omit "fork" unless main_ractor? q = Thread::Queue.new sq = Thread::SizedQueue.new(1) thq = Thread.new { q.pop } diff --git a/test/ruby/test_time.rb b/test/ruby/test_time.rb index 333edb80218a64..9f618f20b1120b 100644 --- a/test/ruby/test_time.rb +++ b/test/ruby/test_time.rb @@ -209,6 +209,7 @@ def negative_time_t? end def test_timegm + pend "accesses current_repeat_count" if non_main_ractor? if negative_time_t? assert_equal(-0x80000000, Time.utc(1901, 12, 13, 20, 45, 52).tv_sec) assert_equal(-2, Time.utc(1969, 12, 31, 23, 59, 58).tv_sec) @@ -441,12 +442,14 @@ def test_marshal_zone assert_equal('UTC', t.zone) assert_equal('UTC', Marshal.load(Marshal.dump(t)).zone) - in_timezone('JST-9') do - t = Time.local(2013, 2, 24) - assert_equal('JST', Time.local(2013, 2, 24).zone) - t = Marshal.load(Marshal.dump(t)) - assert_equal('JST', t.zone) - assert_equal('JST', (t+1).zone, '[ruby-core:81892] [Bug #13710]') + unless multiple_ractors? + in_timezone('JST-9') do + t = Time.local(2013, 2, 24) + assert_equal('JST', Time.local(2013, 2, 24).zone) + t = Marshal.load(Marshal.dump(t)) + assert_equal('JST', t.zone) + assert_equal('JST', (t+1).zone, '[ruby-core:81892] [Bug #13710]') + end end end @@ -472,9 +475,10 @@ def test_marshal_to_s "[ruby-dev:44827] [Bug #5586]") end - Bug8795 = '[ruby-core:56648] [Bug #8795]' + Bug8795 = '[ruby-core:56648] [Bug #8795]'.freeze def test_marshal_broken_offset + omit "global side effects" if multiple_ractors? data = "\x04\bIu:\tTime\r\xEFF\x1C\x80\x00\x00\x00\x00\x06:\voffset" t1 = t2 = nil in_timezone('UTC') do @@ -488,6 +492,7 @@ def test_marshal_broken_offset end def test_marshal_broken_zone + omit "global side effects" if multiple_ractors? data = "\x04\bIu:\tTime\r\xEFF\x1C\x80\x00\x00\x00\x00\x06:\tzone" t1 = t2 = nil in_timezone('UTC') do @@ -570,6 +575,7 @@ def o.to_int; 10; end end def test_time_interval + pend "Timeout" if non_main_ractor? m = Thread::Mutex.new.lock assert_nothing_raised { Timeout.timeout(10) { @@ -1293,6 +1299,7 @@ def test_1970 end def test_2038 + pend "accesses current_repeat_count" if non_main_ractor? # Giveup to try 2nd test because some state is changed. omit if Test::Unit::Runner.current_repeat_count > 0 @@ -1440,6 +1447,7 @@ def test_memsize end def test_deconstruct_keys + omit "global side effects" if multiple_ractors? t = in_timezone('JST-9') { Time.local(2022, 10, 16, 14, 1, 30, 500) } assert_equal( {year: 2022, month: 10, day: 16, wday: 0, yday: 289, diff --git a/test/ruby/test_time_tz.rb b/test/ruby/test_time_tz.rb index f66cd9bec2eedc..dc15b029cc991a 100644 --- a/test/ruby/test_time_tz.rb +++ b/test/ruby/test_time_tz.rb @@ -17,6 +17,7 @@ class TestTimeTZ < Test::Unit::TestCase if force_tz_test module Util def with_tz(tz) + omit "global side effects" if multiple_ractors? && self.is_a?(TestTimeTZ) old = ENV["TZ"] begin ENV["TZ"] = tz @@ -29,6 +30,7 @@ def with_tz(tz) else module Util def with_tz(tz) + omit "global side effects" if multiple_ractors? && self.is_a?(TestTimeTZ) if ENV["TZ"] == tz yield end @@ -88,7 +90,7 @@ def group_by(e, &block) CORRECT_TOKYO_DST_1951 = with_tz("Asia/Tokyo") { if Time.local(1951, 5, 6, 12, 0, 0).dst? # noon, DST if Time.local(1951, 5, 6, 1, 0, 0).dst? # DST with fixed tzdata - Time.local(1951, 9, 8, 23, 0, 0).dst? ? "2018f" : "2018e" + Time.local(1951, 9, 8, 23, 0, 0).dst? ? "2018f".freeze : "2018e".freeze end end } @@ -96,7 +98,7 @@ def group_by(e, &block) Time.local(1994, 12, 31, 0, 0, 0).year == 1995 } CORRECT_SINGAPORE_1982 = with_tz("Asia/Singapore") { - "2022g" if Time.local(1981, 12, 31, 23, 59, 59).utc_offset == 8*3600 + "2022g".freeze if Time.local(1981, 12, 31, 23, 59, 59).utc_offset == 8*3600 } def time_to_s(t) @@ -379,20 +381,23 @@ def self.gen_zdump_test(data) expected = "%04d-%02d-%02d %02d:%02d:%02d %s" % (l+[format_gmtoff(gmtoff)]) mesg_utc = "TZ=#{tz} Time.utc(#{u.map {|arg| arg.inspect }.join(', ')})" mesg = "#{mesg_utc}.localtime" - define_method(gen_test_name(tz)) { - with_tz(tz) { - t = nil - assert_nothing_raised(mesg) { t = Time.utc(*u) } - assert_equal(expected_utc, time_to_s(t), mesg_utc) - assert_nothing_raised(mesg) { t.localtime } - assert_equal(expected, time_to_s(t), mesg) - assert_equal(gmtoff, t.gmtoff) - assert_equal(format_gmtoff(gmtoff), t.strftime("%z")) - assert_equal(format_gmtoff(gmtoff, true), t.strftime("%:z")) - assert_equal(format_gmtoff2(gmtoff), t.strftime("%::z")) - assert_equal(Encoding::US_ASCII, t.zone.encoding) - } - } + class_eval <<-RUBY, __FILE__, __LINE__+1 + def #{gen_test_name(tz).gsub(/[@\/]/, '_')} + tz = #{tz.inspect} + with_tz(tz) { + t = nil + assert_nothing_raised(#{mesg.inspect}) { t = Time.utc(*#{u.inspect}) } + assert_equal(#{expected_utc.inspect}, time_to_s(t), #{mesg_utc.inspect}) + assert_nothing_raised(#{mesg.inspect}) { t.localtime } + assert_equal(#{expected.inspect}, time_to_s(t), #{mesg.inspect}) + assert_equal(#{gmtoff.inspect}, t.gmtoff) + assert_equal(format_gmtoff(#{gmtoff.inspect}), t.strftime("%z")) + assert_equal(format_gmtoff(#{gmtoff.inspect}, true), t.strftime("%:z")) + assert_equal(format_gmtoff2(#{gmtoff.inspect}), t.strftime("%::z")) + assert_equal(Encoding::US_ASCII, t.zone.encoding) + } + end + RUBY } group_by(sample) {|tz, _, _, _| tz }.each {|tz, a| @@ -401,7 +406,11 @@ def self.gen_zdump_test(data) monotonic_to_past = i == 0 || (a[i-1][2] <=> l) < 0 monotonic_to_future = i == a.length-1 || (l <=> a[i+1][2]) < 0 if monotonic_to_past && monotonic_to_future - define_method(gen_test_name(tz)) { + class_eval <<-RUBY, __FILE__, __LINE__+1 + def #{gen_test_name(tz).gsub(/[@\/]/, '_')} + expected = #{expected.inspect} + tz = #{tz.inspect} + l = #{l.inspect} with_tz(tz) { assert_time_constructor(tz, expected, :local, l) assert_time_constructor(tz, expected, :local, l.reverse+[nil, nil, false, nil]) @@ -410,25 +419,40 @@ def self.gen_zdump_test(data) assert_time_constructor(tz, expected, :new, l+[:std]) assert_time_constructor(tz, expected, :new, l+[:dst]) } - } + end + RUBY elsif monotonic_to_past && !monotonic_to_future - define_method(gen_test_name(tz)) { + class_eval <<-RUBY, __FILE__, __LINE__+1 + def #{gen_test_name(tz).gsub(/[@\/]/, '_')} + expected = #{expected.inspect} + tz = #{tz.inspect} + l = #{l.inspect} with_tz(tz) { assert_time_constructor(tz, expected, :local, l.reverse+[nil, nil, true, nil]) assert_time_constructor(tz, expected, :new, l+[:dst]) } - } + end + RUBY elsif !monotonic_to_past && monotonic_to_future - define_method(gen_test_name(tz)) { + class_eval <<-RUBY, __FILE__, __LINE__+1 + def #{gen_test_name(tz).gsub(/[@\/]/, '_')} + expected = #{expected.inspect} + tz = #{tz.inspect} + l = #{l.inspect} with_tz(tz) { assert_time_constructor(tz, expected, :local, l.reverse+[nil, nil, false, nil]) assert_time_constructor(tz, expected, :new, l+[:std]) } - } + end + RUBY else - define_method(gen_test_name(tz)) { - flunk("time in reverse order: TZ=#{tz} #{expected}") - } + class_eval <<-RUBY, __FILE__, __LINE__+1 + def #{gen_test_name(tz).gsub(/[@\/]/, '_')} + expected = #{expected.inspect} + tz = #{tz.inspect} + flunk("time in reverse order: TZ=\#{tz} \#{expected}") + end + RUBY end } } @@ -548,13 +572,15 @@ def self.gen_variational_zdump_test(hint, data) } end - # tzdata-2014g fixed the offset for lisbon from -0:36:32 to -0:36:45. - # [ruby-core:65058] [Bug #10245] - gen_variational_zdump_test "lisbon", <<'End' if has_lisbon_tz + unless will_run_in_non_main_ractor? + # tzdata-2014g fixed the offset for lisbon from -0:36:32 to -0:36:45. + # [ruby-core:65058] [Bug #10245] + gen_variational_zdump_test "lisbon", <<'End' if has_lisbon_tz Europe/Lisbon Mon Jan 1 00:36:31 1912 UTC = Sun Dec 31 23:59:59 1911 LMT isdst=0 gmtoff=-2192 Europe/Lisbon Mon Jan 1 00:36:44 1912 UT = Sun Dec 31 23:59:59 1911 LMT isdst=0 gmtoff=-2205 Europe/Lisbon Sun Dec 31 23:59:59 1911 UT = Sun Dec 31 23:23:14 1911 LMT isdst=0 gmtoff=-2205 End + end class TZ attr_reader :name @@ -722,12 +748,12 @@ def nametest_marshal_compatibility(time_class, tzname, abbr, utc_offset) # t.zone may be a mere String or timezone object. end - ZONES = { + ZONES = Ractor.make_shareable({ "Asia/Tokyo" => ["JST", +9*3600], "America/Los_Angeles" => ["PST", -8*3600, "PDT", -7*3600], "Africa/Ndjamena" => ["WAT", +1*3600], "Etc/UTC" => ["UTC", 0], - } + }) def make_timezone(tzname, abbr, utc_offset, abbr2 = nil, utc_offset2 = nil) self.class::TIME_CLASS.find_timezone(tzname) @@ -744,22 +770,36 @@ def subtest_dst?(time_class, tz, tzarg, tzname, abbr, utc_offset) instance_methods(false).grep(/\Asub(?=test_)/) do |subtest| test = $' ZONES.each_pair do |tzname, (abbr, utc_offset, abbr2, utc_offset2)| - define_method("#{test}@#{tzname}") do + class_eval <<-RUBY, __FILE__, __LINE__+1 + def #{(test + '_' + tzname).gsub(/[^\w]/, '_')} + subtest = #{subtest.inspect} + tzname = #{tzname.inspect} + abbr = #{abbr.inspect} + utc_offset = #{utc_offset.inspect} + abbr2 = #{abbr2.inspect} + utc_offset2 = #{utc_offset2.inspect} tz = make_timezone(tzname, abbr, utc_offset, abbr2, utc_offset2) time_class = self.class::TIME_CLASS __send__(subtest, time_class, tz, tz, tzname, [abbr, abbr2], [utc_offset, utc_offset2]) __send__(subtest, time_class, tz, tzname, tzname, [abbr, abbr2], [utc_offset, utc_offset2]) end + RUBY end end instance_methods(false).grep(/\Aname(?=test_)/) do |subtest| test = $' ZONES.each_pair do |tzname, (abbr, utc_offset)| - define_method("#{test}@#{tzname}") do + class_eval <<-RUBY, __FILE__, __LINE__+1 + def #{(test + '_' + tzname).gsub(/[^\w]/, '_')} + subtest = #{subtest.inspect} + tzname = #{tzname.inspect} + abbr = #{abbr.inspect} + utc_offset = #{utc_offset.inspect} time_class = self.class::TIME_CLASS __send__(subtest, time_class, tzname, abbr, utc_offset) end + RUBY end end end diff --git a/test/ruby/test_trace.rb b/test/ruby/test_trace.rb index 5842f11aee6007..9b987d90432c80 100644 --- a/test/ruby/test_trace.rb +++ b/test/ruby/test_trace.rb @@ -3,6 +3,7 @@ class TestTrace < Test::Unit::TestCase def test_trace + omit "global variable access" if non_main_ractor? $x = 1234 $y = 0 trace_var :$x, proc{$y = $x} @@ -21,20 +22,22 @@ def test_trace end def test_trace_proc_that_raises_exception + omit "global variable access" if non_main_ractor? $x = 1234 trace_var :$x, proc { raise } assert_raise(RuntimeError) { $x = 42 } ensure - untrace_var :$x + untrace_var :$x if main_ractor? end def test_trace_string + omit "global variable access" if non_main_ractor? $x = 1234 trace_var :$x, "$y = :bar" $x = 42 assert_equal(:bar, $y) ensure - untrace_var :$x + untrace_var :$x if main_ractor? end def test_trace_break diff --git a/test/ruby/test_variable.rb b/test/ruby/test_variable.rb index cc784e7644fdf3..817a1e96b19036 100644 --- a/test/ruby/test_variable.rb +++ b/test/ruby/test_variable.rb @@ -36,10 +36,12 @@ def ruler4 Athena = Gods.clone def test_cloned_classes_copy_cvar_cache + omit "class variables" if non_main_ractor? assert_equal "Cronus", Athena.new.ruler0 end def test_setting_class_variable_on_module_through_inheritance + omit "class variables" if non_main_ractor? mod = Module.new mod.class_variable_set(:@@foo, 1) mod.freeze @@ -52,6 +54,7 @@ def test_setting_class_variable_on_module_through_inheritance Zeus = Gods.clone def test_cloned_allows_setting_cvar + omit "class variables" if non_main_ractor? Zeus.class_variable_set(:@@rule, "Athena") god = Gods.new.ruler0 @@ -63,6 +66,7 @@ def test_cloned_allows_setting_cvar end def test_singleton_class_included_class_variable + omit "class variables" if non_main_ractor? c = Class.new c.extend(Olympians) assert_empty(c.singleton_class.class_variables) @@ -91,6 +95,7 @@ def test_singleton_class_included_class_variable end def test_cvar_overtaken_by_parent_class + omit "class variables" if non_main_ractor? error = eval <<~EORB class Parent end @@ -121,6 +126,7 @@ class Parent end def test_cvar_overtaken_by_module + omit "class variables" if non_main_ractor? error = eval <<~EORB class ParentForModule @@cvar = 1 @@ -169,12 +175,14 @@ def t end def test_include_refined_module_class_variable + omit "class variables" if non_main_ractor? assert_warning('') do IncludeRefinedModuleClassVariableNoWarning.new.t end end def test_set_class_variable_on_frozen_object + omit "class variables" if non_main_ractor? set_cvar = EnvUtil.labeled_class("SetCVar") set_cvar.class_eval "#{<<~"begin;"}\n#{<<~'end;'}" begin; @@ -190,6 +198,7 @@ def self.set(val) end def test_variable + omit "class variables" if non_main_ractor? assert_instance_of(Integer, $$) # read-only variable @@ -253,6 +262,7 @@ def test_shadowing_block_local_variables end def test_global_variables + omit "global variables" if non_main_ractor? gv = global_variables assert_empty(gv.grep(/\A(?!\$)/)) assert_nil($~) @@ -349,6 +359,7 @@ def test_global_variable_0 end def test_global_variable_popped + omit "global variables" if non_main_ractor? assert_nothing_raised { EnvUtil.suppress_warning { eval("$foo; 1") @@ -432,9 +443,11 @@ def test_many_instance_variables objects = [Object.new, Hash.new, Module.new] objects.each do |obj| 1000.times do |i| + next if obj.is_a?(Module) && !main_ractor? obj.instance_variable_set("@var#{i}", i) end 1000.times do |i| + next if obj.is_a?(Module) && !main_ractor? assert_equal(i, obj.instance_variable_get("@var#{i}")) end end diff --git a/test/ruby/test_whileuntil.rb b/test/ruby/test_whileuntil.rb index ff6d29ac4a9f89..79a4b60ebcd845 100644 --- a/test/ruby/test_whileuntil.rb +++ b/test/ruby/test_whileuntil.rb @@ -59,14 +59,16 @@ def test_while end assert_equal(220, sum) - tmp = open(tmpfilename, "r") - while line = tmp.gets() - break if $. == 3 - assert_no_match(/vt100/, line) - assert_no_match(/Amiga/, line) - assert_no_match(/paper/, line) + if main_ractor? + tmp = open(tmpfilename, "r") + while line = tmp.gets() + break if $. == 3 + assert_no_match(/vt100/, line) + assert_no_match(/Amiga/, line) + assert_no_match(/paper/, line) + end + tmp.close end - tmp.close File.unlink tmpfilename or `/bin/rm -f "#{tmpfilename}"` assert_file.not_exist?(tmpfilename) diff --git a/test/ruby/test_yield.rb b/test/ruby/test_yield.rb index 9b2b2f37e06e04..f1658b1211c5b9 100644 --- a/test/ruby/test_yield.rb +++ b/test/ruby/test_yield.rb @@ -89,7 +89,7 @@ def test_block_args_unleashed require_relative 'sentence' class TestRubyYieldGen < Test::Unit::TestCase - Syntax = { + Syntax = Ractor.make_shareable({ :exp => [["0"], ["nil"], ["false"], @@ -178,7 +178,7 @@ class TestRubyYieldGen < Test::Unit::TestCase :test_proc => [['def m() yield', :command_args_noblock, ' end; r = m {', :block_param_def, 'vars', '}; undef m; r']], :test_lambda => [['def m() yield', :command_args_noblock, ' end; r = m(&lambda {', :block_param_def, 'vars', '}); undef m; r']], :test_enum => [['o = Object.new; def o.each() yield', :command_args_noblock, ' end; r1 = r2 = nil; o.each {|*x| r1 = x }; o.to_enum.each {|*x| r2 = x }; [r1, r2]']] - } + }) def rename_var(obj) vars = [] diff --git a/test/ruby/test_yjit.rb b/test/ruby/test_yjit.rb index 25399d1e628f33..91aa8dd8099eb3 100644 --- a/test/ruby/test_yjit.rb +++ b/test/ruby/test_yjit.rb @@ -1802,7 +1802,7 @@ def assert_no_exits(script) assert_compiles(script) end - ANY = Object.new + ANY = Object.new.freeze def assert_compiles( test_script, insns: [], call_threshold: 1, diff --git a/test/rubygems/helper.rb b/test/rubygems/helper.rb index 2f4abff1e84ca9..51c99a1bc5e211 100644 --- a/test/rubygems/helper.rb +++ b/test/rubygems/helper.rb @@ -724,7 +724,7 @@ def all_spec_names # # Use this with #write_file to build an installed gem. - def quick_gem(name, version="2") + def quick_gem(name, version = "2") require "rubygems/specification" spec = Gem::Specification.new do |s| @@ -1033,7 +1033,7 @@ def util_set_arch(arch) # Add +spec+ to +@fetcher+ serving the data in the file +path+. # +repo+ indicates which repo to make +spec+ appear to be in. - def add_to_fetcher(spec, path=nil, repo=@gem_repo) + def add_to_fetcher(spec, path = nil, repo = @gem_repo) path ||= spec.cache_file @fetcher.data["#{@gem_repo}gems/#{spec.file_name}"] = read_binary(path) end @@ -1206,7 +1206,7 @@ def wait_for_child_process_to_exit ## # Allows the proper version of +rake+ to be used for the test. - def build_rake_in(good=true) + def build_rake_in(good = true) gem_ruby = Gem.ruby Gem.ruby = self.class.rubybin env_rake = ENV["rake"] diff --git a/test/rubygems/installer_test_case.rb b/test/rubygems/installer_test_case.rb index 7a719843207c82..ded205c5f56273 100644 --- a/test/rubygems/installer_test_case.rb +++ b/test/rubygems/installer_test_case.rb @@ -215,7 +215,7 @@ def util_setup_gem(ui = @ui, force = true) ## # Creates an installer for +spec+ that will install into +gem_home+. - def util_installer(spec, gem_home, force=true) + def util_installer(spec, gem_home, force = true) Gem::Installer.at(spec.cache_file, install_dir: gem_home, force: force) diff --git a/test/rubygems/mock_gem_ui.rb b/test/rubygems/mock_gem_ui.rb index 218d4b6965d1eb..fb804c5555cf6d 100644 --- a/test/rubygems/mock_gem_ui.rb +++ b/test/rubygems/mock_gem_ui.rb @@ -77,7 +77,7 @@ def terminated? @terminated end - def terminate_interaction(status=0) + def terminate_interaction(status = 0) @terminated = true raise TermError, status if status != 0 diff --git a/test/rubygems/test_gem_ext_ext_conf_builder.rb b/test/rubygems/test_gem_ext_ext_conf_builder.rb index 218c6f3d5e3678..bc383e5540a9e3 100644 --- a/test/rubygems/test_gem_ext_ext_conf_builder.rb +++ b/test/rubygems/test_gem_ext_ext_conf_builder.rb @@ -15,15 +15,12 @@ def setup end def test_class_build - if Gem.java_platform? - pend("failing on jruby") - end - if vc_windows? && !nmake_found? pend("test_class_build skipped - nmake not found") end File.open File.join(@ext, "extconf.rb"), "w" do |extconf| + extconf.puts "return if Gem.java_platform?" extconf.puts "require 'mkmf'\ncreate_makefile 'foo'" end @@ -35,20 +32,22 @@ def test_class_build assert_match(/^current directory:/, output[0]) assert_match(/^#{Regexp.quote(Gem.ruby)}.* extconf.rb/, output[1]) - assert_equal "creating Makefile\n", output[2] - assert_match(/^current directory:/, output[3]) - assert_contains_make_command "clean", output[4] - assert_contains_make_command "", output[7] - assert_contains_make_command "install", output[10] + + if Gem.java_platform? + assert_includes(output, "Skipping make for extconf.rb as no Makefile was found.") + else + assert_equal "creating Makefile\n", output[2] + assert_match(/^current directory:/, output[3]) + assert_contains_make_command "clean", output[4] + assert_contains_make_command "", output[7] + assert_contains_make_command "install", output[10] + end + assert_empty Dir.glob(File.join(@ext, "siteconf*.rb")) assert_empty Dir.glob(File.join(@ext, ".gem.*")) end def test_class_build_rbconfig_make_prog - if Gem.java_platform? - pend("failing on jruby") - end - configure_args do File.open File.join(@ext, "extconf.rb"), "w" do |extconf| extconf.puts "require 'mkmf'\ncreate_makefile 'foo'" @@ -72,10 +71,6 @@ def test_class_build_env_make env_large_make = ENV.delete "MAKE" ENV["MAKE"] = "anothermake" - if Gem.java_platform? - pend("failing on jruby") - end - configure_args "" do File.open File.join(@ext, "extconf.rb"), "w" do |extconf| extconf.puts "require 'mkmf'\ncreate_makefile 'foo'" @@ -206,11 +201,11 @@ def test_class_make end def test_class_make_no_Makefile - error = assert_raise Gem::InstallError do + error = assert_raise Gem::Ext::Builder::NoMakefileError do Gem::Ext::ExtConfBuilder.make @ext, ["output"], @ext end - assert_equal "Makefile not found", error.message + assert_match(/No Makefile found/, error.message) end def configure_args(args = nil) diff --git a/test/rubygems/test_gem_remote_fetcher.rb b/test/rubygems/test_gem_remote_fetcher.rb index ca858cfda5d33d..5c1d89fad6934a 100644 --- a/test/rubygems/test_gem_remote_fetcher.rb +++ b/test/rubygems/test_gem_remote_fetcher.rb @@ -592,7 +592,7 @@ def test_yaml_error_on_size end end - def assert_error(exception_class=Exception) + def assert_error(exception_class = Exception) got_exception = false begin diff --git a/test/test_open3.rb b/test/test_open3.rb index 19277c8a66eca6..59eb95ad2c6cb4 100644 --- a/test/test_open3.rb +++ b/test/test_open3.rb @@ -27,12 +27,14 @@ def test_stdin end def test_stdout + omit if non_main_ractor? Open3.popen3(RUBY, '-e', 'STDOUT.print "foo"') {|i,o,e,t| assert_equal("foo", o.read) } end def test_stderr + omit if non_main_ractor? Open3.popen3(RUBY, '-e', 'STDERR.print "bar"') {|i,o,e,t| assert_equal("bar", e.read) } @@ -118,13 +120,13 @@ def with_reopen(io, arg) def test_popen2 with_pipe {|r, w| - with_reopen(STDERR, w) {|old| + with_reopen($stderr, w) {|old| w.close Open3.popen2(RUBY, '-e', 's=STDIN.read; STDOUT.print s+"o"; STDERR.print s+"e"') {|i,o,t| assert_kind_of(Thread, t) i.print "z" i.close - STDERR.reopen(old) + $stderr.reopen(old) assert_equal("zo", o.read) assert_equal("ze", r.read) } @@ -134,13 +136,13 @@ def test_popen2 def test_popen2e with_pipe {|r, w| - with_reopen(STDERR, w) {|old| + with_reopen($stderr, w) {|old| w.close Open3.popen2e(RUBY, '-e', 's=STDIN.read; STDOUT.print s+"o"; STDOUT.flush; STDERR.print s+"e"') {|i,o,t| assert_kind_of(Thread, t) i.print "y" i.close - STDERR.reopen(old) + $stderr.reopen(old) assert_equal("yoye", o.read) assert_equal("", r.read) } diff --git a/test/test_singleton.rb b/test/test_singleton.rb index e474a0ccc596f2..2c5125cf0ca4ca 100644 --- a/test/test_singleton.rb +++ b/test/test_singleton.rb @@ -7,6 +7,10 @@ class SingletonTest include Singleton end + def setup + omit if non_main_ractor? + end + def test_marshal o1 = SingletonTest.instance m = Marshal.dump(o1) diff --git a/test/test_time.rb b/test/test_time.rb index 55964d02fc1e78..d0c1111a4c11a5 100644 --- a/test/test_time.rb +++ b/test/test_time.rb @@ -572,8 +572,16 @@ def test_huge_precision instance_methods(false).grep(/\Asub(test_xmlschema.*)/) do |sub| test = $1 - define_method(test) {__send__(sub, :xmlschema)} - define_method(test.sub(/xmlschema/, 'iso8601')) {__send__(sub, :iso8601)} + class_eval <<-RUBY + def #{test} + __send__(#{sub.inspect}, :xmlschema) + end + def #{test.sub(/xmlschema/, 'iso8601')} + __send__(#{sub.inspect}, :iso8601) + end + RUBY + #define_method(test) {__send__(sub, :xmlschema)} + #define_method(test.sub(/xmlschema/, 'iso8601')) {__send__(sub, :iso8601)} end def test_parse_with_various_object diff --git a/test/test_tmpdir.rb b/test/test_tmpdir.rb index c91fc334ed73db..9c09c66710f3a6 100644 --- a/test/test_tmpdir.rb +++ b/test/test_tmpdir.rb @@ -154,10 +154,10 @@ def test_ractor Ractor.receive end end - dir = r.take + dir = r.value assert_file.directory? dir r.send true - r.take + r.join assert_file.not_exist? dir end end; diff --git a/tool/lib/core_assertions.rb b/tool/lib/core_assertions.rb index 47cc6574c878d1..08f5721e2c2e17 100644 --- a/tool/lib/core_assertions.rb +++ b/tool/lib/core_assertions.rb @@ -32,7 +32,7 @@ def filter bt end end - self.backtrace_filter = BacktraceFilter.new + self.backtrace_filter = BacktraceFilter.new.freeze def self.filter_backtrace bt # :nodoc: backtrace_filter.filter bt @@ -86,18 +86,21 @@ def mu_pp(obj) #:nodoc: end def assert_file - AssertFile + Ractor.current[:__AssertFile] ||= CoreAssertions.new_AssertFile end - FailDesc = proc do |status, message = "", out = ""| - now = Time.now - proc do - EnvUtil.failure_description(status, now, message, out) + FailDesc = Ractor.make_shareable(Ractor.current.instance_eval do + proc do |status, message = "", out = ""| + now = Time.now + proc do + EnvUtil.failure_description(status, now, message, out) + end end - end + end) def assert_in_out_err(args, test_stdin = "", test_stdout = [], test_stderr = [], message = nil, success: nil, failed: nil, **opt) + pend "#{__method__}" unless main_ractor? args = Array(args).dup args.insert((Hash === args[0] ? 1 : 0), '--disable=gems') stdout, stderr, status = EnvUtil.invoke_ruby(args, test_stdin, true, true, **opt) @@ -154,6 +157,7 @@ def syntax_check(code, fname, line) end def assert_no_memory_leak(args, prepare, code, message=nil, limit: 2.0, rss: false, **opt) + omit "separate process" unless main_ractor? # TODO: consider choosing some appropriate limit for RJIT and stop skipping this once it does not randomly fail pend 'assert_no_memory_leak may consider RJIT memory usage as leak' if defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled? # For previous versions which implemented MJIT @@ -270,6 +274,7 @@ def assert_valid_syntax(code, *args, **opt) end def assert_normal_exit(testsrc, message = '', child_env: nil, **opt) + pend "#{__method__}" unless main_ractor? assert_valid_syntax(testsrc, caller_locations(1, 1)[0]) if child_env child_env = [child_env] @@ -281,6 +286,7 @@ def assert_normal_exit(testsrc, message = '', child_env: nil, **opt) end def assert_ruby_status(args, test_stdin="", message=nil, **opt) + pend "#{__method__}" unless main_ractor? out, _, status = EnvUtil.invoke_ruby(args, test_stdin, true, :merge_to_stdout, **opt) desc = FailDesc[status, message, out] assert(!status.signaled?, desc) @@ -288,7 +294,7 @@ def assert_ruby_status(args, test_stdin="", message=nil, **opt) assert(status.success?, desc) end - ABORT_SIGNALS = Signal.list.values_at(*%w"ILL ABRT BUS SEGV TERM") + ABORT_SIGNALS = Signal.list.values_at(*%w"ILL ABRT BUS SEGV TERM").freeze def separated_runner(token, out = nil) include(*Test::Unit::TestCase.ancestors.select {|c| !c.is_a?(Class) }) @@ -304,6 +310,7 @@ def separated_runner(token, out = nil) end def assert_separately(args, file = nil, line = nil, src, ignore_stderr: nil, **opt) + pend "#{__method__}" unless main_ractor? unless file and line loc, = caller_locations(1,1) file ||= loc.path @@ -389,7 +396,7 @@ def assert_ractor(src, args: [], require: nil, require_relative: nil, file: nil, #{require} previous_verbose = $VERBOSE $VERBOSE = nil - Ractor.new {} # trigger initial warning + Ractor.new {}.join # trigger initial warning $VERBOSE = previous_verbose #{src} RUBY @@ -554,7 +561,7 @@ def assert_raise_kind_of(*exp, &b) e end - TEST_DIR = File.join(__dir__, "test/unit") #:nodoc: + TEST_DIR = File.join(__dir__, "test/unit").freeze #:nodoc: # :call-seq: # assert(test, [failure_message]) @@ -673,11 +680,17 @@ def assert_pattern_list(pattern_list, actual, message=nil) def assert_warning(pat, msg = nil) result = nil - stderr = EnvUtil.with_default_internal(of: pat) { - EnvUtil.verbose_warning { + if multiple_ractors? + stderr = EnvUtil.verbose_warning { result = yield } - } + else + stderr = EnvUtil.with_default_internal(of: pat) { + EnvUtil.verbose_warning { + result = yield + } + } + end msg = message(msg) {diff pat, stderr} assert(pat === stderr, msg) result @@ -699,27 +712,32 @@ def assert_deprecated_warn(mesg = /deprecated/, &block) end end - class << (AssertFile = Struct.new(:failure_message).new) - include Assertions - include CoreAssertions - def assert_file_predicate(predicate, *args) - if /\Anot_/ =~ predicate - predicate = $' - neg = " not" + def self.new_AssertFile + struct = Struct.new(:failure_message).new + # Uses method_missing, so contain it within its own object + class << struct + include Assertions + include CoreAssertions + def assert_file_predicate(predicate, *args) + if /\Anot_/ =~ predicate + predicate = $' + neg = " not" + end + result = File.__send__(predicate, *args) + result = !result if neg + mesg = "Expected file ".dup << args.shift.inspect + mesg << "#{neg} to be #{predicate}" + mesg << mu_pp(args).sub(/\A\[(.*)\]\z/m, '(\1)') unless args.empty? + mesg << " #{failure_message}" if failure_message + assert(result, mesg) end - result = File.__send__(predicate, *args) - result = !result if neg - mesg = "Expected file ".dup << args.shift.inspect - mesg << "#{neg} to be #{predicate}" - mesg << mu_pp(args).sub(/\A\[(.*)\]\z/m, '(\1)') unless args.empty? - mesg << " #{failure_message}" if failure_message - assert(result, mesg) - end - alias method_missing assert_file_predicate + alias method_missing assert_file_predicate - def for(message) - clone.tap {|a| a.failure_message = message} + def for(message) + clone.tap {|a| a.failure_message = message} + end end + struct end class AllFailures @@ -845,6 +863,7 @@ def assert_all_assertions_foreach(msg = nil, *keys, &block) # :yield: each elements of +seq+. def assert_linear_performance(seq, rehearsal: nil, pre: ->(n) {n}) pend "No PERFORMANCE_CLOCK found" unless defined?(PERFORMANCE_CLOCK) + pend "Timeout" unless main_ractor? # Timeout testing generally doesn't work when RJIT compilation happens. rjit_enabled = defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled? @@ -967,11 +986,20 @@ def self.glibc?(*ver) end def self.macos?(*ver) - unless defined?(@macos) - @macos = RUBY_PLATFORM.include?('darwin') && `sw_vers -productVersion`.scan(/\d+/).map(&:to_i) + is_main_ractor = Test::Unit::TestCase.main_ractor? + # Don't cache @macos as class ivar if we're running in a ractor. That means we shell out + # each time if we're not in main ractor, but this guard isn't used often so it's fine for now. + if !is_main_ractor || !defined?(@macos) + macos = RUBY_PLATFORM.include?('darwin') && `sw_vers -productVersion`.scan(/\d+/).map(&:to_i) end - version_match? ver, @macos + if macos && is_main_ractor + @macos = macos + elsif is_main_ractor + macos = @macos + end + version_match? ver, macos end + private def macos?(*ver) CoreAssertions.macos?(*ver) end diff --git a/tool/lib/envutil.rb b/tool/lib/envutil.rb index ab5e8d84e9c371..222d6d566d1390 100644 --- a/tool/lib/envutil.rb +++ b/tool/lib/envutil.rb @@ -36,12 +36,14 @@ def rubybin end module_function :rubybin - LANG_ENVS = %w"LANG LC_ALL LC_CTYPE" + LANG_ENVS = %w"LANG LC_ALL LC_CTYPE".freeze DEFAULT_SIGNALS = Signal.list DEFAULT_SIGNALS.delete("TERM") if /mswin|mingw/ =~ RUBY_PLATFORM + DEFAULT_SIGNALS.freeze - RUBYLIB = ENV["RUBYLIB"] + RUBYLIB = ENV["RUBYLIB"].to_s.freeze + MULTIPLE_RACTORS = ENV["RUBY_TESTS_WITH_RACTORS"].to_i > 1 class << self attr_accessor :timeout_scale @@ -54,7 +56,7 @@ def capture_global_values @original_verbose = $VERBOSE @original_warning = if defined?(Warning.categories) - Warning.categories.to_h {|i| [i, Warning[i]]} + Warning.categories.to_h {|i| [i, Warning[i]]}.freeze elsif defined?(Warning.[]) # 2.7+ %i[deprecated experimental performance].to_h do |i| [i, begin Warning[i]; rescue ArgumentError; end] @@ -194,6 +196,11 @@ def invoke_ruby(args, stdin_data = "", capture_stdout = false, capture_stderr = signal: :TERM, rubybin: EnvUtil.rubybin, precommand: nil, **opt) + + #if Ractor.current != Ractor.main + #raise Test::Unit::PendedError.new("not ractor safe (#{__method__}): uses spawn") + #end + timeout = apply_timeout_scale(timeout) in_c, in_p = IO.pipe @@ -293,7 +300,9 @@ def flush; end ensure stderr, $stderr = $stderr, stderr $VERBOSE = EnvUtil.original_verbose - EnvUtil.original_warning&.each {|i, v| Warning[i] = v} + unless MULTIPLE_RACTORS + EnvUtil.original_warning&.each {|i, v| Warning[i] = v} + end end module_function :verbose_warning @@ -328,16 +337,24 @@ def suppress_warning end module_function :suppress_warning + # NOTE: not safe to use when testing under multiple ractors. def under_gc_stress(stress = true) + raise Test::Unit::PendedError.new("not ractor safe (#{__method__})") if MULTIPLE_RACTORS + run_ensure = true stress, GC.stress = GC.stress, stress yield ensure - GC.stress = stress + if run_ensure + GC.stress = stress + end end module_function :under_gc_stress + # NOTE: not safe to use when testing under multiple ractors. def under_gc_compact_stress(val = :empty, &block) raise "compaction doesn't work well on s390x. Omit the test in the caller." if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077 + raise Test::Unit::PendedError.new("not ractor safe (#{__method__})") if MULTIPLE_RACTORS + run_ensure = true if GC.respond_to?(:auto_compact) auto_compact = GC.auto_compact @@ -346,33 +363,50 @@ def under_gc_compact_stress(val = :empty, &block) under_gc_stress(&block) ensure - GC.auto_compact = auto_compact if GC.respond_to?(:auto_compact) + if run_ensure + GC.auto_compact = auto_compact if GC.respond_to?(:auto_compact) + end end module_function :under_gc_compact_stress + # NOTE: not safe to use when testing under multiple ractors. def without_gc + raise Test::Unit::PendedError.new("not ractor safe (#{__method__})") if MULTIPLE_RACTORS + run_ensure = true prev_disabled = GC.disable yield ensure - GC.enable unless prev_disabled + if run_ensure + GC.enable unless prev_disabled + end end module_function :without_gc + # NOTE: not safe to use when testing under multiple ractors. def with_default_external(enc = nil, of: nil) + raise Test::Unit::PendedError.new("not ractor safe (#{__method__})") if MULTIPLE_RACTORS + run_ensure = true enc = of.encoding if defined?(of.encoding) suppress_warning { Encoding.default_external = enc } yield ensure - suppress_warning { Encoding.default_external = EnvUtil.original_external_encoding } + if run_ensure + suppress_warning { Encoding.default_external = EnvUtil.original_external_encoding } + end end module_function :with_default_external + # NOTE: not safe to use when testing under multiple ractors. def with_default_internal(enc = nil, of: nil) + raise Test::Unit::PendedError.new("not ractor safe (#{__method__})") if MULTIPLE_RACTORS + run_ensure = true enc = of.encoding if defined?(of.encoding) suppress_warning { Encoding.default_internal = enc } yield ensure - suppress_warning { Encoding.default_internal = EnvUtil.original_internal_encoding } + if run_ensure + suppress_warning { Encoding.default_internal = EnvUtil.original_internal_encoding } + end end module_function :with_default_internal @@ -401,8 +435,8 @@ def labeled_class(name, superclass = Object, &block) module_function :labeled_class if /darwin/ =~ RUBY_PLATFORM - DIAGNOSTIC_REPORTS_PATH = File.expand_path("~/Library/Logs/DiagnosticReports") - DIAGNOSTIC_REPORTS_TIMEFORMAT = '%Y-%m-%d-%H%M%S' + DIAGNOSTIC_REPORTS_PATH = File.expand_path("~/Library/Logs/DiagnosticReports").freeze + DIAGNOSTIC_REPORTS_TIMEFORMAT = '%Y-%m-%d-%H%M%S'.freeze @ruby_install_name = RbConfig::CONFIG['RUBY_INSTALL_NAME'] def self.diagnostic_reports(signame, pid, now) @@ -481,10 +515,12 @@ def self.gc_stress_to_class? if defined?(RbConfig) module RbConfig - @ruby = EnvUtil.rubybin + RUBY__ = EnvUtil.rubybin.freeze class << self undef ruby if method_defined?(:ruby) - attr_reader :ruby + def ruby + RUBY__ + end end dir = File.dirname(ruby) CONFIG['bindir'] = dir diff --git a/tool/lib/leakchecker.rb b/tool/lib/leakchecker.rb index 69aeb2c254cbfd..f572706d4abc26 100644 --- a/tool/lib/leakchecker.rb +++ b/tool/lib/leakchecker.rb @@ -14,6 +14,7 @@ def initialize end def check(test_name) + return if ENV["RUBY_TESTS_WITH_RACTORS"] if /i386-solaris/ =~ RUBY_PLATFORM && /TestGem/ =~ test_name GC.verify_internal_consistency end @@ -130,6 +131,7 @@ def check_fd_leak(test_name) def extend_tempfile_counter return if defined? LeakChecker::TempfileCounter + return if ENV["RUBY_TESTS_WITH_RACTORS"] m = Module.new { @count = 0 class << self @@ -150,6 +152,7 @@ class << Tempfile def find_tempfiles(prev_count=-1) return [prev_count, []] unless defined? Tempfile + return [prev_count,[]] if ENV["RUBY_TESTS_WITH_RACTORS"] extend_tempfile_counter count = TempfileCounter.count if prev_count == count @@ -164,6 +167,7 @@ def find_tempfiles(prev_count=-1) def check_tempfile_leak(test_name) return false unless defined? Tempfile + return false if ENV["RUBY_TESTS_WITH_RACTORS"] count1, initial_tempfiles = @tempfile_info count2, current_tempfiles = find_tempfiles(count1) leaked = false diff --git a/tool/lib/test/unit.rb b/tool/lib/test/unit.rb index 7d43e825e179eb..137fcb93e42936 100644 --- a/tool/lib/test/unit.rb +++ b/tool/lib/test/unit.rb @@ -171,8 +171,10 @@ def process_args(args = []) opts = option_parser setup_options(opts, options) opts.parse!(args) + @option_parser = nil orig_args -= args args = @init_hook.call(args, options) if @init_hook + @init_hook = nil non_options(args, options) @run_options = orig_args @@ -818,6 +820,10 @@ def _run_parallel suites, type, result end def _run_suites suites, type + if ENV["RUBY_TESTS_WITH_RACTORS"] + Ractor.make_shareable(RbConfig::CONFIG) + Ractor.make_shareable(RbConfig::MAKEFILE_CONFIG) + end _prepare_run(suites, type) @interrupt = nil result = [] @@ -1270,6 +1276,7 @@ def non_options(files, options) result = false files.each {|f| d = File.dirname(path = File.realpath(f)) + # TODO: get enc tests working with ractors unless $:.include? d $: << d end @@ -1513,7 +1520,7 @@ def options end @@installed_at_exit ||= false - @@out = $stdout + OUT = "$stdout" @@after_tests = [] @@current_repeat_count = 0 @@ -1531,15 +1538,29 @@ def self.after_tests &block # Returns the stream to use for output. def self.output - @@out + if String === OUT + eval OUT # due to Ractors + else + OUT + end end ## # Sets Test::Unit::Runner to write output to +stream+. $stdout is the default - # output + # output. NOTE: if not $stdout or $stderr, may not be ractor safe! def self.output= stream - @@out = stream + old_verbose = $VERBOSE + $VERBOSE = nil + fd_num = stream.to_i + if [1,2].include?(fd_num) + stream = fd_num == 1 ? "$stdout" : "$stderr" # best guess + const_set(:OUT, stream) + else + const_set(:OUT, stream) + end + ensure + $VERBOSE = old_verbose end ## @@ -1667,9 +1688,15 @@ def _run_suite suite, type trace = true end + run_tests_inside_ractors_num = ENV["RUBY_TESTS_WITH_RACTORS"].to_i + if run_tests_inside_ractors_num > 1 + def GC.stress=(val) + raise "Cannot call GC.stress=(val) concurrently (it might not be set back properly after teardown)" + end + end + tests_run = 0 assertions = all_test_methods.map { |method| - - inst = suite.new method + inst = suite.new method.to_s _start_method(inst) inst._assertions = 0 @@ -1680,13 +1707,68 @@ def _run_suite suite, type if trace ObjectSpace.trace_object_allocations {inst.run self} else - inst.run self + if run_tests_inside_ractors_num > 0 + old_report = self.report + old_failures = self.failures + old_errors = self.errors + old_skips = self.skips + old_assertion_count = self.assertion_count + old_test_count = self.test_count + self.report = [] + self.failures = 0 + self.errors = 0 + self.skips = 0 + self.assertion_count = 0 + self.test_count = 0 + rs = run_tests_inside_ractors_num.times.map do + Ractor.new(inst, self) do |instance, runner| + res = instance.run runner + testcase_copyable_ivars = {:@_assertions => true, :@__passed__ => true, :@__name__ => true} + runner_copyable_ivars = {:@report => true, :@failures => true, :@errors => true, :@skips => true, :@assertion_count => true, :@test_count => true} + instance.instance_variables.each do |ivar| + unless testcase_copyable_ivars[ivar] + instance.remove_instance_variable(ivar) + end + end + runner.instance_variables.each do |ivar| + unless runner_copyable_ivars[ivar] + runner.remove_instance_variable(ivar) + end + end + [instance, runner, res] + end + end + ractor_results = [] + while rs.any? + r, obj = Ractor.select(*rs) + inst, runner, res = *obj + ractor_results << [res, inst, runner] + rs.delete(r) + end + # ractors done + self.report = old_report + self.failures = old_failures + self.errors = old_errors + self.skips = old_skips + self.assertion_count = old_assertion_count + self.test_count = old_test_count + res = +"" + ractor_results.each do |(res0, inst, runner)| + res << res0 + _merge_results_from_ractor(inst, runner) + end + inst._assertions = self.assertion_count - old_assertion_count + res + else + inst.run self + end end + tests_run += 1 + print "%.2f s = " % (Time.now - start_time) if @verbose print result puts if @verbose - $stdout.flush leakchecker.check("#{inst.class}\##{inst.__name__}") @@ -1697,6 +1779,18 @@ def _run_suite suite, type return assertions.size, assertions.inject(0) { |sum, n| sum + n } end + def __init_runner(runner) + end + + def _merge_results_from_ractor(inst, runner_cpy) + self.report += runner_cpy.report + self.failures += runner_cpy.failures + self.errors += runner_cpy.errors + self.skips += runner_cpy.skips + self.assertion_count += inst._assertions + self.test_count += runner_cpy.test_count + end + def _start_method(inst) end def _end_method(inst) @@ -1734,8 +1828,6 @@ def initialize # :nodoc: @report = [] @errors = @failures = @skips = 0 @verbose = false - @mutex = Thread::Mutex.new - @info_signal = Signal.list['INFO'] @repeat_count = nil end @@ -1763,6 +1855,12 @@ def _run args = [] self.options.merge! args puts "Run options: #{help}" + ractors_num = ENV["RUBY_TESTS_WITH_RACTORS"].to_i + + if ractors_num > 0 + puts "\nNOTE: Running tests inside ractors (each test method inside #{ractors_num} " \ + "ractor#{ractors_num > 1 ? 's' : ''})" + end self.class.plugins.each do |plugin| send plugin diff --git a/tool/lib/test/unit/assertions.rb b/tool/lib/test/unit/assertions.rb index 19581fc3ab3ec0..782f3850629a4b 100644 --- a/tool/lib/test/unit/assertions.rb +++ b/tool/lib/test/unit/assertions.rb @@ -544,8 +544,12 @@ def skipped? # Takes a block and wraps it with the runner's shared mutex. def synchronize - Test::Unit::Runner.runner.synchronize do + if non_main_ractor? yield + else + Test::Unit::Runner.runner.synchronize do + yield + end end end diff --git a/tool/lib/test/unit/testcase.rb b/tool/lib/test/unit/testcase.rb index 51ffff37ebc376..c381cd1b767d78 100644 --- a/tool/lib/test/unit/testcase.rb +++ b/tool/lib/test/unit/testcase.rb @@ -50,6 +50,27 @@ def mingw? platform = RUBY_PLATFORM /mingw/ =~ platform end + def main_ractor? + return true if !defined?(Ractor) + Ractor.current == Ractor.main + end + + def non_main_ractor? + not main_ractor? + end + + def multiple_ractors? + ENV["RUBY_TESTS_WITH_RACTORS"].to_i > 1 + end + + # In order to guard generating methods dynamically that will run inside a ractor + def will_run_in_non_main_ractor? + ENV["RUBY_TESTS_WITH_RACTORS"].to_i > 0 + end + + def will_run_in_main_ractor? + not will_run_in_non_main_ractor? + end end ## @@ -141,7 +162,7 @@ class TestCase alias method_name __name__ PASSTHROUGH_EXCEPTIONS = [NoMemoryError, SignalException, - Interrupt, SystemExit] # :nodoc: + Interrupt, SystemExit].freeze # :nodoc: ## # Runs the tests reporting the status to +runner+ @@ -198,22 +219,24 @@ def run runner RUN_TEST_TRACE = "#{__FILE__}:#{__LINE__+3}:in `run_test'".freeze def run_test(name) - progname, $0 = $0, "#{$0}: #{self.class}##{name}" + progname, $0 = $0, "#{$0}: #{self.class}##{name}" if main_ractor? self.__send__(name) ensure - $@.delete(RUN_TEST_TRACE) if $@ - $0 = progname + if main_ractor? + $@.delete(RUN_TEST_TRACE) if $@ + $0 = progname + end end def initialize name # :nodoc: @__name__ = name @__io__ = nil @__passed__ = nil - @@__current__ = self # FIX: make thread local + Ractor.current[:__test_current__] = self end def self.current # :nodoc: - @@__current__ # FIX: make thread local + Ractor.current[:__test_current__] end ## diff --git a/tool/lib/tracepointchecker.rb b/tool/lib/tracepointchecker.rb index 3254e59357d493..7ff155227a2cb3 100644 --- a/tool/lib/tracepointchecker.rb +++ b/tool/lib/tracepointchecker.rb @@ -120,7 +120,7 @@ def self.check end if defined?(TracePoint.stat) class ::Test::Unit::TestCase - include TracePointChecker::ZombieTraceHunter + include TracePointChecker::ZombieTraceHunter unless ENV["RUBY_TESTS_WITH_RACTORS"] end if defined?(TracePointChecker) # TracePointChecker.start verbose: false diff --git a/tool/lib/zombie_hunter.rb b/tool/lib/zombie_hunter.rb index 33bc46794127f6..b1d3c9eaa5841b 100644 --- a/tool/lib/zombie_hunter.rb +++ b/tool/lib/zombie_hunter.rb @@ -3,7 +3,7 @@ module ZombieHunter def after_teardown super - assert_empty(Process.waitall) + assert_empty(Process.waitall) unless multiple_ractors? end end diff --git a/tool/make-snapshot b/tool/make-snapshot index c7ccc468d4c256..7d4fce4f153172 100755 --- a/tool/make-snapshot +++ b/tool/make-snapshot @@ -334,7 +334,7 @@ def package(vcs, rev, destdir, tmp = nil) FileUtils.rm(file, verbose: $VERBOSE) end - status = IO.read(File.dirname(__FILE__) + "/prereq.status") + status = File.read(File.dirname(__FILE__) + "/prereq.status") Dir.chdir(tmp) if tmp if !File.directory?(v) @@ -346,10 +346,10 @@ def package(vcs, rev, destdir, tmp = nil) File.open("#{v}/revision.h", "wb") {|f| f.puts vcs.revision_header(revision, modified) } - version ||= (versionhdr = IO.read("#{v}/version.h"))[RUBY_VERSION_PATTERN, 1] + version ||= (versionhdr = File.read("#{v}/version.h"))[RUBY_VERSION_PATTERN, 1] version ||= begin - include_ruby_versionhdr = IO.read("#{v}/include/ruby/version.h") + include_ruby_versionhdr = File.read("#{v}/include/ruby/version.h") api_major_version = include_ruby_versionhdr[/^\#define\s+RUBY_API_VERSION_MAJOR\s+([\d.]+)/, 1] api_minor_version = include_ruby_versionhdr[/^\#define\s+RUBY_API_VERSION_MINOR\s+([\d.]+)/, 1] version_teeny = versionhdr[/^\#define\s+RUBY_VERSION_TEENY\s+(\d+)/, 1] @@ -358,14 +358,14 @@ def package(vcs, rev, destdir, tmp = nil) version or return if patchlevel unless tag.empty? - versionhdr ||= IO.read("#{v}/version.h") + versionhdr ||= File.read("#{v}/version.h") patchlevel = versionhdr[/^\#define\s+RUBY_PATCHLEVEL\s+(\d+)/, 1] tag = (patchlevel ? "p#{patchlevel}" : vcs.revision_name(revision)) end elsif prerelease - versionhdr ||= IO.read("#{v}/version.h") + versionhdr ||= File.read("#{v}/version.h") versionhdr.sub!(/^\#\s*define\s+RUBY_PATCHLEVEL_STR\s+"\K.+?(?=")/, tag) or raise "no match of RUBY_PATCHLEVEL_STR to replace" - IO.write("#{v}/version.h", versionhdr) + File.write("#{v}/version.h", versionhdr) else tag ||= vcs.revision_name(revision) end @@ -430,7 +430,7 @@ def package(vcs, rev, destdir, tmp = nil) puts "cross.rb:", File.read("cross.rb").gsub(/^/, "> "), "" if $VERBOSE unless File.exist?("configure") print "creating configure..." - unless system([ENV["AUTOCONF"]]*2) + unless system(File.exist?(gen = "./autogen.sh") ? gen : [ENV["AUTOCONF"]]*2) puts $colorize.fail(" failed") return end @@ -439,11 +439,11 @@ def package(vcs, rev, destdir, tmp = nil) clean.add("autom4te.cache") clean.add("enc/unicode/data") print "creating prerequisites..." - if File.file?("common.mk") && /^prereq/ =~ commonmk = IO.read("common.mk") + if File.file?("common.mk") && /^prereq/ =~ commonmk = File.read("common.mk") puts extout = clean.add('tmp') begin - status = IO.read("tool/prereq.status") + status = File.read("tool/prereq.status") rescue Errno::ENOENT # use fallback file end @@ -456,7 +456,7 @@ def package(vcs, rev, destdir, tmp = nil) File.binwrite("#{defaults}/ruby.rb", "") miniruby = ENV['MINIRUBY'] + " -I. -I#{extout} -rcross" baseruby = ENV["BASERUBY"] - mk = (IO.read("template/Makefile.in") rescue IO.read("Makefile.in")). + mk = (File.read("template/Makefile.in") rescue File.read("Makefile.in")). gsub(/^@.*\n/, '') vars = { "EXTOUT"=>extout, @@ -480,7 +480,7 @@ def package(vcs, rev, destdir, tmp = nil) vars["UNICODE_VERSION"] = $unicode_version if $unicode_version args = vars.dup mk.gsub!(/@([A-Za-z_]\w*)@/) {args.delete($1); vars[$1] || ENV[$1]} - mk << commonmk.gsub(/\{\$([^(){}]*)[^{}]*\}/, "").sub(/^revision\.tmp::$/, '\& Makefile') + mk << commonmk.gsub(/\{\$([^(){}]*)[^{}]*\}/, "").gsub(/^!/, '-').sub(/^revision\.tmp::$/, '\& Makefile') mk << <<-'APPEND' update-download:: touch-unicode-files diff --git a/tool/prereq.status b/tool/prereq.status index 6de00c8a92bee8..da92460c8d66a1 100644 --- a/tool/prereq.status +++ b/tool/prereq.status @@ -41,4 +41,5 @@ s,@rubylibprefix@,,g s,@srcdir@,.,g s/@[A-Za-z][A-Za-z0-9_]*@//g -s/{\$([A-Za-z]*)}//g +s/{\$([^(){}]*)}//g +s/^!/-/ diff --git a/tool/sync_default_gems.rb b/tool/sync_default_gems.rb index 5794edaa83145a..029a27c8292b79 100755 --- a/tool/sync_default_gems.rb +++ b/tool/sync_default_gems.rb @@ -330,6 +330,7 @@ def sync_default_gems(gem) rm_rf("test/prism/snapshots") rm("prism/extconf.rb") + `git checkout prism/generate-srcs.mk.rb` when "resolv" rm_rf(%w[lib/resolv.* ext/win32/resolv test/resolv ext/win32/lib/win32/resolv.rb]) cp_r("#{upstream}/lib/resolv.rb", "lib") diff --git a/tool/update-deps b/tool/update-deps index 375986a915ab46..c927d2483e9a7a 100755 --- a/tool/update-deps +++ b/tool/update-deps @@ -96,6 +96,15 @@ result.each {|k,v| # They can be referenced as $(top_srcdir)/filename. # % ruby -e 'def g(d) Dir.chdir(d) { Dir["**/*.{c,h,inc,dmyh}"] } end; puts((g("repo_source_dir_after_build") - g("repo_source_dir_original")).sort)' FILES_IN_SOURCE_DIRECTORY = %w[ + prism/api_node.c + prism/ast.h + prism/diagnostic.c + prism/diagnostic.h + prism/node.c + prism/prettyprint.c + prism/serialize.c + prism/token_type.c + prism/version.h ] # Files built in the build directory (except extconf.h). @@ -157,16 +166,6 @@ FILES_NEED_VPATH = %w[ enc/trans/single_byte.c enc/trans/utf8_mac.c enc/trans/utf_16_32.c - - prism/api_node.c - prism/ast.h - prism/diagnostic.c - prism/diagnostic.h - prism/node.c - prism/prettyprint.c - prism/serialize.c - prism/token_type.c - prism/version.h ] # Multiple files with same filename. diff --git a/transcode.c b/transcode.c index 507bce78e1357f..94fbb3d8d6bbfc 100644 --- a/transcode.c +++ b/transcode.c @@ -1826,7 +1826,9 @@ rb_econv_asciicompat_encoding(const char *ascii_incompat_name) st_table *table2; struct asciicompat_encoding_t data = {0}; - RB_VM_LOCKING() { + unsigned int lev; + RB_VM_LOCK_ENTER_LEV(&lev); + { if (st_lookup(transcoder_table, (st_data_t)ascii_incompat_name, &v)) { table2 = (st_table *)v; /* @@ -1839,12 +1841,14 @@ rb_econv_asciicompat_encoding(const char *ascii_incompat_name) if (table2->num_entries == 1) { data.ascii_incompat_name = ascii_incompat_name; data.ascii_compat_name = NULL; + RB_VM_LOCK_LEAVE_LEV(&lev); st_foreach(table2, asciicompat_encoding_i, (st_data_t)&data); + RB_VM_LOCK_ENTER_LEV(&lev); } } - } + RB_VM_LOCK_LEAVE_LEV(&lev); return data.ascii_compat_name; // can be NULL } @@ -2989,10 +2993,12 @@ static rb_encoding * make_encoding(const char *name) { rb_encoding *enc; - RB_VM_LOCKING() { - enc = rb_enc_find(name); - if (!enc) + enc = rb_enc_find(name); + if (!enc) { + RB_VM_LOCKING() { + // TODO: check again. We may need to export `enc_registered` from encoding.c enc = make_dummy_encoding(name); + } } return enc; } @@ -3029,14 +3035,10 @@ econv_s_asciicompat_encoding(VALUE klass, VALUE arg) VALUE enc = Qnil; enc_arg(&arg, &arg_name, &arg_enc); - - RB_VM_LOCKING() { - result_name = rb_econv_asciicompat_encoding(arg_name); - - if (result_name) { - result_enc = make_encoding(result_name); - enc = rb_enc_from_encoding(result_enc); - } + result_name = rb_econv_asciicompat_encoding(arg_name); + result_enc = make_encoding(result_name); + if (result_name) { + enc = rb_enc_from_encoding(result_enc); } return enc; } diff --git a/variable.c b/variable.c index 4f0f83d20343fb..f9788b980df716 100644 --- a/variable.c +++ b/variable.c @@ -2995,9 +2995,10 @@ static VALUE autoload_synchronized(VALUE _arguments) { struct autoload_arguments *arguments = (struct autoload_arguments *)_arguments; + rb_const_entry_t constant_entry = {0}; - rb_const_entry_t *constant_entry = rb_const_lookup(arguments->module, arguments->name); - if (constant_entry && !UNDEF_P(constant_entry->value)) { + rb_const_entry_t *ce = rb_const_lookup(arguments->module, arguments->name, &constant_entry); + if (ce && !UNDEF_P(constant_entry.value)) { return Qfalse; } @@ -3198,13 +3199,15 @@ autoloading_const_entry(VALUE mod, ID id) return 0; } + static int autoload_defined_p(VALUE mod, ID id) { - rb_const_entry_t *ce = rb_const_lookup(mod, id); + rb_const_entry_t ce_out = {0}; + rb_const_entry_t *ce = rb_const_lookup(mod, id, &ce_out); // If there is no constant or the constant is not undefined (special marker for autoloading): - if (!ce || !UNDEF_P(ce->value)) { + if (!ce || !UNDEF_P(ce_out.value)) { // We are not autoloading: return 0; } @@ -3393,11 +3396,12 @@ autoload_try_load(VALUE _arguments) struct autoload_load_arguments *arguments = (struct autoload_load_arguments*)_arguments; VALUE result = autoload_feature_require(_arguments); + rb_const_entry_t ce_out = {0}; // After we loaded the feature, if the constant is not defined, we remove it completely: - rb_const_entry_t *ce = rb_const_lookup(arguments->module, arguments->name); + rb_const_entry_t *ce = rb_const_lookup(arguments->module, arguments->name, &ce_out); - if (!ce || UNDEF_P(ce->value)) { + if (!ce || UNDEF_P(ce_out.value)) { result = Qfalse; rb_const_remove(arguments->module, arguments->name); @@ -3429,10 +3433,11 @@ autoload_try_load(VALUE _arguments) VALUE rb_autoload_load(VALUE module, ID name) { - rb_const_entry_t *ce = rb_const_lookup(module, name); + rb_const_entry_t ce_out = {0}; + rb_const_entry_t *ce = rb_const_lookup(module, name, &ce_out); // We bail out as early as possible without any synchronisation: - if (!ce || !UNDEF_P(ce->value)) { + if (!ce || !UNDEF_P(ce_out.value)) { return Qfalse; } @@ -3450,7 +3455,7 @@ rb_autoload_load(VALUE module, ID name) // This confirms whether autoloading is required or not: if (autoload_const_value == Qfalse) return autoload_const_value; - arguments.flag = ce->flag & (CONST_DEPRECATED | CONST_VISIBILITY_MASK); + arguments.flag = ce_out.flag & (CONST_DEPRECATED | CONST_VISIBILITY_MASK); // Only one thread will enter here at a time: VALUE result = rb_mutex_synchronize(arguments.mutex, autoload_try_load, (VALUE)&arguments); @@ -3521,6 +3526,7 @@ rb_const_search_from(VALUE klass, ID id, int exclude, int recurse, int visibilit { VALUE value, current; bool first_iteration = true; + rb_const_entry_t ce_out = {0}; for (current = klass; RTEST(current); @@ -3542,13 +3548,13 @@ rb_const_search_from(VALUE klass, ID id, int exclude, int recurse, int visibilit if (BUILTIN_TYPE(tmp) == T_ICLASS) tmp = RBASIC(tmp)->klass; // Do the lookup. Loop in case of autoload. - while ((ce = rb_const_lookup(tmp, id))) { - if (visibility && RB_CONST_PRIVATE_P(ce)) { + while ((ce = rb_const_lookup(tmp, id, &ce_out))) { + if (visibility && RB_CONST_PRIVATE_P(&ce_out)) { GET_EC()->private_const_reference = tmp; return Qundef; } - rb_const_warn_if_deprecated(ce, tmp, id); - value = ce->value; + rb_const_warn_if_deprecated(&ce_out, tmp, id); + value = ce_out.value; if (UNDEF_P(value)) { struct autoload_const *ac; if (am == tmp) break; @@ -3628,16 +3634,17 @@ rb_const_location_from(VALUE klass, ID id, int exclude, int recurse, int visibil { while (RTEST(klass)) { rb_const_entry_t *ce; + rb_const_entry_t ce_out = {0}; - while ((ce = rb_const_lookup(klass, id))) { - if (visibility && RB_CONST_PRIVATE_P(ce)) { + while ((ce = rb_const_lookup(klass, id, &ce_out))) { + if (visibility && RB_CONST_PRIVATE_P(&ce_out)) { return Qnil; } if (exclude && klass == rb_cObject) { goto not_found; } - if (UNDEF_P(ce->value)) { // autoload + if (UNDEF_P(ce_out.value)) { // autoload VALUE autoload_const_value = autoload_data(klass, id); if (RTEST(autoload_const_value)) { struct autoload_const *autoload_const; @@ -3649,8 +3656,8 @@ rb_const_location_from(VALUE klass, ID id, int exclude, int recurse, int visibil } } - if (NIL_P(ce->file)) return rb_ary_new(); - return rb_assoc_new(ce->file, INT2NUM(ce->line)); + if (NIL_P(ce_out.file)) return rb_ary_new(); + return rb_assoc_new(ce_out.file, INT2NUM(ce_out.line)); } if (!recurse) break; klass = RCLASS_SUPER(klass); @@ -3707,39 +3714,42 @@ rb_mod_remove_const(VALUE mod, VALUE name) return rb_const_remove(mod, id); } -static rb_const_entry_t * const_lookup(struct rb_id_table *tbl, ID id); +static rb_const_entry_t * const_lookup(struct rb_id_table *tbl, ID id, rb_const_entry_t *ce_out); VALUE rb_const_remove(VALUE mod, ID id) { VALUE val; rb_const_entry_t *ce; + rb_const_entry_t ce_out = {0}; rb_check_frozen(mod); - ce = rb_const_lookup(mod, id); - if (!ce || !rb_id_table_delete(RCLASS_WRITABLE_CONST_TBL(mod), id)) { - if (rb_const_defined_at(mod, id)) { - rb_name_err_raise("cannot remove %2$s::%1$s", mod, ID2SYM(id)); - } + RB_VM_LOCKING() { + ce = rb_const_lookup(mod, id, &ce_out); + if (!ce || !rb_id_table_delete(RCLASS_WRITABLE_CONST_TBL(mod), id)) { + if (rb_const_defined_at(mod, id)) { + rb_name_err_raise("cannot remove %2$s::%1$s", mod, ID2SYM(id)); + } - undefined_constant(mod, ID2SYM(id)); - } + undefined_constant(mod, ID2SYM(id)); + } - rb_const_warn_if_deprecated(ce, mod, id); - rb_clear_constant_cache_for_id(id); + rb_const_warn_if_deprecated(ce, mod, id); + rb_clear_constant_cache_for_id(id); - val = ce->value; + val = ce_out.value; - if (UNDEF_P(val)) { - autoload_delete(mod, id); - val = Qnil; - } + if (UNDEF_P(val)) { + autoload_delete(mod, id); + val = Qnil; + } - if (ce != const_lookup(RCLASS_PRIME_CONST_TBL(mod), id)) { - ruby_xfree(ce); + if (ce != const_lookup(RCLASS_PRIME_CONST_TBL(mod), id, NULL)) { + ruby_xfree(ce); + } + // else - skip free'ing the ce because it still exists in the prime classext } - // else - skip free'ing the ce because it still exists in the prime classext return val; } @@ -3879,15 +3889,16 @@ rb_const_defined_0(VALUE klass, ID id, int exclude, int recurse, int visibility) VALUE tmp; int mod_retry = 0; rb_const_entry_t *ce; + rb_const_entry_t ce_out = {0}; tmp = klass; retry: while (tmp) { - if ((ce = rb_const_lookup(tmp, id))) { - if (visibility && RB_CONST_PRIVATE_P(ce)) { + if ((ce = rb_const_lookup(tmp, id, &ce_out))) { + if (visibility && RB_CONST_PRIVATE_P(&ce_out)) { return (int)Qfalse; } - if (UNDEF_P(ce->value) && !check_autoload_required(tmp, id, 0) && + if (UNDEF_P(ce_out.value) && !check_autoload_required(tmp, id, 0) && !rb_autoloading_value(tmp, id, NULL, NULL)) return (int)Qfalse; @@ -4015,8 +4026,8 @@ const_set(VALUE klass, ID id, VALUE val) RCLASS_WRITE_CONST_TBL(klass, tbl, false); rb_clear_constant_cache_for_id(id); ce = ZALLOC(rb_const_entry_t); - rb_id_table_insert(tbl, id, (VALUE)ce); setup_const_entry(ce, klass, val, CONST_PUBLIC); + rb_id_table_insert(tbl, id, (VALUE)ce); } else { struct autoload_const ac = { @@ -4029,6 +4040,7 @@ const_set(VALUE klass, ID id, VALUE val) } } + // TODO: I think this needs to be locked /* * Resolve and cache class name immediately to resolve ambiguity * and avoid order-dependency on const_tbl @@ -4093,6 +4105,8 @@ const_tbl_update(struct autoload_const *ac, int autoload_force) rb_const_flag_t visibility = ac->flag; rb_const_entry_t *ce; + ASSERT_vm_locking(); + if (rb_id_table_lookup(tbl, id, &value)) { ce = (rb_const_entry_t *)value; if (UNDEF_P(ce->value)) { @@ -4139,8 +4153,8 @@ const_tbl_update(struct autoload_const *ac, int autoload_force) rb_clear_constant_cache_for_id(id); ce = ZALLOC(rb_const_entry_t); - rb_id_table_insert(tbl, id, (VALUE)ce); setup_const_entry(ce, klass, val, visibility); + rb_id_table_insert(tbl, id, (VALUE)ce); } } @@ -4188,29 +4202,31 @@ set_const_visibility(VALUE mod, int argc, const VALUE *argv, return; } - for (i = 0; i < argc; i++) { - struct autoload_const *ac; - VALUE val = argv[i]; - id = rb_check_id(&val); - if (!id) { - undefined_constant(mod, val); - } - if ((ce = rb_const_lookup(mod, id))) { - ce->flag &= ~mask; - ce->flag |= flag; - if (UNDEF_P(ce->value)) { - struct autoload_data *ele; - - ele = autoload_data_for_named_constant(mod, id, &ac); - if (ele) { - ac->flag &= ~mask; - ac->flag |= flag; + RB_VM_LOCKING() { + for (i = 0; i < argc; i++) { + struct autoload_const *ac; + VALUE val = argv[i]; + id = rb_check_id(&val); + if (!id) { + undefined_constant(mod, val); + } + if ((ce = rb_const_lookup(mod, id, NULL))) { + ce->flag &= ~mask; + ce->flag |= flag; + if (UNDEF_P(ce->value)) { + struct autoload_data *ele; + + ele = autoload_data_for_named_constant(mod, id, &ac); + if (ele) { + ac->flag &= ~mask; + ac->flag |= flag; + } } + rb_clear_constant_cache_for_id(id); + } + else { + undefined_constant(mod, ID2SYM(id)); } - rb_clear_constant_cache_for_id(id); - } - else { - undefined_constant(mod, ID2SYM(id)); } } } @@ -4226,10 +4242,12 @@ rb_deprecate_constant(VALUE mod, const char *name) if (!(id = rb_check_id_cstr(name, len, NULL))) { undefined_constant(mod, rb_fstring_new(name, len)); } - if (!(ce = rb_const_lookup(mod, id))) { - undefined_constant(mod, ID2SYM(id)); + RB_VM_LOCKING() { + if (!(ce = rb_const_lookup(mod, id, NULL))) { + undefined_constant(mod, ID2SYM(id)); + } + ce->flag |= CONST_DEPRECATED; } - ce->flag |= CONST_DEPRECATED; } /* @@ -4786,23 +4804,30 @@ rb_fields_tbl_copy(VALUE dst, VALUE src) } static rb_const_entry_t * -const_lookup(struct rb_id_table *tbl, ID id) +const_lookup(struct rb_id_table *tbl, ID id, rb_const_entry_t *entry_out) { if (tbl) { + rb_const_entry_t *ce; VALUE val; bool r; RB_VM_LOCKING() { r = rb_id_table_lookup(tbl, id, &val); + if (r) { + ce = (rb_const_entry_t*)val; + if (entry_out) *entry_out = *ce; + } } - if (r) return (rb_const_entry_t *)val; + if (r) { + return ce; + } } return NULL; } rb_const_entry_t * -rb_const_lookup(VALUE klass, ID id) +rb_const_lookup(VALUE klass, ID id, rb_const_entry_t *entry_out) { - return const_lookup(RCLASS_CONST_TBL(klass), id); + return const_lookup(RCLASS_CONST_TBL(klass), id, entry_out); } diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 3aca1bc24f35eb..fd10921cd0fe1d 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -1092,10 +1092,11 @@ vm_get_ev_const(rb_execution_context_t *ec, VALUE orig_klass, ID id, bool allow_ if (!NIL_P(klass)) { VALUE av, am = 0; rb_const_entry_t *ce; + rb_const_entry_t ce_out = {0}; search_continue: - if ((ce = rb_const_lookup(klass, id))) { - rb_const_warn_if_deprecated(ce, klass, id); - val = ce->value; + if ((ce = rb_const_lookup(klass, id, &ce_out))) { + rb_const_warn_if_deprecated(&ce_out, klass, id); + val = ce_out.value; if (UNDEF_P(val)) { if (am == klass) break; am = klass; diff --git a/win32/setup.mak b/win32/setup.mak index 275ccda3bb6578..6af70d58300561 100644 --- a/win32/setup.mak +++ b/win32/setup.mak @@ -238,6 +238,16 @@ MACHINE = x86 @echo # ENCODING>>$(MAKEFILE) @$(MAKE) -l -f $(srcdir)/win32/enc-setup.mak srcdir="$(srcdir)" MAKEFILE=$(MAKEFILE) +!ifdef BASERUBY +ruby = $(BASERUBY) +!else ifndef ruby +ruby = ruby +!endif +$(srcdir)/prism/srcs.mk: + $(ruby:/=\) $(srcdir)/prism/generate-srcs.mk.rb > $@ + +-epilogue-: $(srcdir)/prism/srcs.mk + -epilogue-: nul @type << >>$(MAKEFILE) diff --git a/zjit/src/codegen.rs b/zjit/src/codegen.rs index cba25f9cdb85e7..a58950ab9acb4b 100644 --- a/zjit/src/codegen.rs +++ b/zjit/src/codegen.rs @@ -313,7 +313,7 @@ fn gen_insn(cb: &mut CodeBlock, jit: &mut JITState, asm: &mut Assembler, functio // Convert InsnId to lir::Opnd macro_rules! opnd { ($insn_id:ident) => { - jit.get_opnd(*$insn_id)? + jit.get_opnd($insn_id.clone())? }; } @@ -370,7 +370,7 @@ fn gen_insn(cb: &mut CodeBlock, jit: &mut JITState, asm: &mut Assembler, functio Insn::SetGlobal { id, val, state } => return gen_setglobal(jit, asm, *id, opnd!(val), &function.frame_state(*state)), Insn::GetGlobal { id, state: _ } => gen_getglobal(asm, *id), &Insn::GetLocal { ep_offset, level } => gen_getlocal_with_ep(asm, ep_offset, level)?, - Insn::SetLocal { val, ep_offset, level } => return gen_setlocal_with_ep(asm, opnd!(val), *ep_offset, *level), + &Insn::SetLocal { val, ep_offset, level } => return gen_setlocal_with_ep(asm, jit, function, val, ep_offset, level), Insn::GetConstantPath { ic, state } => gen_get_constant_path(jit, asm, *ic, &function.frame_state(*state))?, Insn::SetIvar { self_val, id, val, state: _ } => return gen_setivar(asm, opnd!(self_val), *id, opnd!(val)), Insn::SideExit { state, reason } => return gen_side_exit(jit, asm, reason, &function.frame_state(*state)), @@ -507,21 +507,19 @@ fn gen_getlocal_with_ep(asm: &mut Assembler, local_ep_offset: u32, level: u32) - /// Set a local variable from a higher scope or the heap. `local_ep_offset` is in number of VALUEs. /// We generate this instruction with level=0 only when the local variable is on the heap, so we /// can't optimize the level=0 case using the SP register. -fn gen_setlocal_with_ep(asm: &mut Assembler, val: Opnd, local_ep_offset: u32, level: u32) -> Option<()> { +fn gen_setlocal_with_ep(asm: &mut Assembler, jit: &JITState, function: &Function, val: InsnId, local_ep_offset: u32, level: u32) -> Option<()> { let ep = gen_get_ep(asm, level); - match val { - // If we're writing a constant, non-heap VALUE, do a raw memory write without - // running write barrier. - lir::Opnd::Value(const_val) if const_val.special_const_p() => { - let offset = -(SIZEOF_VALUE_I32 * i32::try_from(local_ep_offset).ok()?); - asm.mov(Opnd::mem(64, ep, offset), val); - } + + // When we've proved that we're writing an immediate, + // we can skip the write barrier. + if function.type_of(val).is_immediate() { + let offset = -(SIZEOF_VALUE_I32 * i32::try_from(local_ep_offset).ok()?); + asm.mov(Opnd::mem(64, ep, offset), jit.get_opnd(val)?); + } else { // We're potentially writing a reference to an IMEMO/env object, // so take care of the write barrier with a function. - _ => { - let local_index = c_int::try_from(local_ep_offset).ok().and_then(|idx| idx.checked_mul(-1))?; - asm_ccall!(asm, rb_vm_env_write, ep, local_index.into(), val); - } + let local_index = c_int::try_from(local_ep_offset).ok().and_then(|idx| idx.checked_mul(-1))?; + asm_ccall!(asm, rb_vm_env_write, ep, local_index.into(), jit.get_opnd(val)?); } Some(()) } diff --git a/zjit/src/hir.rs b/zjit/src/hir.rs index c88965f891ac59..c50c1ce985a69c 100644 --- a/zjit/src/hir.rs +++ b/zjit/src/hir.rs @@ -1264,7 +1264,7 @@ impl Function { self.union_find.borrow_mut().make_equal_to(insn, replacement); } - fn type_of(&self, insn: InsnId) -> Type { + pub fn type_of(&self, insn: InsnId) -> Type { assert!(self.insns[insn.0].has_output()); self.insn_types[self.union_find.borrow_mut().find(insn).0] } @@ -3798,40 +3798,6 @@ mod tests { use super::*; use expect_test::{expect, Expect}; - #[macro_export] - macro_rules! assert_matches { - ( $x:expr, $pat:pat ) => { - { - let val = $x; - if (!matches!(val, $pat)) { - eprintln!("{} ({:?}) does not match pattern {}", stringify!($x), val, stringify!($pat)); - assert!(false); - } - } - }; - } - - - #[track_caller] - fn assert_matches_value(insn: Option<&Insn>, val: VALUE) { - match insn { - Some(Insn::Const { val: Const::Value(spec) }) => { - assert_eq!(*spec, val); - } - _ => assert!(false, "Expected Const {val}, found {insn:?}"), - } - } - - #[track_caller] - fn assert_matches_const(insn: Option<&Insn>, expected: Const) { - match insn { - Some(Insn::Const { val }) => { - assert_eq!(*val, expected, "{val:?} does not match {expected:?}"); - } - _ => assert!(false, "Expected Const {expected:?}, found {insn:?}"), - } - } - #[track_caller] fn assert_method_hir(method: &str, hir: Expect) { let iseq = crate::cruby::with_rubyvm(|| get_method_iseq("self", method));