* 2022-01-18 [ci skip]
[ruby-80x24.org.git] / test / ruby / test_rubyoptions.rb
blob2cbd902f1fb3fa1abf7f3e45acc0603c395fe3c5
1 # -*- coding: us-ascii -*-
2 require 'test/unit'
4 require 'timeout'
5 require 'tmpdir'
6 require 'tempfile'
7 require_relative '../lib/jit_support'
9 class TestRubyOptions < Test::Unit::TestCase
10   def self.yjit_enabled? = defined?(RubyVM::YJIT.enabled?) && RubyVM::YJIT.enabled?
12   NO_JIT_DESCRIPTION =
13     if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # checking -DMJIT_FORCE_ENABLE
14       RUBY_DESCRIPTION.sub(/\+MJIT /, '')
15     elsif yjit_enabled? # checking -DYJIT_FORCE_ENABLE
16       RUBY_DESCRIPTION.sub(/\+YJIT /, '')
17     else
18       RUBY_DESCRIPTION
19     end
21   def write_file(filename, content)
22     File.open(filename, "w") {|f|
23       f << content
24     }
25   end
27   def with_tmpchdir
28     Dir.mktmpdir {|d|
29       d = File.realpath(d)
30       Dir.chdir(d) {
31         yield d
32       }
33     }
34   end
36   def test_source_file
37     assert_in_out_err([], "", [], [])
38   end
40   def test_usage
41     assert_in_out_err(%w(-h)) do |r, e|
42       assert_operator(r.size, :<=, 25)
43       longer = r[1..-1].select {|x| x.size > 80}
44       assert_equal([], longer)
45       assert_equal([], e)
46     end
47   end
49   def test_usage_long
50     assert_in_out_err(%w(--help)) do |r, e|
51       longer = r[1..-1].select {|x| x.size > 80}
52       assert_equal([], longer)
53       assert_equal([], e)
54     end
55   end
57   def test_option_variables
58     assert_in_out_err(["-e", 'p [$-p, $-l, $-a]']) do |r, e|
59       assert_equal(["[false, false, false]"], r)
60       assert_equal([], e)
61     end
63     assert_in_out_err(%w(-p -l -a -e) + ['p [$-p, $-l, $-a]'],
64                       "foo\nbar\nbaz") do |r, e|
65       assert_equal(
66         [ '[true, true, true]', 'foo',
67           '[true, true, true]', 'bar',
68           '[true, true, true]', 'baz' ], r)
69       assert_equal([], e)
70     end
71   end
73   def test_backtrace_limit
74     assert_in_out_err(%w(--backtrace-limit), "", [], /missing argument for --backtrace-limit/)
75     assert_in_out_err(%w(--backtrace-limit= 1), "", [], /missing argument for --backtrace-limit/)
76     assert_in_out_err(%w(--backtrace-limit=-1), "", [], /wrong limit for backtrace length/)
77     code = 'def f(n);n > 0 ? f(n-1) : raise;end;f(5)'
78     assert_in_out_err(%w(--backtrace-limit=1), code, [],
79                       [/.*unhandled exception\n/, /^\tfrom .*\n/,
80                        /^\t \.{3} \d+ levels\.{3}\n/])
81     assert_in_out_err(%w(--backtrace-limit=3), code, [],
82                       [/.*unhandled exception\n/, *[/^\tfrom .*\n/]*3,
83                        /^\t \.{3} \d+ levels\.{3}\n/])
84     assert_kind_of(Integer, Thread::Backtrace.limit)
85     assert_in_out_err(%w(--backtrace-limit=1), "p Thread::Backtrace.limit", ['1'], [])
86   end
88   def test_warning
89     save_rubyopt = ENV['RUBYOPT']
90     ENV['RUBYOPT'] = nil
91     assert_in_out_err(%w(-W0 -e) + ['p $-W'], "", %w(0), [])
92     assert_in_out_err(%w(-W1 -e) + ['p $-W'], "", %w(1), [])
93     assert_in_out_err(%w(-Wx -e) + ['p $-W'], "", %w(2), [])
94     assert_in_out_err(%w(-W -e) + ['p $-W'], "", %w(2), [])
95     assert_in_out_err(%w(-We) + ['p $-W'], "", %w(2), [])
96     assert_in_out_err(%w(-w -W0 -e) + ['p $-W'], "", %w(0), [])
97     assert_in_out_err(%w(-W:deprecated -e) + ['p Warning[:deprecated]'], "", %w(true), [])
98     assert_in_out_err(%w(-W:no-deprecated -e) + ['p Warning[:deprecated]'], "", %w(false), [])
99     assert_in_out_err(%w(-W:experimental -e) + ['p Warning[:experimental]'], "", %w(true), [])
100     assert_in_out_err(%w(-W:no-experimental -e) + ['p Warning[:experimental]'], "", %w(false), [])
101     assert_in_out_err(%w(-W:qux), "", [], /unknown warning category: `qux'/)
102     assert_in_out_err(%w(-w -e) + ['p Warning[:deprecated]'], "", %w(true), [])
103     assert_in_out_err(%w(-W -e) + ['p Warning[:deprecated]'], "", %w(true), [])
104     assert_in_out_err(%w(-We) + ['p Warning[:deprecated]'], "", %w(true), [])
105     assert_in_out_err(%w(-e) + ['p Warning[:deprecated]'], "", %w(false), [])
106     code = 'puts "#{$VERBOSE}:#{Warning[:deprecated]}:#{Warning[:experimental]}"'
107     Tempfile.create(["test_ruby_test_rubyoption", ".rb"]) do |t|
108       t.puts code
109       t.close
110       assert_in_out_err(["-r#{t.path}", '-e', code], "", %w(false:false:true false:false:true), [])
111       assert_in_out_err(["-r#{t.path}", '-w', '-e', code], "", %w(true:true:true true:true:true), [])
112       assert_in_out_err(["-r#{t.path}", '-W:deprecated', '-e', code], "", %w(false:true:true false:true:true), [])
113       assert_in_out_err(["-r#{t.path}", '-W:no-experimental', '-e', code], "", %w(false:false:false false:false:false), [])
114     end
115   ensure
116     ENV['RUBYOPT'] = save_rubyopt
117   end
119   def test_debug
120     assert_in_out_err(["--disable-gems", "-de", "p $DEBUG"], "", %w(true), [])
122     assert_in_out_err(["--disable-gems", "--debug", "-e", "p $DEBUG"],
123                       "", %w(true), [])
125     assert_in_out_err(["--disable-gems", "--debug-", "-e", "p $DEBUG"], "", %w(), /invalid option --debug-/)
126   end
128   q = Regexp.method(:quote)
129   VERSION_PATTERN =
130     case RUBY_ENGINE
131     when 'jruby'
132       /^jruby #{q[RUBY_ENGINE_VERSION]} \(#{q[RUBY_VERSION]}\).*? \[#{
133         q[RbConfig::CONFIG["host_os"]]}-#{q[RbConfig::CONFIG["host_cpu"]]}\]$/
134     else
135       /^ruby #{q[RUBY_VERSION]}(?:[p ]|dev|rc).*? \[#{q[RUBY_PLATFORM]}\]$/
136     end
137   private_constant :VERSION_PATTERN
139   VERSION_PATTERN_WITH_JIT =
140     case RUBY_ENGINE
141     when 'ruby'
142       /^ruby #{q[RUBY_VERSION]}(?:[p ]|dev|rc).*? \+MJIT \[#{q[RUBY_PLATFORM]}\]$/
143     else
144       VERSION_PATTERN
145     end
146   private_constant :VERSION_PATTERN_WITH_JIT
148   def test_verbose
149     assert_in_out_err([{'RUBY_YJIT_ENABLE' => nil}, "-vve", ""]) do |r, e|
150       assert_match(VERSION_PATTERN, r[0])
151       if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? && !mjit_force_enabled? # checking -DMJIT_FORCE_ENABLE
152         assert_equal(NO_JIT_DESCRIPTION, r[0])
153       elsif self.class.yjit_enabled? && !yjit_force_enabled? # checking -DYJIT_FORCE_ENABLE
154         assert_equal(NO_JIT_DESCRIPTION, r[0])
155       else
156         assert_equal(RUBY_DESCRIPTION, r[0])
157       end
158       assert_equal([], e)
159     end
161     assert_in_out_err(%w(--verbose -e) + ["p $VERBOSE"], "", %w(true), [])
163     assert_in_out_err(%w(--verbose), "", [], [])
164   end
166   def test_copyright
167     assert_in_out_err(%w(--copyright), "",
168                       /^ruby - Copyright \(C\) 1993-\d+ Yukihiro Matsumoto$/, [])
170     assert_in_out_err(%w(--verbose -e) + ["p $VERBOSE"], "", %w(true), [])
171   end
173   def test_enable
174     if JITSupport.supported?
175       assert_in_out_err(%w(--enable all -e) + [""], "", [], [])
176       assert_in_out_err(%w(--enable-all -e) + [""], "", [], [])
177       assert_in_out_err(%w(--enable=all -e) + [""], "", [], [])
178     end
179     assert_in_out_err(%w(--enable foobarbazqux -e) + [""], "", [],
180                       /unknown argument for --enable: `foobarbazqux'/)
181     assert_in_out_err(%w(--enable), "", [], /missing argument for --enable/)
182   end
184   def test_disable
185     assert_in_out_err(%w(--disable all -e) + [""], "", [], [])
186     assert_in_out_err(%w(--disable-all -e) + [""], "", [], [])
187     assert_in_out_err(%w(--disable=all -e) + [""], "", [], [])
188     assert_in_out_err(%w(--disable foobarbazqux -e) + [""], "", [],
189                       /unknown argument for --disable: `foobarbazqux'/)
190     assert_in_out_err(%w(--disable), "", [], /missing argument for --disable/)
191     assert_in_out_err(%w(--disable-gems -e) + ['p defined? Gem'], "", ["nil"], [])
192     assert_in_out_err(%w(--disable-did_you_mean -e) + ['p defined? DidYouMean'], "", ["nil"], [])
193     assert_in_out_err(%w(--disable-gems -e) + ['p defined? DidYouMean'], "", ["nil"], [])
194   end
196   def test_kanji
197     assert_in_out_err(%w(-KU), "p '\u3042'") do |r, e|
198       assert_equal("\"\u3042\"", r.join.force_encoding(Encoding::UTF_8))
199     end
200     line = '-eputs"\xc2\xa1".encoding'
201     env = {'RUBYOPT' => nil}
202     assert_in_out_err([env, '-Ke', line], "", ["EUC-JP"], [])
203     assert_in_out_err([env, '-KE', line], "", ["EUC-JP"], [])
204     assert_in_out_err([env, '-Ks', line], "", ["Windows-31J"], [])
205     assert_in_out_err([env, '-KS', line], "", ["Windows-31J"], [])
206     assert_in_out_err([env, '-Ku', line], "", ["UTF-8"], [])
207     assert_in_out_err([env, '-KU', line], "", ["UTF-8"], [])
208     assert_in_out_err([env, '-Kn', line], "", ["ASCII-8BIT"], [])
209     assert_in_out_err([env, '-KN', line], "", ["ASCII-8BIT"], [])
210     assert_in_out_err([env, '-wKe', line], "", ["EUC-JP"], /-K/)
211   end
213   def test_version
214     env = {'RUBY_YJIT_ENABLE' => nil} # unset in children
215     assert_in_out_err([env, '--version']) do |r, e|
216       assert_match(VERSION_PATTERN, r[0])
217       if ENV['RUBY_YJIT_ENABLE'] == '1'
218         assert_equal(NO_JIT_DESCRIPTION, r[0])
219       elsif defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? || self.class.yjit_enabled? # checking -D(M|Y)JIT_FORCE_ENABLE
220         assert_equal(EnvUtil.invoke_ruby(['-e', 'print RUBY_DESCRIPTION'], '', true).first, r[0])
221       else
222         assert_equal(RUBY_DESCRIPTION, r[0])
223       end
224       assert_equal([], e)
225     end
227     return if RbConfig::CONFIG["MJIT_SUPPORT"] == 'no'
228     return if yjit_force_enabled?
230     [
231       %w(--version --mjit --disable=mjit),
232       %w(--version --enable=mjit --disable=mjit),
233       %w(--version --enable-mjit --disable-mjit),
234       *([
235         %w(--version --jit --disable=jit),
236         %w(--version --enable=jit --disable=jit),
237         %w(--version --enable-jit --disable-jit),
238       ] unless JITSupport.yjit_supported?),
239     ].each do |args|
240       assert_in_out_err([env] + args) do |r, e|
241         assert_match(VERSION_PATTERN, r[0])
242         assert_match(NO_JIT_DESCRIPTION, r[0])
243         assert_equal([], e)
244       end
245     end
247     if JITSupport.supported?
248       [
249         %w(--version --mjit),
250         %w(--version --enable=mjit),
251         %w(--version --enable-mjit),
252         *([
253           %w(--version --jit),
254           %w(--version --enable=jit),
255           %w(--version --enable-jit),
256         ] unless JITSupport.yjit_supported?),
257       ].each do |args|
258         assert_in_out_err([env] + args) do |r, e|
259           assert_match(VERSION_PATTERN_WITH_JIT, r[0])
260           if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # checking -DMJIT_FORCE_ENABLE
261             assert_equal(RUBY_DESCRIPTION, r[0])
262           else
263             assert_equal(EnvUtil.invoke_ruby([env, '--mjit', '-e', 'print RUBY_DESCRIPTION'], '', true).first, r[0])
264           end
265           assert_equal([], e)
266         end
267       end
268     end
269   end
271   def test_eval
272     assert_in_out_err(%w(-e), "", [], /no code specified for -e \(RuntimeError\)/)
273   end
275   def test_require
276     require "pp"
277     assert_in_out_err(%w(-r pp -e) + ["pp 1"], "", %w(1), [])
278     assert_in_out_err(%w(-rpp -e) + ["pp 1"], "", %w(1), [])
279     assert_in_out_err(%w(-ep\ 1 -r), "", %w(1), [])
280     assert_in_out_err(%w(-r), "", [], [])
281   rescue LoadError
282   end
284   def test_include
285     d = Dir.tmpdir
286     assert_in_out_err(["-I" + d, "-e", ""], "", [], [])
287     assert_in_out_err(["-I", d, "-e", ""], "", [], [])
288   end
290   def test_separator
291     assert_in_out_err(%w(-000 -e) + ["print gets"], "foo\nbar\0baz", %W(foo bar\0baz), [])
293     assert_in_out_err(%w(-0141 -e) + ["print gets"], "foo\nbar\0baz", %w(foo ba), [])
295     assert_in_out_err(%w(-0e) + ["print gets"], "foo\nbar\0baz", %W(foo bar\0), [])
297     assert_in_out_err(%w(-00 -e) + ["p gets, gets"], "foo\nbar\n\nbaz\nzot\n\n\n", %w("foo\nbar\n\n" "baz\nzot\n\n"), [])
299     assert_in_out_err(%w(-00 -e) + ["p gets, gets"], "foo\nbar\n\n\n\nbaz\n", %w("foo\nbar\n\n" "baz\n"), [])
300   end
302   def test_autosplit
303     assert_in_out_err(%w(-W0 -an -F: -e) + ["p $F"], "foo:bar:baz\nqux:quux:quuux\n",
304                       ['["foo", "bar", "baz\n"]', '["qux", "quux", "quuux\n"]'], [])
305   end
307   def test_chdir
308     assert_in_out_err(%w(-C), "", [], /Can't chdir/)
310     assert_in_out_err(%w(-C test_ruby_test_rubyoptions_foobarbazqux), "", [], /Can't chdir/)
312     d = Dir.tmpdir
313     assert_in_out_err(["-C", d, "-e", "puts Dir.pwd"]) do |r, e|
314       assert_file.identical?(r.join, d)
315       assert_equal([], e)
316     end
317   end
319   def test_yydebug
320     assert_in_out_err(["-ye", ""]) do |r, e|
321       assert_not_equal([], r)
322       assert_equal([], e)
323     end
325     assert_in_out_err(%w(--yydebug -e) + [""]) do |r, e|
326       assert_not_equal([], r)
327       assert_equal([], e)
328     end
329   end
331   def test_encoding
332     assert_in_out_err(%w(--encoding), "", [], /missing argument for --encoding/)
334     assert_in_out_err(%w(--encoding test_ruby_test_rubyoptions_foobarbazqux), "", [],
335                       /unknown encoding name - test_ruby_test_rubyoptions_foobarbazqux \(RuntimeError\)/)
337     if /mswin|mingw|aix|android/ =~ RUBY_PLATFORM &&
338       (str = "\u3042".force_encoding(Encoding.find("external"))).valid_encoding?
339       # This result depends on locale because LANG=C doesn't affect locale
340       # on Windows.
341       # On AIX, the source encoding of stdin with LANG=C is ISO-8859-1,
342       # which allows \u3042.
343       out, err = [str], []
344     else
345       out, err = [], /invalid multibyte char/
346     end
347     assert_in_out_err(%w(-Eutf-8), "puts '\u3042'", out, err)
348     assert_in_out_err(%w(--encoding utf-8), "puts '\u3042'", out, err)
349   end
351   def test_syntax_check
352     assert_in_out_err(%w(-c -e a=1+1 -e !a), "", ["Syntax OK"], [])
353   end
355   def test_invalid_option
356     assert_in_out_err(%w(--foobarbazqux), "", [], /invalid option --foobarbazqux/)
358     assert_in_out_err(%W(-\r -e) + [""], "", [], [])
360     assert_in_out_err(%W(-\rx), "", [], /invalid option -\\r  \(-h will show valid options\) \(RuntimeError\)/)
362     assert_in_out_err(%W(-\x01), "", [], /invalid option -\\x01  \(-h will show valid options\) \(RuntimeError\)/)
364     assert_in_out_err(%w(-Z), "", [], /invalid option -Z  \(-h will show valid options\) \(RuntimeError\)/)
365   end
367   def test_rubyopt
368     rubyopt_orig = ENV['RUBYOPT']
370     ENV['RUBYOPT'] = ' - -'
371     assert_in_out_err([], "", [], [])
373     ENV['RUBYOPT'] = '-e "p 1"'
374     assert_in_out_err([], "", [], /invalid switch in RUBYOPT: -e \(RuntimeError\)/)
376     ENV['RUBYOPT'] = '-Eus-ascii -KN'
377     assert_in_out_err(%w(-Eutf-8 -KU), "p '\u3042'") do |r, e|
378       assert_equal("\"\u3042\"", r.join.force_encoding(Encoding::UTF_8))
379       assert_equal([], e)
380     end
382     ENV['RUBYOPT'] = '-w'
383     assert_in_out_err(%w(), "p $VERBOSE", ["true"])
384     assert_in_out_err(%w(-W1), "p $VERBOSE", ["false"])
385     assert_in_out_err(%w(-W0), "p $VERBOSE", ["nil"])
386     assert_in_out_err(%w(), "p Warning[:deprecated]", ["true"])
387     assert_in_out_err(%w(-W0), "p Warning[:deprecated]", ["false"])
388     assert_in_out_err(%w(-W1), "p Warning[:deprecated]", ["false"])
389     assert_in_out_err(%w(-W2), "p Warning[:deprecated]", ["true"])
390     ENV['RUBYOPT'] = '-W:deprecated'
391     assert_in_out_err(%w(), "p Warning[:deprecated]", ["true"])
392     ENV['RUBYOPT'] = '-W:no-deprecated'
393     assert_in_out_err(%w(), "p Warning[:deprecated]", ["false"])
394     ENV['RUBYOPT'] = '-W:experimental'
395     assert_in_out_err(%w(), "p Warning[:experimental]", ["true"])
396     ENV['RUBYOPT'] = '-W:no-experimental'
397     assert_in_out_err(%w(), "p Warning[:experimental]", ["false"])
398     ENV['RUBYOPT'] = '-W:qux'
399     assert_in_out_err(%w(), "", [], /unknown warning category: `qux'/)
400   ensure
401     if rubyopt_orig
402       ENV['RUBYOPT'] = rubyopt_orig
403     else
404       ENV.delete('RUBYOPT')
405     end
406   end
408   def test_search
409     rubypath_orig = ENV['RUBYPATH']
410     path_orig = ENV['PATH']
412     Tempfile.create(["test_ruby_test_rubyoption", ".rb"]) {|t|
413       t.puts "p 1"
414       t.close
416       @verbose = $VERBOSE
417       $VERBOSE = nil
419       path, name = File.split(t.path)
421       ENV['PATH'] = (path_orig && RbConfig::CONFIG['LIBPATHENV'] == 'PATH') ?
422           [path, path_orig].join(File::PATH_SEPARATOR) : path
423       assert_in_out_err(%w(-S) + [name], "", %w(1), [])
424       ENV['PATH'] = path_orig
426       ENV['RUBYPATH'] = path
427       assert_in_out_err(%w(-S) + [name], "", %w(1), [])
428     }
430   ensure
431     if rubypath_orig
432       ENV['RUBYPATH'] = rubypath_orig
433     else
434       ENV.delete('RUBYPATH')
435     end
436     if path_orig
437       ENV['PATH'] = path_orig
438     else
439       ENV.delete('PATH')
440     end
441     $VERBOSE = @verbose
442   end
444   def test_shebang
445     assert_in_out_err([], "#! /test_r_u_b_y_test_r_u_b_y_options_foobarbazqux\r\np 1\r\n",
446                       [], /: no Ruby script found in input/)
448     assert_in_out_err([], "#! /test_r_u_b_y_test_r_u_b_y_options_foobarbazqux -foo -bar\r\np 1\r\n",
449                       [], /: no Ruby script found in input/)
451     warning = /mswin|mingw/ =~ RUBY_PLATFORM ? [] : /shebang line ending with \\r/
452     assert_in_out_err([{'RUBYOPT' => nil}], "#!ruby -KU -Eutf-8\r\np \"\u3042\"\r\n",
453                       ["\"\u3042\""], warning,
454                       encoding: Encoding::UTF_8)
456     bug4118 = '[ruby-dev:42680]'
457     assert_in_out_err(%w[], "#!/bin/sh\n""#!shebang\n""#!ruby\n""puts __LINE__\n",
458                       %w[4], [], bug4118)
459     assert_in_out_err(%w[-x], "#!/bin/sh\n""#!shebang\n""#!ruby\n""puts __LINE__\n",
460                       %w[4], [], bug4118)
462     assert_ruby_status(%w[], "#! ruby -- /", '[ruby-core:82267] [Bug #13786]')
464     assert_ruby_status(%w[], "#!")
465     assert_in_out_err(%w[-c], "#!", ["Syntax OK"])
466   end
468   def test_flag_in_shebang
469     Tempfile.create(%w"pflag .rb") do |script|
470       code = "#!ruby -p"
471       script.puts(code)
472       script.close
473       assert_in_out_err([script.path, script.path], '', [code])
474     end
475     Tempfile.create(%w"sflag .rb") do |script|
476       script.puts("#!ruby -s")
477       script.puts("p $abc")
478       script.close
479       assert_in_out_err([script.path, "-abc=foo"], '', ['"foo"'])
480     end
481   end
483   def test_sflag
484     assert_in_out_err(%w(- -abc -def=foo -ghi-jkl -- -xyz),
485                       "#!ruby -s\np [$abc, $def, $ghi_jkl, defined?($xyz)]\n",
486                       ['[true, "foo", true, nil]'], [])
488     assert_in_out_err(%w(- -#), "#!ruby -s\n", [],
489                       /invalid name for global variable - -# \(NameError\)/)
491     assert_in_out_err(%w(- -#=foo), "#!ruby -s\n", [],
492                       /invalid name for global variable - -# \(NameError\)/)
493   end
495   def test_assignment_in_conditional
496     Tempfile.create(["test_ruby_test_rubyoption", ".rb"]) {|t|
497       t.puts "if a = 1"
498       t.puts "end"
499       t.puts "0.times do"
500       t.puts "  if b = 2"
501       t.puts "    a += b"
502       t.puts "  end"
503       t.puts "end"
504       t.flush
505       warning = ' warning: found `= literal\' in conditional, should be =='
506       err = ["#{t.path}:1:#{warning}",
507              "#{t.path}:4:#{warning}",
508             ]
509       bug2136 = '[ruby-dev:39363]'
510       assert_in_out_err(["-w", t.path], "", [], err, bug2136)
511       assert_in_out_err(["-wr", t.path, "-e", ""], "", [], err, bug2136)
513       t.rewind
514       t.truncate(0)
515       t.puts "if a = ''; end"
516       t.puts "if a = []; end"
517       t.puts "if a = [1]; end"
518       t.puts "if a = [a]; end"
519       t.puts "if a = {}; end"
520       t.puts "if a = {1=>2}; end"
521       t.puts "if a = {3=>a}; end"
522       t.flush
523       err = ["#{t.path}:1:#{warning}",
524              "#{t.path}:2:#{warning}",
525              "#{t.path}:3:#{warning}",
526              "#{t.path}:5:#{warning}",
527              "#{t.path}:6:#{warning}",
528             ]
529       feature4299 = '[ruby-dev:43083]'
530       assert_in_out_err(["-w", t.path], "", [], err, feature4299)
531       assert_in_out_err(["-wr", t.path, "-e", ""], "", [], err, feature4299)
532     }
533   end
535   def test_indentation_check
536     all_assertions do |a|
537       Tempfile.create(["test_ruby_test_rubyoption", ".rb"]) do |t|
538         [
539           "begin", "if false", "for _ in []", "while false",
540           "def foo", "class X", "module M",
541           ["-> do", "end"], ["-> {", "}"],
542           ["if false;", "else ; end"],
543           ["if false;", "elsif false ; end"],
544           ["begin", "rescue ; end"],
545           ["begin rescue", "else ; end"],
546           ["begin", "ensure ; end"],
547           ["  case nil", "when true; end"],
548           ["case nil; when true", "end"],
549           ["if false;", "end", "if true\nelse ", "end"],
550           ["else", " end", "_ = if true\n"],
551           ["begin\n    def f() = nil", "end"],
552           ["begin\n    def self.f() = nil", "end"],
553         ].each do
554           |b, e = 'end', pre = nil, post = nil|
555           src = ["#{pre}#{b}\n", " #{e}\n#{post}"]
556           k = b[/\A\s*(\S+)/, 1]
557           e = e[/\A\s*(\S+)/, 1]
558           n = 1 + src[0].count("\n")
559           n1 = 1 + (pre ? pre.count("\n") : 0)
561           a.for("no directives with #{src}") do
562             err = ["#{t.path}:#{n}: warning: mismatched indentations at '#{e}' with '#{k}' at #{n1}"]
563             t.rewind
564             t.truncate(0)
565             t.puts src
566             t.flush
567             assert_in_out_err(["-w", t.path], "", [], err)
568             assert_in_out_err(["-wr", t.path, "-e", ""], "", [], err)
569           end
571           a.for("false directive with #{src}") do
572             t.rewind
573             t.truncate(0)
574             t.puts "# -*- warn-indent: false -*-"
575             t.puts src
576             t.flush
577             assert_in_out_err(["-w", t.path], "", [], [], '[ruby-core:25442]')
578           end
580           a.for("false and true directives with #{src}") do
581             err = ["#{t.path}:#{n+2}: warning: mismatched indentations at '#{e}' with '#{k}' at #{n1+2}"]
582             t.rewind
583             t.truncate(0)
584             t.puts "# -*- warn-indent: false -*-"
585             t.puts "# -*- warn-indent: true -*-"
586             t.puts src
587             t.flush
588             assert_in_out_err(["-w", t.path], "", [], err, '[ruby-core:25442]')
589           end
591           a.for("false directives after #{src}") do
592             t.rewind
593             t.truncate(0)
594             t.puts "# -*- warn-indent: true -*-"
595             t.puts src[0]
596             t.puts "# -*- warn-indent: false -*-"
597             t.puts src[1]
598             t.flush
599             assert_in_out_err(["-w", t.path], "", [], [], '[ruby-core:25442]')
600           end
602           a.for("BOM with #{src}") do
603             err = ["#{t.path}:#{n}: warning: mismatched indentations at '#{e}' with '#{k}' at #{n1}"]
604             t.rewind
605             t.truncate(0)
606             t.print "\u{feff}"
607             t.puts src
608             t.flush
609             assert_in_out_err(["-w", t.path], "", [], err)
610             assert_in_out_err(["-wr", t.path, "-e", ""], "", [], err)
611           end
612         end
613       end
614     end
615   end
617   def test_notfound
618     notexist = "./notexist.rb"
619     dir, *rubybin = RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME', 'EXEEXT')
620     rubybin = "#{dir}/#{rubybin.join('')}"
621     rubybin.tr!('/', '\\') if /mswin|mingw/ =~ RUBY_PLATFORM
622     rubybin = Regexp.quote(rubybin)
623     pat = Regexp.quote(notexist)
624     bug1573 = '[ruby-core:23717]'
625     assert_file.not_exist?(notexist)
626     assert_in_out_err(["-r", notexist, "-ep"], "", [], /.* -- #{pat} \(LoadError\)/, bug1573)
627     assert_in_out_err([notexist], "", [], /#{rubybin}:.* -- #{pat} \(LoadError\)/, bug1573)
628   end
630   def test_program_name
631     ruby = EnvUtil.rubybin
632     IO.popen([ruby, '-e', 'print $0']) {|f|
633       assert_equal('-e', f.read)
634     }
635     IO.popen([ruby, '-'], 'r+') {|f|
636       f << 'print $0'
637       f.close_write
638       assert_equal('-', f.read)
639     }
640     Dir.mktmpdir {|d|
641       n1 = File.join(d, 't1')
642       open(n1, 'w') {|f| f << 'print $0' }
643       IO.popen([ruby, n1]) {|f|
644         assert_equal(n1, f.read)
645       }
646       if File.respond_to? :symlink
647         n2 = File.join(d, 't2')
648         begin
649           File.symlink(n1, n2)
650         rescue Errno::EACCES
651         else
652           IO.popen([ruby, n2]) {|f|
653             assert_equal(n2, f.read)
654           }
655         end
656       end
657       Dir.chdir(d) {
658         n3 = '-e'
659         open(n3, 'w') {|f| f << 'print $0' }
660         IO.popen([ruby, '--', n3]) {|f|
661           assert_equal(n3, f.read)
662         }
663         n4 = '-'
664         IO.popen([ruby, '--', n4], 'r+') {|f|
665           f << 'print $0'
666           f.close_write
667           assert_equal(n4, f.read)
668         }
669       }
670     }
671   end
673   if /linux|freebsd|netbsd|openbsd|darwin/ =~ RUBY_PLATFORM
674     PSCMD = EnvUtil.find_executable("ps", "-o", "command", "-p", $$.to_s) {|out| /ruby/=~out}
675     PSCMD&.pop
676   end
678   def test_set_program_name
679     omit "platform dependent feature" unless defined?(PSCMD) and PSCMD
681     with_tmpchdir do
682       write_file("test-script", "$0 = 'hello world'; /test-script/ =~ Process.argv0 or $0 = 'Process.argv0 changed!'; sleep 60")
684       pid = spawn(EnvUtil.rubybin, "test-script")
685       ps = nil
686       now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
687       stop = now + 30
688       begin
689         sleep 0.1
690         ps = `#{PSCMD.join(' ')} #{pid}`
691         break if /hello world/ =~ ps
692         now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
693       end until Process.wait(pid, Process::WNOHANG) || now > stop
694       assert_match(/hello world/, ps)
695       assert_operator now, :<, stop
696       Process.kill :KILL, pid
697       EnvUtil.timeout(5) { Process.wait(pid) }
698     end
699   end
701   def test_setproctitle
702     omit "platform dependent feature" unless defined?(PSCMD) and PSCMD
704     assert_separately([], "#{<<-"{#"}\n#{<<-'};'}")
705     {#
706       assert_raise(ArgumentError) do
707         Process.setproctitle("hello\0")
708       end
709     };
711     with_tmpchdir do
712       write_file("test-script", "$_0 = $0.dup; Process.setproctitle('hello world'); $0 == $_0 or Process.setproctitle('$0 changed!'); sleep 60")
714       pid = spawn(EnvUtil.rubybin, "test-script")
715       ps = nil
716       now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
717       stop = now + 30
718       begin
719         sleep 0.1
720         ps = `#{PSCMD.join(' ')} #{pid}`
721         break if /hello world/ =~ ps
722         now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
723       end until Process.wait(pid, Process::WNOHANG) || now > stop
724       assert_match(/hello world/, ps)
725       assert_operator now, :<, stop
726       Process.kill :KILL, pid
727       Timeout.timeout(5) { Process.wait(pid) }
728     end
729   end
731   module SEGVTest
732     opts = {}
733     unless /mswin|mingw/ =~ RUBY_PLATFORM
734       opts[:rlimit_core] = 0
735     end
736     ExecOptions = opts.freeze
738     ExpectedStderrList = [
739       %r(
740         -e:(?:1:)?\s\[BUG\]\sSegmentation\sfault.*\n
741       )x,
742       %r(
743         #{ Regexp.quote(NO_JIT_DESCRIPTION) }\n\n
744       )x,
745       %r(
746         (?:--\s(?:.+\n)*\n)?
747         --\sControl\sframe\sinformation\s-+\n
748         (?:(?:c:.*\n)|(?:^\s+.+\n))*
749         \n
750       )x,
751       %r(
752         (?:
753         --\sRuby\slevel\sbacktrace\sinformation\s----------------------------------------\n
754         (?:-e:1:in\s\`(?:block\sin\s)?<main>\'\n)*
755         -e:1:in\s\`kill\'\n
756         \n
757         )?
758       )x,
759       %r(
760         (?:--\sMachine(?:.+\n)*\n)?
761       )x,
762       %r(
763         (?:
764           --\sC\slevel\sbacktrace\sinformation\s-------------------------------------------\n
765           (?:(?:.*\s)?\[0x\h+\].*\n|.*:\d+\n)*\n
766         )?
767       )x,
768       %r(
769         (?:--\sOther\sruntime\sinformation\s-+\n
770           (?:.*\n)*
771         )?
772       )x,
773     ]
774   end
776   def assert_segv(args, message=nil)
777     omit if ENV['RUBY_ON_BUG']
779     test_stdin = ""
780     opt = SEGVTest::ExecOptions.dup
781     list = SEGVTest::ExpectedStderrList
783     assert_in_out_err(args, test_stdin, //, list, encoding: "ASCII-8BIT", **opt)
784   end
786   def test_segv_test
787     assert_segv(["--disable-gems", "-e", "Process.kill :SEGV, $$"])
788   end
790   def test_segv_loaded_features
791     bug7402 = '[ruby-core:49573]'
793     status = assert_segv(['-e', 'END {Process.kill :SEGV, $$}',
794                           '-e', 'class Bogus; def to_str; exit true; end; end',
795                           '-e', '$".clear',
796                           '-e', '$".unshift Bogus.new',
797                           '-e', '(p $"; abort) unless $".size == 1',
798                          ])
799     assert_not_predicate(status, :success?, "segv but success #{bug7402}")
800   end
802   def test_segv_setproctitle
803     bug7597 = '[ruby-dev:46786]'
804     Tempfile.create(["test_ruby_test_bug7597", ".rb"]) {|t|
805       t.write "f" * 100
806       t.flush
807       assert_segv(["--disable-gems", "-e", "$0=ARGV[0]; Process.kill :SEGV, $$", t.path], bug7597)
808     }
809   end
811   def test_DATA
812     Tempfile.create(["test_ruby_test_rubyoption", ".rb"]) {|t|
813       t.puts "puts DATA.read.inspect"
814       t.puts "__END__"
815       t.puts "foo"
816       t.puts "bar"
817       t.puts "baz"
818       t.flush
819       assert_in_out_err([t.path], "", %w("foo\\nbar\\nbaz\\n"), [])
820     }
821   end
823   def test_unused_variable
824     feature3446 = '[ruby-dev:41620]'
825     assert_in_out_err(["-we", "a=1"], "", [], [], feature3446)
826     assert_in_out_err(["-we", "def foo\n  a=1\nend"], "", [], ["-e:2: warning: assigned but unused variable - a"], feature3446)
827     assert_in_out_err(["-we", "def foo\n  eval('a=1')\nend"], "", [], [], feature3446)
828     assert_in_out_err(["-we", "1.times do\n  a=1\nend"], "", [], [], feature3446)
829     assert_in_out_err(["-we", "def foo\n  1.times do\n    a=1\n  end\nend"], "", [], ["-e:3: warning: assigned but unused variable - a"], feature3446)
830     assert_in_out_err(["-we", "def foo\n""  1.times do |a| end\n""end"], "", [], [])
831     feature6693 = '[ruby-core:46160]'
832     assert_in_out_err(["-we", "def foo\n  _a=1\nend"], "", [], [], feature6693)
833     bug7408 = '[ruby-core:49659]'
834     assert_in_out_err(["-we", "def foo\n  a=1\n :a\nend"], "", [], ["-e:2: warning: assigned but unused variable - a"], bug7408)
835     feature7730 = '[ruby-core:51580]'
836     assert_in_out_err(["-w", "-"], "a=1", [], ["-:1: warning: assigned but unused variable - a"], feature7730)
837     assert_in_out_err(["-w", "-"], "eval('a=1')", [], [], feature7730)
838   end
840   def test_script_from_stdin
841     begin
842       require 'pty'
843       require 'io/console'
844     rescue LoadError
845       return
846     end
847     require 'timeout'
848     result = nil
849     IO.pipe {|r, w|
850       begin
851         PTY.open {|m, s|
852           s.echo = false
853           m.print("\C-d")
854           pid = spawn(EnvUtil.rubybin, :in => s, :out => w)
855           w.close
856           assert_nothing_raised('[ruby-dev:37798]') do
857             result = EnvUtil.timeout(3) {r.read}
858           end
859           Process.wait pid
860         }
861       rescue RuntimeError
862         omit $!
863       end
864     }
865     assert_equal("", result, '[ruby-dev:37798]')
866     IO.pipe {|r, w|
867       PTY.open {|m, s|
868         s.echo = false
869         pid = spawn(EnvUtil.rubybin, :in => s, :out => w)
870         w.close
871         m.print("$stdin.read; p $stdin.gets\n\C-d")
872         m.print("abc\n\C-d")
873         m.print("zzz\n")
874         result = r.read
875         Process.wait pid
876       }
877     }
878     assert_equal("\"zzz\\n\"\n", result, '[ruby-core:30910]')
879   end
881   def test_unmatching_glob
882     bug3851 = '[ruby-core:32478]'
883     a = "a[foo"
884     Dir.mktmpdir do |dir|
885       open(File.join(dir, a), "w") {|f| f.puts("p 42")}
886       assert_in_out_err(["-C", dir, a], "", ["42"], [], bug3851)
887       File.unlink(File.join(dir, a))
888       assert_in_out_err(["-C", dir, a], "", [], /LoadError/, bug3851)
889     end
890   end
892   case RUBY_PLATFORM
893   when /mswin|mingw/
894     def test_command_line_glob_nonascii
895       bug10555 = '[ruby-dev:48752] [Bug #10555]'
896       name = "\u{3042}.txt"
897       expected = name.encode("external") rescue "?.txt"
898       with_tmpchdir do |dir|
899         open(name, "w") {}
900         assert_in_out_err(["-e", "puts ARGV", "?.txt"], "", [expected], [],
901                           bug10555, encoding: "external")
902       end
903     end
905     def test_command_line_progname_nonascii
906       bug10555 = '[ruby-dev:48752] [Bug #10555]'
907       name = expected = nil
908       unless (0x80..0x10000).any? {|c|
909                name = c.chr(Encoding::UTF_8)
910                expected = name.encode("locale") rescue nil
911              }
912         omit "can't make locale name"
913       end
914       name << ".rb"
915       expected << ".rb"
916       with_tmpchdir do |dir|
917         open(name, "w") {|f| f.puts "puts File.basename($0)"}
918         assert_in_out_err([name], "", [expected], [],
919                           bug10555, encoding: "locale")
920       end
921     end
923     def test_command_line_glob_with_dir
924       bug10941 = '[ruby-core:68430] [Bug #10941]'
925       with_tmpchdir do |dir|
926         Dir.mkdir('test')
927         assert_in_out_err(["-e", "", "test/*"], "", [], [], bug10941)
928       end
929     end
931     Ougai = %W[\u{68ee}O\u{5916}.txt \u{68ee 9d0e 5916}.txt \u{68ee 9dd7 5916}.txt]
932     def test_command_line_glob_noncodepage
933       with_tmpchdir do |dir|
934         Ougai.each {|f| open(f, "w") {}}
935         assert_in_out_err(["-Eutf-8", "-e", "puts ARGV", "*"], "", Ougai, encoding: "utf-8")
936         ougai = Ougai.map {|f| f.encode("external", replace: "?")}
937         assert_in_out_err(["-e", "puts ARGV", "*.txt"], "", ougai)
938       end
939     end
941     def assert_e_script_encoding(str, args = [])
942       cmds = [
943         EnvUtil::LANG_ENVS.inject({}) {|h, k| h[k] = ENV[k]; h},
944         *args,
945         '-e', "s = '#{str}'",
946         '-e', 'puts s.encoding.name',
947         '-e', 'puts s.dump',
948       ]
949       assert_in_out_err(cmds, "", [str.encoding.name, str.dump], [],
950                         "#{str.encoding}:#{str.dump} #{args.inspect}")
951     end
953     # tested codepages: 437 850 852 855 932 65001
954     # Since the codepage is shared all processes per conhost.exe, do
955     # not chcp, or parallel test may break.
956     def test_locale_codepage
957       locale = Encoding.find("locale")
958       list = %W"\u{c7} \u{452} \u{3066 3059 3068}"
959       list.each do |s|
960         assert_e_script_encoding(s, %w[-U])
961       end
962       list.each do |s|
963         s = s.encode(locale) rescue next
964         assert_e_script_encoding(s)
965         assert_e_script_encoding(s, %W[-E#{locale.name}])
966       end
967     end
968   when /cygwin/
969     def test_command_line_non_ascii
970       assert_separately([{"LC_ALL"=>"ja_JP.SJIS"}, "-", "\u{3042}".encode("SJIS")], <<-"end;")
971         bug12184 = '[ruby-dev:49519] [Bug #12184]'
972         a = ARGV[0]
973         assert_equal([Encoding::SJIS, 130, 160], [a.encoding, *a.bytes], bug12184)
974       end;
975     end
976   end
978   def test_script_is_directory
979     feature2408 = '[ruby-core:26925]'
980     assert_in_out_err(%w[.], "", [], /Is a directory -- \./, feature2408)
981   end
983   def test_pflag_gsub
984     bug7157 = '[ruby-core:47967]'
985     assert_in_out_err(['-p', '-e', 'gsub(/t.*/){"TEST"}'], %[test], %w[TEST], [], bug7157)
986   end
988   def test_pflag_sub
989     bug7157 = '[ruby-core:47967]'
990     assert_in_out_err(['-p', '-e', 'sub(/t.*/){"TEST"}'], %[test], %w[TEST], [], bug7157)
991   end
993   def assert_norun_with_rflag(*opt)
994     bug10435 = "[ruby-dev:48712] [Bug #10435]: should not run with #{opt} option"
995     stderr = []
996     Tempfile.create(%w"bug10435- .rb") do |script|
997       dir, base = File.split(script.path)
998       script.puts "abort ':run'"
999       script.close
1000       opts = ['-C', dir, '-r', "./#{base}", *opt]
1001       _, e = assert_in_out_err([*opts, '-ep'], "", //)
1002       stderr.concat(e) if e
1003       stderr << "---"
1004       _, e = assert_in_out_err([*opts, base], "", //)
1005       stderr.concat(e) if e
1006     end
1007     assert_not_include(stderr, ":run", bug10435)
1008   end
1010   def test_dump_syntax_with_rflag
1011     assert_norun_with_rflag('-c')
1012     assert_norun_with_rflag('--dump=syntax')
1013   end
1015   def test_dump_yydebug_with_rflag
1016     assert_norun_with_rflag('-y')
1017     assert_norun_with_rflag('--dump=yydebug')
1018   end
1020   def test_dump_parsetree_with_rflag
1021     assert_norun_with_rflag('--dump=parsetree')
1022     assert_norun_with_rflag('--dump=parsetree', '-e', '#frozen-string-literal: true')
1023   end
1025   def test_dump_insns_with_rflag
1026     assert_norun_with_rflag('--dump=insns')
1027   end
1029   def test_frozen_string_literal
1030     all_assertions do |a|
1031       [["disable", "false"], ["enable", "true"]].each do |opt, exp|
1032         %W[frozen_string_literal frozen-string-literal].each do |arg|
1033           key = "#{opt}=#{arg}"
1034           negopt = exp == "true" ? "disable" : "enable"
1035           env = {"RUBYOPT"=>"--#{negopt}=#{arg}"}
1036           a.for(key) do
1037             assert_in_out_err([env, "--disable=gems", "--#{key}"], 'p("foo".frozen?)', [exp])
1038           end
1039         end
1040       end
1041       %W"disable enable".product(%W[false true]) do |opt, exp|
1042         a.for("#{opt}=>#{exp}") do
1043           assert_in_out_err(["-w", "--disable=gems", "--#{opt}=frozen-string-literal"], <<-"end;", [exp])
1044             #-*- frozen-string-literal: #{exp} -*-
1045             p("foo".frozen?)
1046           end;
1047         end
1048       end
1049     end
1050   end
1052   def test_frozen_string_literal_debug
1053     with_debug_pat = /created at/
1054     wo_debug_pat = /can\'t modify frozen String: "\w+" \(FrozenError\)\n\z/
1055     frozen = [
1056       ["--enable-frozen-string-literal", true],
1057       ["--disable-frozen-string-literal", false],
1058       [nil, false],
1059     ]
1060     debugs = [
1061       ["--debug-frozen-string-literal", true],
1062       ["--debug=frozen-string-literal", true],
1063       ["--debug", true],
1064       [nil, false],
1065     ]
1066     opts = ["--disable=gems"]
1067     frozen.product(debugs) do |(opt1, freeze), (opt2, debug)|
1068       opt = opts + [opt1, opt2].compact
1069       err = !freeze ? [] : debug ? with_debug_pat : wo_debug_pat
1070       [
1071         ['"foo" << "bar"', err],
1072         ['"foo#{123}bar" << "bar"', []],
1073         ['+"foo#{123}bar" << "bar"', []],
1074         ['-"foo#{123}bar" << "bar"', wo_debug_pat],
1075       ].each do |code, expected|
1076         assert_in_out_err(opt, code, [], expected, "#{opt} #{code}")
1077       end
1078     end
1079   end
1081   def test___dir__encoding
1082     lang = {"LC_ALL"=>ENV["LC_ALL"]||ENV["LANG"]}
1083     with_tmpchdir do
1084       testdir = "\u30c6\u30b9\u30c8"
1085       Dir.mkdir(testdir)
1086       Dir.chdir(testdir) do
1087         open("test.rb", "w") do |f|
1088           f.puts <<-END
1089             if __FILE__.encoding == __dir__.encoding
1090               p true
1091             else
1092               puts "__FILE__: \#{__FILE__.encoding}, __dir__: \#{__dir__.encoding}"
1093             end
1094           END
1095         end
1096         r, = EnvUtil.invoke_ruby([lang, "test.rb"], "", true)
1097         assert_equal "true", r.chomp, "the encoding of __FILE__ and __dir__ should be same"
1098       end
1099     end
1100   end
1102   def test_cwd_encoding
1103     with_tmpchdir do
1104       testdir = "\u30c6\u30b9\u30c8"
1105       Dir.mkdir(testdir)
1106       Dir.chdir(testdir) do
1107         File.write("a.rb", "require './b'")
1108         File.write("b.rb", "puts 'ok'")
1109         assert_ruby_status([{"RUBYLIB"=>"."}, *%w[-E cp932:utf-8 a.rb]])
1110       end
1111     end
1112   end
1114   def test_rubylib_invalid_encoding
1115     env = {"RUBYLIB"=>"\xFF", "LOCALE"=>"en_US.UTF-8", "LC_ALL"=>"en_US.UTF-8"}
1116     assert_ruby_status([env, "-e;"])
1117   end
1119   def test_null_script
1120     omit "#{IO::NULL} is not a character device" unless File.chardev?(IO::NULL)
1121     assert_in_out_err([IO::NULL], success: true)
1122   end
1124   def test_jit_debug
1125     # mswin uses prebuilt precompiled header. Thus it does not show a pch compilation log to check "-O0 -O1".
1126     if JITSupport.supported? && !RUBY_PLATFORM.match?(/mswin/)
1127       env = { 'MJIT_SEARCH_BUILD_DIR' => 'true' }
1128       assert_in_out_err([env, "--disable-yjit", "--mjit-debug=-O0 -O1", "--mjit-verbose=2", "" ], "", [], /-O0 -O1/)
1129     end
1130   end
1132   private
1134   def mjit_force_enabled?
1135     "#{RbConfig::CONFIG['CFLAGS']} #{RbConfig::CONFIG['CPPFLAGS']}".match?(/(\A|\s)-D ?MJIT_FORCE_ENABLE\b/)
1136   end
1138   def yjit_force_enabled?
1139     "#{RbConfig::CONFIG['CFLAGS']} #{RbConfig::CONFIG['CPPFLAGS']}".match?(/(\A|\s)-D ?YJIT_FORCE_ENABLE\b/)
1140   end