PageRenderTime 59ms CodeModel.GetById 1ms RepoModel.GetById 0ms app.codeStats 0ms

/test/ruby/test_rubyoptions.rb

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