diff options
Diffstat (limited to 'test/ruby')
117 files changed, 2909 insertions, 20167 deletions
diff --git a/test/ruby/enc/test_case_comprehensive.rb b/test/ruby/enc/test_case_comprehensive.rb index bde47017a2..cd6447e928 100644 --- a/test/ruby/enc/test_case_comprehensive.rb +++ b/test/ruby/enc/test_case_comprehensive.rb @@ -73,11 +73,7 @@ TestComprehensiveCaseMapping.data_files_available? and class TestComprehensiveC @@codepoints << code upcase[code] = hex2utf8 data[12] unless data[12].empty? downcase[code] = hex2utf8 data[13] unless data[13].empty? - if code>="\u1C90" and code<="\u1CBF" # exception for Georgian: use lowercase for titlecase - titlecase[code] = hex2utf8(data[13]) unless data[13].empty? - else - titlecase[code] = hex2utf8 data[14] unless data[14].empty? - end + titlecase[code] = hex2utf8 data[14] unless data[14].empty? end read_data_file('CaseFolding') do |code, data| casefold[code] = hex2utf8(data[2]) if data[1] =~ /^[CF]$/ diff --git a/test/ruby/enc/test_case_mapping.rb b/test/ruby/enc/test_case_mapping.rb index 31acdc4331..d095cd569c 100644 --- a/test/ruby/enc/test_case_mapping.rb +++ b/test/ruby/enc/test_case_mapping.rb @@ -187,39 +187,6 @@ class TestCaseMappingPreliminary < Test::Unit::TestCase assert_equal 0, "\ua64A" =~ /\uA64B/i end - def test_georgian_canary - message = "Reexamine implementation of Georgian in String#capitalize" - assert_equal false, "\u1CBB".match?(/\p{assigned}/), message - assert_equal false, "\u1CBC".match?(/\p{assigned}/), message - end - - def test_georgian_unassigned - message = "Unassigned codepoints should not be converted" - assert_equal "\u1CBB", "\u1CBB".capitalize, message - assert_equal "\u1CBC", "\u1CBC".capitalize, message - end - - def test_georgian_capitalize - assert_equal "\u10D0\u10D1\u10D2", "\u1C90\u1C91\u1C92".capitalize - assert_equal "\u10D0\u10D1\u10D2", "\u1C90\u1C91\u10D2".capitalize - assert_equal "\u10D0\u10D1\u10D2", "\u1C90\u10D1\u1C92".capitalize - assert_equal "\u10D0\u10D1\u10D2", "\u1C90\u10D1\u10D2".capitalize - assert_equal "\u10D0\u10D1\u10D2", "\u10D0\u1C91\u1C92".capitalize - assert_equal "\u10D0\u10D1\u10D2", "\u10D0\u1C91\u10D2".capitalize - assert_equal "\u10D0\u10D1\u10D2", "\u10D0\u10D1\u1C92".capitalize - assert_equal "\u10D0\u10D1\u10D2", "\u10D0\u10D1\u10D2".capitalize - end - - def test_shift_jis_downcase_ascii - s = ("A".."Z").map {|c| "\x89#{c}"}.join("").force_encoding("Shift_JIS") - assert_equal s, s.downcase(:ascii) - end - - def test_shift_jis_upcase_ascii - s = ("a".."z").map {|c| "\x89#{c}"}.join("").force_encoding("Shift_JIS") - assert_equal s, s.upcase(:ascii) - end - def no_longer_a_test_buffer_allocations assert_equal 'TURKISH*ı'*10, ('I'*10).downcase(:turkic) assert_equal 'TURKISH*ı'*100, ('I'*100).downcase(:turkic) diff --git a/test/ruby/enc/test_cesu8.rb b/test/ruby/enc/test_cesu8.rb deleted file mode 100644 index d9debe76cd..0000000000 --- a/test/ruby/enc/test_cesu8.rb +++ /dev/null @@ -1,109 +0,0 @@ -# frozen_string_literal: false -require 'test/unit' - -class TestCESU8 < Test::Unit::TestCase - - def encdump(obj) - case obj - when String - obj.dump - when Regexp - "Regexp.new(#{encdump(obj.source)}, #{obj.options})" - else - raise Argument, "unexpected: #{obj.inspect}" - end - end - - def enccall(recv, meth, *args) - desc = '' - if String === recv - desc << encdump(recv) - else - desc << recv.inspect - end - desc << '.' << meth.to_s - if !args.empty? - desc << '(' - args.each_with_index {|a, i| - desc << ',' if 0 < i - if String === a - desc << encdump(a) - else - desc << a.inspect - end - } - desc << ')' - end - result = nil - assert_nothing_raised(desc) { - result = recv.send(meth, *args) - } - result - end - - def assert_str_equal(expected, actual, message=nil) - full_message = build_message(message, <<EOT) -#{encdump expected} expected but not equal to -#{encdump actual}. -EOT - assert_equal(expected, actual, full_message) - end - - # tests start - - def test_cesu8_valid_encoding - all_assertions do |a| - [ - "\x00", - "\x7f", - "\u0080", - "\u07ff", - "\u0800", - "\ud7ff", - "\xed\xa0\x80\xed\xb0\x80", - "\xed\xaf\xbf\xed\xbf\xbf", - "\ue000", - "\uffff", - ].each {|s| - s.force_encoding("cesu-8") - a.for(s) { - assert_predicate(s, :valid_encoding?, "#{encdump s}.valid_encoding?") - } - } - [ - "\x80", - "\xc0\x80", - "\xc0", - "\xe0\x80\x80", - "\xed\xa0\x80", - "\xed\xb0\x80\xed\xb0\x80", - "\xe0", - "\xff", - ].each {|s| - s.force_encoding("cesu-8") - a.for(s) { - assert_not_predicate(s, :valid_encoding?, "#{encdump s}.valid_encoding?") - } - } - end - end - - def test_cesu8_ord - [ - ["\x00", 0], - ["\x7f", 0x7f], - ["\u0080", 0x80], - ["\u07ff", 0x7ff], - ["\u0800", 0x800], - ["\ud7ff", 0xd7ff], - ["\xed\xa0\x80\xed\xb0\x80", 0x10000], - ["\xed\xaf\xbf\xed\xbf\xbf", 0x10ffff], - ["\xee\x80\x80", 0xe000], - ["\xef\xbf\xbf", 0xffff], - ].each do |chr, ord| - chr.force_encoding("cesu-8") - assert_equal ord, chr.ord - assert_equal chr, ord.chr("cesu-8") - end - end -end diff --git a/test/ruby/enc/test_emoji_breaks.rb b/test/ruby/enc/test_emoji_breaks.rb deleted file mode 100644 index 7048d8d59f..0000000000 --- a/test/ruby/enc/test_emoji_breaks.rb +++ /dev/null @@ -1,122 +0,0 @@ -# frozen_string_literal: true -# Copyright © 2018 Martin J. Dürst (duerst@it.aoyama.ac.jp) - -require "test/unit" - -class TestEmojiBreaks < Test::Unit::TestCase -end - -class TestEmojiBreaks::BreakTest - attr_reader :string, :comment, :filename, :line_number, :type, :shortname - - def initialize(filename, line_number, data, comment='') - @filename = filename - @line_number = line_number - @comment = comment.gsub(/\s+/, ' ').strip - if filename=='emoji-test' - codes, @type = data.split(/\s*;\s*/) - @shortname = '' - else - codes, @type, @shortname = data.split(/\s*;\s*/) - end - @type = @type.gsub(/\s+/, ' ').strip - @shortname = @shortname.gsub(/\s+/, ' ').strip - @string = codes.split(/\s+/) - .map do |ch| - c = ch.to_i(16) - # eliminate cases with surrogates - # raise ArgumentError if 0xD800 <= c and c <= 0xDFFF - c.chr('UTF-8') - end.join - end -end - -class TestEmojiBreaks < Test::Unit::TestCase - EMOJI_DATA_FILES = %w[emoji-sequences emoji-test emoji-variation-sequences emoji-zwj-sequences] - EMOJI_VERSION = RbConfig::CONFIG['UNICODE_EMOJI_VERSION'] - EMOJI_DATA_PATH = File.expand_path("../../../enc/unicode/data/emoji/#{EMOJI_VERSION}", __dir__) - - def self.expand_filename(basename) - File.expand_path("#{EMOJI_DATA_PATH}/#{basename}.txt", __dir__) - end - - def self.data_files_available? - EMOJI_DATA_FILES.all? do |f| - File.exist?(expand_filename(f)) - end - end - - def test_data_files_available - unless TestEmojiBreaks.data_files_available? - skip "Emoji data files not available in #{EMOJI_DATA_PATH}." - end - end -end - -TestEmojiBreaks.data_files_available? and class TestEmojiBreaks - def read_data - tests = [] - EMOJI_DATA_FILES.each do |filename| - version_mismatch = true - file_tests = [] - IO.foreach(TestEmojiBreaks.expand_filename(filename), encoding: Encoding::UTF_8) do |line| - line.chomp! - raise "File Name Mismatch" if $.==1 and not line=="# #{filename}.txt" - version_mismatch = false if line=="# Version: #{EMOJI_VERSION}" - next if /\A(#|\z)/.match? line - file_tests << BreakTest.new(filename, $., *line.split('#')) rescue 'whatever' - end - raise "File Version Mismatch" if version_mismatch - tests += file_tests - end - tests - end - - def all_tests - @@tests ||= read_data - rescue Errno::ENOENT - @@tests ||= [] - end - - def test_single_emoji - all_tests.each do |test| - expected = [test.string] - actual = test.string.each_grapheme_cluster.to_a - assert_equal expected, actual, - "file: #{test.filename}, line #{test.line_number}, " + - "type: #{test.type}, shortname: #{test.shortname}, comment: #{test.comment}" - end - end - - def test_embedded_emoji - all_tests.each do |test| - expected = ["\t", test.string, "\t"] - actual = "\t#{test.string}\t".each_grapheme_cluster.to_a - assert_equal expected, actual, - "file: #{test.filename}, line #{test.line_number}, " + - "type: #{test.type}, shortname: #{test.shortname}, comment: #{test.comment}" - end - end - - # test some pseodorandom combinations of emoji - def test_mixed_emoji - srand 0 - length = all_tests.length - step = 503 # use a prime number - all_tests.each do |test1| - start = rand step - start.step(by: step, to: length-1) do |t2| - test2 = all_tests[t2] - # exclude skin tones, because they glue to previous grapheme clusters - next if (0x1F3FB..0x1F3FF).include? test2.string.ord - expected = [test1.string, test2.string] - actual = (test1.string+test2.string).each_grapheme_cluster.to_a - assert_equal expected, actual, - "file1: #{test1.filename}, line1 #{test1.line_number}, " + - "file2: #{test2.filename}, line2 #{test2.line_number},\n" + - "type1: #{test1.type}, shortname1: #{test1.shortname}, comment1: #{test1.comment},\n" + - "type2: #{test2.type}, shortname2: #{test2.shortname}, comment2: #{test2.comment}" - end - end - end -end diff --git a/test/ruby/enc/test_grapheme_breaks.rb b/test/ruby/enc/test_grapheme_breaks.rb index 2d210946a9..7f6c776113 100644 --- a/test/ruby/enc/test_grapheme_breaks.rb +++ b/test/ruby/enc/test_grapheme_breaks.rb @@ -3,13 +3,10 @@ require "test/unit" -class TestGraphemeBreaksFromFile < Test::Unit::TestCase -end - -class TestGraphemeBreaksFromFile::BreakTest +class BreakTest attr_reader :clusters, :string, :comment, :line_number - def initialize(line_number, data, comment) + def initialize (line_number, data, comment) @line_number = line_number @comment = comment @clusters = data.sub(/\A\s*÷\s*/, '') diff --git a/test/ruby/enc/test_regex_casefold.rb b/test/ruby/enc/test_regex_casefold.rb index ec5dc7f220..2b252bd441 100644 --- a/test/ruby/enc/test_regex_casefold.rb +++ b/test/ruby/enc/test_regex_casefold.rb @@ -11,7 +11,7 @@ class TestCaseFold < Test::Unit::TestCase def check_downcase_properties(expected, start, *flags) assert_equal expected, start.downcase(*flags) - temp = start.dup + temp = start assert_equal expected, temp.downcase!(*flags) assert_equal expected, expected.downcase(*flags) temp = expected diff --git a/test/ruby/marshaltestlib.rb b/test/ruby/marshaltestlib.rb index 5c48a8d853..358d3c5133 100644 --- a/test/ruby/marshaltestlib.rb +++ b/test/ruby/marshaltestlib.rb @@ -110,9 +110,7 @@ module MarshalTestLib class MyException < Exception; def initialize(v, *args) super(*args); @v = v; end; attr_reader :v; end def test_exception marshal_equal(Exception.new('foo')) {|o| o.message} - obj = Object.new - e = assert_raise(NoMethodError) {obj.no_such_method()} - marshal_equal(e) {|o| o.message} + marshal_equal(assert_raise(NoMethodError) {no_such_method()}) {|o| o.message} end def test_exception_subclass diff --git a/test/ruby/sentence.rb b/test/ruby/sentence.rb index 9bfd7c7599..28fb5d1cf8 100644 --- a/test/ruby/sentence.rb +++ b/test/ruby/sentence.rb @@ -353,7 +353,7 @@ class Sentence # * No rule derives to empty sequence # * Underivable rule simplified # * No channel rule - # * Symbols which has zero or one choices are not appeared in rhs. + # * Symbols which has zero or one choices are not appered in rhs. # # Note that the rules which can derive empty and non-empty # sequences are modified to derive only non-empty sequences. diff --git a/test/ruby/test_alias.rb b/test/ruby/test_alias.rb index 271d552bf5..e81636fa43 100644 --- a/test/ruby/test_alias.rb +++ b/test/ruby/test_alias.rb @@ -35,18 +35,6 @@ class TestAlias < Test::Unit::TestCase end end - class Alias4 < Alias0 - alias foo1 foo - alias foo2 foo1 - alias foo3 foo2 - end - - class Alias5 < Alias4 - alias foo1 foo - alias foo3 foo2 - alias foo2 foo1 - end - def test_alias x = Alias2.new assert_equal "foo", x.bar @@ -59,18 +47,10 @@ class TestAlias < Test::Unit::TestCase assert_raise(NoMethodError) { x.quux } end - def test_alias_inspect - o = Alias4.new - assert_equal("TestAlias::Alias4(TestAlias::Alias0)#foo()", o.method(:foo).inspect.split[1]) - assert_equal("TestAlias::Alias4(TestAlias::Alias0)#foo1(foo)()", o.method(:foo1).inspect.split[1]) - assert_equal("TestAlias::Alias4(TestAlias::Alias0)#foo2(foo)()", o.method(:foo2).inspect.split[1]) - assert_equal("TestAlias::Alias4(TestAlias::Alias0)#foo3(foo)()", o.method(:foo3).inspect.split[1]) - - o = Alias5.new - assert_equal("TestAlias::Alias5(TestAlias::Alias0)#foo()", o.method(:foo).inspect.split[1]) - assert_equal("TestAlias::Alias5(TestAlias::Alias0)#foo1(foo)()", o.method(:foo1).inspect.split[1]) - assert_equal("TestAlias::Alias5(TestAlias::Alias0)#foo2(foo)()", o.method(:foo2).inspect.split[1]) - assert_equal("TestAlias::Alias5(TestAlias::Alias0)#foo3(foo)()", o.method(:foo3).inspect.split[1]) + class C + def m + $SAFE + end end def test_nonexistmethod diff --git a/test/ruby/test_argf.rb b/test/ruby/test_argf.rb index 6262514241..311469aad9 100644 --- a/test/ruby/test_argf.rb +++ b/test/ruby/test_argf.rb @@ -35,8 +35,8 @@ class TestArgf < Test::Unit::TestCase open("#{@tmpdir}/#{basename}-#{@tmp_count}", "w") end - def make_tempfile(basename = "argf-qux") - t = make_tempfile0(basename) + def make_tempfile + t = make_tempfile0("argf-qux") t.puts "foo" t.puts "bar" t.puts "baz" @@ -255,26 +255,6 @@ class TestArgf < Test::Unit::TestCase assert_warning(/#{base}/) {argf.gets} end - def test_inplace_nonascii - ext = Encoding.default_external or - skip "no default external encoding" - t = nil - ["\u{3042}", "\u{e9}"].any? do |n| - t = make_tempfile(n.encode(ext)) - rescue Encoding::UndefinedConversionError - end - t or skip "no name to test" - assert_in_out_err(["-i.bak", "-", t.path], - "#{<<~"{#"}\n#{<<~'};'}") - {# - puts ARGF.gets.chomp + '.new' - puts ARGF.gets.chomp + '.new' - puts ARGF.gets.chomp + '.new' - }; - assert_equal("foo.new\n""bar.new\n""baz.new\n", File.read(t.path)) - assert_equal("foo\n""bar\n""baz\n", File.read(t.path + ".bak")) - end - def test_inplace_no_backup t = make_tempfile @@ -387,21 +367,6 @@ class TestArgf < Test::Unit::TestCase assert_equal("foo", File.read(name+suffix)) end - def test_inplace_bug_17117 - assert_in_out_err(["-", @t1.path], "#{<<~"{#"}#{<<~'};'}") - {# - #!/usr/bin/ruby -pi.bak - BEGIN { - GC.start - arr = [] - 1000000.times { |x| arr << "fooo#{x}" } - } - puts "hello" - }; - assert_equal("hello\n1\nhello\n2\n", File.read(@t1.path)) - assert_equal("1\n2\n", File.read("#{@t1.path}.bak")) - end - def test_encoding ruby('-e', "#{<<~"{#"}\n#{<<~'};'}", @t1.path, @t2.path, @t3.path) do |f| {# @@ -740,13 +705,6 @@ class TestArgf < Test::Unit::TestCase ["\"a\\n\\n\"", "\"b\\n\""], []) end - def test_each_line_chomp - assert_in_out_err(['-e', 'ARGF.each_line(chomp: false) {|para| p para}'], "a\nb\n", - ["\"a\\n\"", "\"b\\n\""], []) - assert_in_out_err(['-e', 'ARGF.each_line(chomp: true) {|para| p para}'], "a\nb\n", - ["\"a\"", "\"b\""], []) - end - def test_each_byte ruby('-e', "#{<<~"{#"}\n#{<<~'};'}", @t1.path, @t2.path, @t3.path) do |f| {# @@ -998,11 +956,48 @@ class TestArgf < Test::Unit::TestCase assert_ruby_status(["-e", "2.times {STDIN.tty?; readlines}"], "", bug5952) end - def test_each_codepoint + def test_lines ruby('-W1', '-e', "#{<<~"{#"}\n#{<<~'};'}", @t1.path, @t2.path, @t3.path) do |f| {# - print Marshal.dump(ARGF.each_codepoint.to_a) + $stderr = $stdout + s = [] + ARGF.lines {|l| s << l } + p s + }; + assert_match(/deprecated/, f.gets) + assert_equal("[\"1\\n\", \"2\\n\", \"3\\n\", \"4\\n\", \"5\\n\", \"6\\n\"]\n", f.read) + end + end + + def test_bytes + ruby('-W1', '-e', "#{<<~"{#"}\n#{<<~'};'}", @t1.path, @t2.path, @t3.path) do |f| + {# + $stderr = $stdout + print Marshal.dump(ARGF.bytes.to_a) + }; + assert_match(/deprecated/, f.gets) + assert_equal([49, 10, 50, 10, 51, 10, 52, 10, 53, 10, 54, 10], Marshal.load(f.read)) + end + end + + def test_chars + ruby('-W1', '-e', "#{<<~"{#"}\n#{<<~'};'}", @t1.path, @t2.path, @t3.path) do |f| + {# + $stderr = $stdout + print [Marshal.dump(ARGF.chars.to_a)].pack('m') + }; + assert_match(/deprecated/, f.gets) + assert_equal(["1", "\n", "2", "\n", "3", "\n", "4", "\n", "5", "\n", "6", "\n"], Marshal.load(f.read.unpack('m').first)) + end + end + + def test_codepoints + ruby('-W1', '-e', "#{<<~"{#"}\n#{<<~'};'}", @t1.path, @t2.path, @t3.path) do |f| + {# + $stderr = $stdout + print Marshal.dump(ARGF.codepoints.to_a) }; + assert_match(/deprecated/, f.gets) assert_equal([49, 10, 50, 10, 51, 10, 52, 10, 53, 10, 54, 10], Marshal.load(f.read)) end end diff --git a/test/ruby/test_arithmetic_sequence.rb b/test/ruby/test_arithmetic_sequence.rb deleted file mode 100644 index 5e2a825265..0000000000 --- a/test/ruby/test_arithmetic_sequence.rb +++ /dev/null @@ -1,491 +0,0 @@ -# frozen_string_literal: false -require 'test/unit' - -class TestArithmeticSequence < Test::Unit::TestCase - def test_new - assert_raise(NoMethodError) { Enumerator::ArithmeticSequence.new } - end - - def test_allocate - assert_raise(TypeError) { Enumerator::ArithmeticSequence.allocate } - end - - def test_begin - assert_equal(1, 1.step.begin) - assert_equal(1, 1.step(10).begin) - assert_equal(1, 1.step(to: 10).begin) - assert_equal(1, 1.step(nil).begin) - assert_equal(1, 1.step(to: nil).begin) - assert_equal(1, 1.step(by: 2).begin) - assert_equal(1, 1.step(by: -1).begin) - assert_equal(1, 1.step(by: nil).begin) - assert_equal(1, 1.step(10, 2).begin) - assert_equal(1, 1.step(10, by: 2).begin) - assert_equal(1, 1.step(to: 10, by: 2).begin) - assert_equal(10, 10.step(to: 1, by: -1).begin) - assert_equal(10, 10.step(to: 1, by: -2).begin) - assert_equal(10, 10.step(to: -1, by: -2).begin) - assert_equal(10.0, 10.0.step(to: -1.0, by: -2.0).begin) - - assert_equal(3, (3..).step(2).begin) - assert_equal(4, (4...).step(7).begin) - assert_equal(nil, (..10).step(9).begin) - assert_equal(nil, (...11).step(5).begin) - end - - def test_end - assert_equal(nil, 1.step.end) - assert_equal(10, 1.step(10).end) - assert_equal(10, 1.step(to: 10).end) - assert_equal(nil, 1.step(nil).end) - assert_equal(nil, 1.step(to: nil).end) - assert_equal(nil, 1.step(by: 2).end) - assert_equal(nil, 1.step(by: -1).end) - assert_equal(nil, 1.step(by: nil).end) - assert_equal(10, 1.step(10, 2).end) - assert_equal(10, 1.step(10, by: 2).end) - assert_equal(10, 1.step(to: 10, by: 2).end) - assert_equal(1, 10.step(to: 1, by: -1).end) - assert_equal(1, 10.step(to: 1, by: -2).end) - assert_equal(-1, 10.step(to: -1, by: -2).end) - assert_equal(-1.0, 10.0.step(to: -1.0, by: -2.0).end) - - assert_equal(nil, (3..).step(2).end) - assert_equal(nil, (4...).step(7).end) - assert_equal(10, (..10).step(9).end) - assert_equal(11, (...11).step(5).end) - end - - def test_exclude_end_p - assert_equal(false, 1.step.exclude_end?) - assert_equal(false, 1.step(10).exclude_end?) - assert_equal(false, 1.step(to: 10).exclude_end?) - assert_equal(false, 1.step(nil).exclude_end?) - assert_equal(false, 1.step(to: nil).exclude_end?) - assert_equal(false, 1.step(by: 2).exclude_end?) - assert_equal(false, 1.step(by: -1).exclude_end?) - assert_equal(false, 1.step(by: nil).exclude_end?) - assert_equal(false, 1.step(10, 2).exclude_end?) - assert_equal(false, 1.step(10, by: 2).exclude_end?) - assert_equal(false, 1.step(to: 10, by: 2).exclude_end?) - assert_equal(false, 10.step(to: 1, by: -1).exclude_end?) - assert_equal(false, 10.step(to: 1, by: -2).exclude_end?) - assert_equal(false, 10.step(to: -1, by: -2).exclude_end?) - - assert_equal(false, (3..).step(2).exclude_end?) - assert_equal(true, (4...).step(7).exclude_end?) - assert_equal(false, (..10).step(9).exclude_end?) - assert_equal(true, (...11).step(5).exclude_end?) - end - - def test_step - assert_equal(1, 1.step.step) - assert_equal(1, 1.step(10).step) - assert_equal(1, 1.step(to: 10).step) - assert_equal(1, 1.step(nil).step) - assert_equal(1, 1.step(to: nil).step) - assert_equal(2, 1.step(by: 2).step) - assert_equal(-1, 1.step(by: -1).step) - assert_equal(1, 1.step(by: nil).step) - assert_equal(2, 1.step(10, 2).step) - assert_equal(2, 1.step(10, by: 2).step) - assert_equal(2, 1.step(to: 10, by: 2).step) - assert_equal(-1, 10.step(to: 1, by: -1).step) - assert_equal(-2, 10.step(to: 1, by: -2).step) - assert_equal(-2, 10.step(to: -1, by: -2).step) - assert_equal(-2.0, 10.0.step(to: -1.0, by: -2.0).step) - - assert_equal(2, (3..).step(2).step) - assert_equal(7, (4...).step(7).step) - assert_equal(9, (..10).step(9).step) - assert_equal(5, (...11).step(5).step) - end - - def test_eq - seq = 1.step - assert_equal(seq, seq) - assert_equal(seq, 1.step) - assert_equal(seq, 1.step(nil)) - end - - def test_eqq - seq = 1.step - assert_operator(seq, :===, seq) - assert_operator(seq, :===, 1.step) - assert_operator(seq, :===, 1.step(nil)) - end - - def test_eql_p - seq = 1.step - assert_operator(seq, :eql?, seq) - assert_operator(seq, :eql?, 1.step) - assert_operator(seq, :eql?, 1.step(nil)) - end - - def test_hash - seq = 1.step - assert_equal(seq.hash, seq.hash) - assert_equal(seq.hash, 1.step.hash) - assert_equal(seq.hash, 1.step(nil).hash) - assert_kind_of(String, seq.hash.to_s) - end - - def test_first - seq = 1.step - assert_equal(1, seq.first) - assert_equal([1], seq.first(1)) - assert_equal([1, 2, 3], seq.first(3)) - - seq = 1.step(by: 2) - assert_equal(1, seq.first) - assert_equal([1], seq.first(1)) - assert_equal([1, 3, 5], seq.first(3)) - - seq = 10.step(by: -2) - assert_equal(10, seq.first) - assert_equal([10], seq.first(1)) - assert_equal([10, 8, 6], seq.first(3)) - - seq = 1.step(by: 4) - assert_equal([1, 5, 9], seq.first(3)) - - seq = 1.step(10, by: 4) - assert_equal([1, 5, 9], seq.first(5)) - - seq = 1.step(0) - assert_equal(nil, seq.first) - assert_equal([], seq.first(1)) - assert_equal([], seq.first(3)) - - seq = 1.step(10, by: -1) - assert_equal(nil, seq.first) - assert_equal([], seq.first(1)) - assert_equal([], seq.first(3)) - - seq = 10.0.step(-1.0, by: -2.0) - assert_equal(10.0, seq.first) - assert_equal([10.0], seq.first(1)) - assert_equal([10.0, 8.0, 6.0], seq.first(3)) - - seq = (1..).step(2) - assert_equal(1, seq.first) - assert_equal([1], seq.first(1)) - assert_equal([1, 3, 5], seq.first(3)) - - seq = (..10).step(2) - assert_equal(nil, seq.first) - assert_raise(TypeError) { seq.first(1) } - assert_raise(TypeError) { seq.first(3) } - end - - def test_first_bug15518 - bug15518 = '[Bug #15518]' - seq = (1 .. 10.0).step(1) - five_float_classes = Array.new(5) { Float } - assert_equal(five_float_classes, seq.first(5).map(&:class), bug15518) - assert_equal([1.0, 2.0, 3.0, 4.0, 5.0], seq.first(5), bug15518) - seq = (1 .. Float::INFINITY).step(1) - assert_equal(five_float_classes, seq.first(5).map(&:class), bug15518) - assert_equal([1.0, 2.0, 3.0, 4.0, 5.0], seq.first(5), bug15518) - seq = (1 .. Float::INFINITY).step(1r) - assert_equal(five_float_classes, seq.first(5).map(&:class), bug15518) - assert_equal([1.0, 2.0, 3.0, 4.0, 5.0], seq.first(5), bug15518) - end - - def test_last - seq = 1.step(10) - assert_equal(10, seq.last) - assert_equal([10], seq.last(1)) - assert_equal([8, 9, 10], seq.last(3)) - - seq = 1.step(10, 2) - assert_equal(9, seq.last) - assert_equal([9], seq.last(1)) - assert_equal([5, 7, 9], seq.last(3)) - - seq = 10.step(1, -2) - assert_equal(2, seq.last) - assert_equal([2], seq.last(1)) - assert_equal([6, 4, 2], seq.last(3)) - - seq = 10.step(-1, -2) - assert_equal(0, seq.last) - - seq = 1.step(10, 4) - assert_equal([1, 5, 9], seq.last(5)) - - seq = 10.step(1) - assert_equal(nil, seq.last) - assert_equal([], seq.last(1)) - assert_equal([], seq.last(5)) - - seq = 1.step(10, -1) - assert_equal(nil, seq.last) - assert_equal([], seq.last(1)) - assert_equal([], seq.last(5)) - - seq = (1..10).step - assert_equal(10, seq.last) - assert_equal([10], seq.last(1)) - assert_equal([8, 9, 10], seq.last(3)) - - seq = (1...10).step - assert_equal(9, seq.last) - assert_equal([9], seq.last(1)) - assert_equal([7, 8, 9], seq.last(3)) - - seq = 10.0.step(-3.0, by: -2.0) - assert_equal(-2.0, seq.last) - assert_equal([-2.0], seq.last(1)) - assert_equal([2.0, 0.0, -2.0], seq.last(3)) - end - - def test_last_with_float - res = (1..3).step(2).last(2.0) - assert_equal([1, 3], res) - assert_instance_of Integer, res[0] - assert_instance_of Integer, res[1] - - res = (1..3).step(2).last(5.0) - assert_equal([1, 3], res) - assert_instance_of Integer, res[0] - assert_instance_of Integer, res[1] - end - - def test_last_with_rational - res = (1..3).step(2).last(2r) - assert_equal([1, 3], res) - assert_instance_of Integer, res[0] - assert_instance_of Integer, res[1] - - res = (1..3).step(2).last(10/2r) - assert_equal([1, 3], res) - assert_instance_of Integer, res[0] - assert_instance_of Integer, res[1] - end - - def test_last_bug17218 - seq = (1.0997r .. 1.1r).step(0.0001r) - assert_equal(1.1r, seq.last, '[ruby-core:100312] [Bug #17218]') - end - - def test_to_a - assert_equal([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 1.step(10).to_a) - assert_equal([1, 3, 5, 7, 9], 1.step(10, 2).to_a) - assert_equal([1, 3, 5, 7, 9], (1..10).step(2).to_a) - assert_equal([10, 8, 6, 4, 2], 10.step(1, by: -2).to_a) - assert_equal([10, 8, 6, 4, 2], (10..1).step(-2).to_a) - assert_equal([10.0, 8.0, 6.0, 4.0, 2.0], (10.0..1.0).step(-2.0).to_a) - end - - def test_to_a_bug15444 - seq = ((1/10r)..(1/2r)).step(1/10r) - assert_num_equal_type([1/10r, 1/5r, 3/10r, 2/5r, 1/2r], seq.to_a, - '[ruby-core:90648] [Bug #15444]') - end - - def test_to_a_bug17218 - seq = (1.0997r .. 1.1r).step(0.0001r) - assert_equal([1.0997r, 1.0998r, 1.0999r, 1.1r], seq.to_a, '[ruby-core:100312] [Bug #17218]') - end - - def test_slice - seq = 1.step(10, 2) - assert_equal([[1, 3, 5], [7, 9]], seq.each_slice(3).to_a) - - seq = 10.step(1, -2) - assert_equal([[10, 8, 6], [4, 2]], seq.each_slice(3).to_a) - end - - def test_cons - seq = 1.step(10, 2) - assert_equal([[1, 3, 5], [3, 5, 7], [5, 7, 9]], seq.each_cons(3).to_a) - - seq = 10.step(1, -2) - assert_equal([[10, 8, 6], [8, 6, 4], [6, 4, 2]], seq.each_cons(3).to_a) - end - - def test_with_index - seq = 1.step(6, 2) - assert_equal([[1, 0], [3, 1], [5, 2]], seq.with_index.to_a) - assert_equal([[1, 10], [3, 11], [5, 12]], seq.with_index(10).to_a) - - seq = 10.step(5, -2) - assert_equal([[10, 0], [8, 1], [6, 2]], seq.with_index.to_a) - assert_equal([[10, 10], [8, 11], [6, 12]], seq.with_index(10).to_a) - end - - def test_with_object - obj = [0, 1] - seq = 1.step(10, 2) - ret = seq.each_with_object(obj) do |i, memo| - memo[0] += i - memo[1] *= i - end - assert_same(obj, ret) - assert_equal([25, 945], ret) - - obj = [0, 1] - seq = 10.step(1, -2) - ret = seq.each_with_object(obj) do |i, memo| - memo[0] += i - memo[1] *= i - end - assert_same(obj, ret) - assert_equal([30, 3840], ret) - end - - def test_next - seq = 1.step(10, 2) - [1, 3, 5, 7, 9].each do |i| - assert_equal(i, seq.next) - end - - seq = 10.step(1, -2) - [10, 8, 6, 4, 2].each do |i| - assert_equal(i, seq.next) - end - end - - def test_next_bug15444 - seq = ((1/10r)..(1/2r)).step(1/10r) - assert_equal(1/10r, seq.next, '[ruby-core:90648] [Bug #15444]') - end - - def test_next_rewind - seq = 1.step(6, 2) - assert_equal(1, seq.next) - assert_equal(3, seq.next) - seq.rewind - assert_equal(1, seq.next) - assert_equal(3, seq.next) - assert_equal(5, seq.next) - assert_raise(StopIteration) { seq.next } - - seq = 10.step(5, -2) - assert_equal(10, seq.next) - assert_equal(8, seq.next) - seq.rewind - assert_equal(10, seq.next) - assert_equal(8, seq.next) - assert_equal(6, seq.next) - assert_raise(StopIteration) { seq.next } - end - - def test_next_after_stopiteration - seq = 1.step(2, 2) - assert_equal(1, seq.next) - assert_raise(StopIteration) { seq.next } - assert_raise(StopIteration) { seq.next } - seq.rewind - assert_equal(1, seq.next) - assert_raise(StopIteration) { seq.next } - assert_raise(StopIteration) { seq.next } - end - - def test_stop_result - seq = 1.step(2, 2) - res = seq.each {} - assert_equal(1, seq.next) - exc = assert_raise(StopIteration) { seq.next } - assert_equal(res, exc.result) - end - - def test_peek - seq = 1.step(2, 2) - assert_equal(1, seq.peek) - assert_equal(1, seq.peek) - assert_equal(1, seq.next) - assert_raise(StopIteration) { seq.peek } - assert_raise(StopIteration) { seq.peek } - - seq = 10.step(9, -2) - assert_equal(10, seq.peek) - assert_equal(10, seq.peek) - assert_equal(10, seq.next) - assert_raise(StopIteration) { seq.peek } - assert_raise(StopIteration) { seq.peek } - end - - def test_next_values - seq = 1.step(2, 2) - assert_equal([1], seq.next_values) - end - - def test_peek_values - seq = 1.step(2, 2) - assert_equal([1], seq.peek_values) - end - - def test_num_step_inspect - assert_equal('(1.step)', 1.step.inspect) - assert_equal('(1.step(10))', 1.step(10).inspect) - assert_equal('(1.step(10, 2))', 1.step(10, 2).inspect) - assert_equal('(1.step(10, by: 2))', 1.step(10, by: 2).inspect) - assert_equal('(1.step(by: 2))', 1.step(by: 2).inspect) - end - - def test_range_step_inspect - assert_equal('((1..).step)', (1..).step.inspect) - assert_equal('((1..10).step)', (1..10).step.inspect) - assert_equal('((1..10).step(2))', (1..10).step(2).inspect) - end - - def test_num_step_size - assert_equal(10, 1.step(10).size) - assert_equal(5, 1.step(10, 2).size) - assert_equal(4, 1.step(10, 3).size) - assert_equal(1, 1.step(10, 10).size) - assert_equal(0, 1.step(0).size) - assert_equal(Float::INFINITY, 1.step.size) - - assert_equal(10, 10.step(1, -1).size) - assert_equal(5, 10.step(1, -2).size) - assert_equal(4, 10.step(1, -3).size) - assert_equal(1, 10.step(1, -10).size) - assert_equal(0, 1.step(2, -1).size) - assert_equal(Float::INFINITY, 1.step(by: -1).size) - end - - def test_range_step_size - assert_equal(10, (1..10).step.size) - assert_equal(9, (1...10).step.size) - assert_equal(5, (1..10).step(2).size) - assert_equal(5, (1...10).step(2).size) - assert_equal(4, (1...9).step(2).size) - assert_equal(Float::INFINITY, (1..).step.size) - - assert_equal(10, (10..1).step(-1).size) - assert_equal(9, (10...1).step(-1).size) - assert_equal(5, (10..1).step(-2).size) - assert_equal(5, (10...1).step(-2).size) - assert_equal(4, (10...2).step(-2).size) - assert_equal(Float::INFINITY, (1..).step(-1).size) - end - - def assert_num_equal_type(ary1, ary2, message=nil) - assert_equal(ary1.length, ary2.length, message) - ary1.zip(ary2) do |e1, e2| - assert_equal(e1.class, e2.class, message) - if e1.is_a? Complex - assert_equal(e1.real, e2.real, message) - assert_equal(e1.imag, e2.imag, message) - else - assert_equal(e1, e2, message) - end - end - end - - def test_complex - assert_num_equal_type([1, 1+1i, 1+2i], (1..).step(1i).take(3)) - assert_num_equal_type([1, 1+1.0i, 1+2.0i], (1..).step(1.0i).take(3)) - assert_num_equal_type([0.0, 0.0+1.0i, 0.0+2.0i], (0.0..).step(1.0i).take(3)) - assert_num_equal_type([0.0+0.0i, 0.0+1.0i, 0.0+2.0i], (0.0i..).step(1.0i).take(3)) - end - - def test_sum - assert_equal([1, 3, 5, 7, 9].sum, (1..10).step(2).sum) - assert_equal([1.0, 2.5, 4.0, 5.5, 7.0, 8.5, 10.0].sum, (1.0..10.0).step(1.5).sum) - assert_equal([1/2r, 1r, 3/2r, 2, 5/2r, 3, 7/2r, 4].sum, ((1/2r)...(9/2r)).step(1/2r).sum) - end -end diff --git a/test/ruby/test_array.rb b/test/ruby/test_array.rb index 522b58e214..3212ed3aca 100644 --- a/test/ruby/test_array.rb +++ b/test/ruby/test_array.rb @@ -7,6 +7,7 @@ require "rbconfig/sizeof" class TestArray < Test::Unit::TestCase def setup @verbose = $VERBOSE + $VERBOSE = nil @cls = Array end @@ -14,11 +15,6 @@ class TestArray < Test::Unit::TestCase $VERBOSE = @verbose end - def assert_equal_instance(x, y, *msg) - assert_equal(x, y, *msg) - assert_instance_of(x.class, y) - end - def test_percent_i assert_equal([:foo, :bar], %i[foo bar]) assert_equal([:"\"foo"], %i["foo]) @@ -45,9 +41,6 @@ class TestArray < Test::Unit::TestCase assert_equal(2, x[2]) assert_equal([1, 2, 3], x[1..3]) assert_equal([1, 2, 3], x[1,3]) - assert_equal([3, 4, 5], x[3..]) - assert_equal([0, 1, 2], x[..2]) - assert_equal([0, 1], x[...2]) x[0, 2] = 10 assert_equal([10, 2, 3, 4, 5], x) @@ -118,9 +111,6 @@ class TestArray < Test::Unit::TestCase assert_equal('1', (x * 1).join(":")) assert_equal('', (x * 0).join(":")) - assert_instance_of(Array, (@cls[] * 5)) - assert_instance_of(Array, (@cls[1] * 5)) - *x = *(1..7).to_a assert_equal(7, x.size) assert_equal([1, 2, 3, 4, 5, 6, 7], x) @@ -155,17 +145,14 @@ class TestArray < Test::Unit::TestCase assert_equal(1, x.first) assert_equal([1], x.first(1)) assert_equal([1, 2, 3], x.first(3)) - assert_raise_with_message(ArgumentError, /0\.\.1/) {x.first(1, 2)} assert_equal(5, x.last) assert_equal([5], x.last(1)) assert_equal([3, 4, 5], x.last(3)) - assert_raise_with_message(ArgumentError, /0\.\.1/) {x.last(1, 2)} assert_equal(1, x.shift) assert_equal([2, 3, 4], x.shift(3)) assert_equal([5], x) - assert_raise_with_message(ArgumentError, /0\.\.1/) {x.first(1, 2)} assert_equal([2, 3, 4, 5], x.unshift(2, 3, 4)) assert_equal([1, 2, 3, 4, 5], x.unshift(1)) @@ -174,7 +161,6 @@ class TestArray < Test::Unit::TestCase assert_equal(5, x.pop) assert_equal([3, 4], x.pop(2)) assert_equal([1, 2], x) - assert_raise_with_message(ArgumentError, /0\.\.1/) {x.pop(1, 2)} assert_equal([1, 2, 3, 4], x.push(3, 4)) assert_equal([1, 2, 3, 4, 5], x.push(5)) @@ -184,7 +170,6 @@ class TestArray < Test::Unit::TestCase def test_find_all_0 assert_respond_to([], :find_all) assert_respond_to([], :select) # Alias - assert_respond_to([], :filter) # Alias assert_equal([], [].find_all{ |obj| obj == "foo"}) x = ["foo", "bar", "baz", "baz", 1, 2, 3, 3, 4] @@ -213,8 +198,6 @@ class TestArray < Test::Unit::TestCase assert_equal([0, 1, 2, 13, 4, 5], [0, 1, 2, 3, 4, 5].fill(3...4){|i| i+10}) assert_equal([0, 1, 12, 13, 14, 5], [0, 1, 2, 3, 4, 5].fill(2..-2){|i| i+10}) assert_equal([0, 1, 12, 13, 4, 5], [0, 1, 2, 3, 4, 5].fill(2...-2){|i| i+10}) - assert_equal([0, 1, 2, 13, 14, 15], [0, 1, 2, 3, 4, 5].fill(3..){|i| i+10}) - assert_equal([0, 1, 2, 13, 14, 15], [0, 1, 2, 3, 4, 5].fill(3...){|i| i+10}) end # From rubicon @@ -248,23 +231,6 @@ class TestArray < Test::Unit::TestCase assert_equal(@cls[], @cls[ 1, 2, 3 ]*64 & @cls[ 4, 5, 6 ]*64) end - def test_intersection - assert_equal(@cls[1, 2], @cls[1, 2, 3].intersection(@cls[1, 2])) - assert_equal(@cls[ ], @cls[1].intersection(@cls[ ])) - assert_equal(@cls[ ], @cls[ ].intersection(@cls[1])) - assert_equal(@cls[1], @cls[1, 2, 3].intersection(@cls[1, 2], @cls[1])) - assert_equal(@cls[ ], @cls[1, 2, 3].intersection(@cls[1, 2], @cls[3])) - assert_equal(@cls[ ], @cls[1, 2, 3].intersection(@cls[4, 5, 6])) - end - - def test_intersection_big_array - assert_equal(@cls[1, 2], (@cls[1, 2, 3] * 64).intersection(@cls[1, 2] * 64)) - assert_equal(@cls[ ], (@cls[1] * 64).intersection(@cls[ ])) - assert_equal(@cls[ ], @cls[ ].intersection(@cls[1] * 64)) - assert_equal(@cls[1], (@cls[1, 2, 3] * 64).intersection((@cls[1, 2] * 64), (@cls[1] * 64))) - assert_equal(@cls[ ], (@cls[1, 2, 3] * 64).intersection(@cls[4, 5, 6] * 64)) - end - def test_MUL # '*' assert_equal(@cls[], @cls[]*3) assert_equal(@cls[1, 1, 1], @cls[1]*3) @@ -288,39 +254,29 @@ class TestArray < Test::Unit::TestCase def test_MINUS # '-' assert_equal(@cls[], @cls[1] - @cls[1]) assert_equal(@cls[1], @cls[1, 2, 3, 4, 5] - @cls[2, 3, 4, 5]) + # Ruby 1.8 feature change + #assert_equal(@cls[1], @cls[1, 2, 1, 3, 1, 4, 1, 5] - @cls[2, 3, 4, 5]) assert_equal(@cls[1, 1, 1, 1], @cls[1, 2, 1, 3, 1, 4, 1, 5] - @cls[2, 3, 4, 5]) + a = @cls[] + 1000.times { a << 1 } + assert_equal(1000, a.length) + #assert_equal(@cls[1], a - @cls[2]) + assert_equal(@cls[1] * 1000, a - @cls[2]) + #assert_equal(@cls[1], @cls[1, 2, 1] - @cls[2]) assert_equal(@cls[1, 1], @cls[1, 2, 1] - @cls[2]) assert_equal(@cls[1, 2, 3], @cls[1, 2, 3] - @cls[4, 5, 6]) end def test_MINUS_big_array # '-' assert_equal(@cls[1]*64, @cls[1, 2, 3, 4, 5]*64 - @cls[2, 3, 4, 5]*64) + # Ruby 1.8 feature change + #assert_equal(@cls[1], @cls[1, 2, 1, 3, 1, 4, 1, 5]*64 - @cls[2, 3, 4, 5]*64) assert_equal(@cls[1, 1, 1, 1]*64, @cls[1, 2, 1, 3, 1, 4, 1, 5]*64 - @cls[2, 3, 4, 5]*64) a = @cls[] 1000.times { a << 1 } assert_equal(1000, a.length) - assert_equal(@cls[1] * 1000, a - @cls[2]) - end - - def test_difference - assert_equal(@cls[], @cls[1].difference(@cls[1])) - assert_equal(@cls[1], @cls[1, 2, 3, 4, 5].difference(@cls[2, 3, 4, 5])) - assert_equal(@cls[1, 1], @cls[1, 2, 1].difference(@cls[2])) - assert_equal(@cls[1, 1, 1, 1], @cls[1, 2, 1, 3, 1, 4, 1, 5].difference(@cls[2, 3, 4, 5])) - assert_equal(@cls[], @cls[1, 2, 3, 4].difference(@cls[1], @cls[2], @cls[3], @cls[4])) - a = [1] - assert_equal(@cls[1], a.difference(@cls[2], @cls[2])) - assert_equal(@cls[], a.difference(@cls[1])) - assert_equal(@cls[1], a) - end - - def test_difference_big_array - assert_equal(@cls[1]*64, (@cls[1, 2, 3, 4, 5] * 64).difference(@cls[2, 3, 4] * 64, @cls[3, 5] * 64)) - assert_equal(@cls[1, 1, 1, 1]*64, (@cls[1, 2, 1, 3, 1, 4, 1, 5] * 64).difference(@cls[2, 3, 4, 5] * 64)) - a = @cls[1] * 1000 - assert_equal(@cls[1] * 1000, a.difference(@cls[2], @cls[2])) - assert_equal(@cls[], a.difference(@cls[1])) - assert_equal(@cls[1] * 1000, a) + #assert_equal(@cls[1], a - @cls[2]) + assert_equal(@cls[1] * 1000, a - @cls[2]) end def test_LSHIFT # '<<' @@ -396,15 +352,12 @@ class TestArray < Test::Unit::TestCase assert_equal(@cls[99], a[-2..-2]) assert_equal(@cls[10, 11, 12], a[9..11]) - assert_equal(@cls[98, 99, 100], a[97..]) - assert_equal(@cls[1, 2, 3], a[..2]) - assert_equal(@cls[1, 2], a[...2]) assert_equal(@cls[10, 11, 12], a[-91..-89]) - assert_equal(@cls[98, 99, 100], a[-3..]) - assert_equal(@cls[1, 2, 3], a[..-98]) - assert_equal(@cls[1, 2], a[...-98]) assert_nil(a[10, -3]) + # Ruby 1.8 feature change: + # Array#[size..x] returns [] instead of nil. + #assert_nil(a[10..7]) assert_equal [], a[10..7] assert_raise(TypeError) {a['cat']} @@ -460,41 +413,33 @@ class TestArray < Test::Unit::TestCase assert_equal(b, a[10..19] = b) assert_equal(@cls[*(0..9).to_a] + b + @cls[*(20..99).to_a], a) + # Ruby 1.8 feature change: + # assigning nil does not remove elements. +=begin a = @cls[*(0..99).to_a] assert_equal(nil, a[0,1] = nil) - assert_equal(@cls[nil] + @cls[*(1..99).to_a], a) + assert_equal(@cls[*(1..99).to_a], a) a = @cls[*(0..99).to_a] assert_equal(nil, a[10,10] = nil) - assert_equal(@cls[*(0..9).to_a] + @cls[nil] + @cls[*(20..99).to_a], a) + assert_equal(@cls[*(0..9).to_a] + @cls[*(20..99).to_a], a) a = @cls[*(0..99).to_a] assert_equal(nil, a[-1, 1] = nil) - assert_equal(@cls[*(0..98).to_a] + @cls[nil], a) + assert_equal(@cls[*(0..98).to_a], a) a = @cls[*(0..99).to_a] assert_equal(nil, a[-10, 10] = nil) - assert_equal(@cls[*(0..89).to_a] + @cls[nil], a) + assert_equal(@cls[*(0..89).to_a], a) a = @cls[*(0..99).to_a] assert_equal(nil, a[0,1000] = nil) - assert_equal(@cls[nil] , a) + assert_equal(@cls[] , a) a = @cls[*(0..99).to_a] assert_equal(nil, a[10..19] = nil) - assert_equal(@cls[*(0..9).to_a] + @cls[nil] + @cls[*(20..99).to_a], a) - - a = @cls[*(0..99).to_a] - assert_equal(nil, a[10..] = nil) - assert_equal(@cls[*(0..9).to_a] + @cls[nil], a) - - a = @cls[*(0..99).to_a] - assert_equal(nil, a[..10] = nil) - assert_equal(@cls[nil] + @cls[*(11..99).to_a], a) - - a = @cls[*(0..99).to_a] - assert_equal(nil, a[...10] = nil) - assert_equal(@cls[nil] + @cls[*(10..99).to_a], a) + assert_equal(@cls[*(0..9).to_a] + @cls[*(20..99).to_a], a) +=end a = @cls[1, 2, 3] a[1, 0] = a @@ -563,14 +508,18 @@ class TestArray < Test::Unit::TestCase end def test_clone - for frozen in [ false, true ] - a = @cls[*(0..99).to_a] - a.freeze if frozen - b = a.clone - - assert_equal(a, b) - assert_not_equal(a.__id__, b.__id__) - assert_equal(a.frozen?, b.frozen?) + for taint in [ false, true ] + for frozen in [ false, true ] + a = @cls[*(0..99).to_a] + a.taint if taint + a.freeze if frozen + b = a.clone + + assert_equal(a, b) + assert_not_equal(a.__id__, b.__id__) + assert_equal(a.frozen?, b.frozen?) + assert_equal(a.tainted?, b.tainted?) + end end end @@ -581,11 +530,12 @@ class TestArray < Test::Unit::TestCase assert_equal([], @cls[].collect { 99 }) + # Ruby 1.9 feature change: + # Enumerable#collect without block returns an Enumerator. + #assert_equal([1, 2, 3], @cls[1, 2, 3].collect) assert_kind_of Enumerator, @cls[1, 2, 3].collect - assert_raise(ArgumentError) { - assert_equal([[1, 2, 3]], [[1, 2, 3]].collect(&->(a, b, c) {[a, b, c]})) - } + assert_equal([[1, 2, 3]], [[1, 2, 3]].collect(&->(a, b, c) {[a, b, c]})) end # also update map! @@ -661,7 +611,7 @@ class TestArray < Test::Unit::TestCase assert_equal(5, a.count) assert_equal(2, a.count(1)) assert_equal(3, a.count {|x| x % 2 == 1 }) - assert_equal(2, assert_warning(/given block not used/) {a.count(1) {|x| x % 2 == 1 }}) + assert_equal(2, a.count(1) {|x| x % 2 == 1 }) assert_raise(ArgumentError) { a.count(0, 1) } bug8654 = '[ruby-core:56072]' @@ -757,14 +707,18 @@ class TestArray < Test::Unit::TestCase end def test_dup - for frozen in [ false, true ] - a = @cls[*(0..99).to_a] - a.freeze if frozen - b = a.dup - - assert_equal(a, b) - assert_not_equal(a.__id__, b.__id__) - assert_equal(false, b.frozen?) + for taint in [ false, true ] + for frozen in [ false, true ] + a = @cls[*(0..99).to_a] + a.taint if taint + a.freeze if frozen + b = a.dup + + assert_equal(a, b) + assert_not_equal(a.__id__, b.__id__) + assert_equal(false, b.frozen?) + assert_equal(a.tainted?, b.tainted?) + end end end @@ -780,7 +734,7 @@ class TestArray < Test::Unit::TestCase a = @cls[] i = 0 a.each { |e| - assert(false, "Never get here") + assert_equal(a[i], e) i += 1 } assert_equal(0, i) @@ -800,7 +754,7 @@ class TestArray < Test::Unit::TestCase a = @cls[] i = 0 a.each_index { |ind| - assert(false, "Never get here") + assert_equal(i, ind) i += 1 } assert_equal(0, i) @@ -849,14 +803,14 @@ class TestArray < Test::Unit::TestCase a2 = @cls[ 5, 6 ] a3 = @cls[ 4, a2 ] a4 = @cls[ a1, a3 ] - assert_equal_instance([1, 2, 3, 4, 5, 6], a4.flatten) - assert_equal_instance(@cls[ a1, a3], a4) + assert_equal(@cls[1, 2, 3, 4, 5, 6], a4.flatten) + assert_equal(@cls[ a1, a3], a4) a5 = @cls[ a1, @cls[], a3 ] - assert_equal_instance([1, 2, 3, 4, 5, 6], a5.flatten) - assert_equal_instance([1, 2, 3, 4, [5, 6]], a5.flatten(1)) - assert_equal_instance([], @cls[].flatten) - assert_equal_instance([], + assert_equal(@cls[1, 2, 3, 4, 5, 6], a5.flatten) + assert_equal(@cls[1, 2, 3, 4, [5, 6]], a5.flatten(1)) + assert_equal(@cls[], @cls[].flatten) + assert_equal(@cls[], @cls[@cls[@cls[@cls[],@cls[]],@cls[@cls[]],@cls[]],@cls[@cls[@cls[]]]].flatten) end @@ -864,6 +818,13 @@ class TestArray < Test::Unit::TestCase assert_raise(TypeError, "[ruby-dev:31197]") { [[]].flatten("") } end + def test_flatten_taint + a6 = @cls[[1, 2], 3] + a6.taint + a7 = a6.flatten + assert_equal(true, a7.tainted?) + end + def test_flatten_level0 a8 = @cls[[1, 2], 3] a9 = a8.flatten(0) @@ -893,17 +854,6 @@ class TestArray < Test::Unit::TestCase assert_raise(NoMethodError, bug12738) { a.flatten.m } end - def test_flatten_recursive - a = [] - a << a - assert_raise(ArgumentError) { a.flatten } - b = [1]; c = [2, b]; b << c - assert_raise(ArgumentError) { b.flatten } - - assert_equal([1, 2, b], b.flatten(1)) - assert_equal([1, 2, 1, 2, 1, c], b.flatten(4)) - end - def test_flatten! a1 = @cls[ 1, 2, 3] a2 = @cls[ 5, 6 ] @@ -1099,7 +1049,7 @@ class TestArray < Test::Unit::TestCase assert_nil(a.index('ca')) assert_nil(a.index([1,2])) - assert_equal(1, assert_warn(/given block not used/) {a.index(99) {|x| x == 'cat' }}) + assert_equal(1, a.index(99) {|x| x == 'cat' }) end def test_values_at @@ -1110,42 +1060,56 @@ class TestArray < Test::Unit::TestCase end def test_join - assert_deprecated_warning {$, = ""} + $, = "" a = @cls[] - assert_equal("", assert_deprecated_warn(/non-nil value/) {a.join}) + assert_equal("", 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, a.join.encoding) - assert_deprecated_warning {$, = ""} + $, = "" 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", a.join) + assert_equal("12", a.join(nil)) assert_equal("1,2", a.join(',')) - assert_deprecated_warning {$, = ""} + $, = "" 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", a.join) + assert_equal("123", a.join(nil)) assert_equal("1,2,3", a.join(',')) - assert_deprecated_warning {$, = ":"} + $, = ":" 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)}) + assert_equal("1:2:3", a.join) + assert_equal("1:2:3", a.join(nil)) assert_equal("1,2,3", a.join(',')) - assert_deprecated_warning {$, = ""} + $, = "" + a = @cls[1, 2, 3] + a.taint + s = a.join + assert_equal(true, s.tainted?) + + bug5902 = '[ruby-core:42161]' + sep = ":".taint + + s = @cls[].join(sep) + assert_equal(false, s.tainted?, bug5902) + s = @cls[1].join(sep) + assert_equal(false, s.tainted?, bug5902) + s = @cls[1, 2].join(sep) + assert_equal(true, s.tainted?, bug5902) 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, [[]].join.encoding) + assert_equal(Encoding::US_ASCII, [1, [u]].join.encoding) + assert_equal(Encoding::UTF_8, [u, [e]].join.encoding) + assert_equal(Encoding::UTF_8, [u, [1]].join.encoding) + assert_equal(Encoding::UTF_8, [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, [[], u, nil].join.encoding, bug5379) + assert_equal(Encoding::UTF_8, [[], "\u3042", nil].join.encoding, bug5379) ensure $, = nil end @@ -1285,6 +1249,9 @@ class TestArray < Test::Unit::TestCase a = @cls[1, 2, 3] assert_equal(@cls[1, 2, 3, 4, 5], a.push(4, 5)) assert_equal(@cls[1, 2, 3, 4, 5, nil], a.push(nil)) + # Ruby 1.8 feature: + # Array#push accepts any number of arguments. + #assert_raise(ArgumentError, "a.push()") { a.push() } a.push assert_equal @cls[1, 2, 3, 4, 5, nil], a a.push 6, 7 @@ -1410,6 +1377,9 @@ class TestArray < Test::Unit::TestCase a = @cls[*%w( dog cat bee ant )] assert_equal(@cls[*%w(ant bee cat dog)], a.reverse!) assert_equal(@cls[*%w(ant bee cat dog)], a) + # Ruby 1.8 feature change: + # Array#reverse always returns self. + #assert_nil(@cls[].reverse!) assert_equal @cls[], @cls[].reverse! end @@ -1439,17 +1409,7 @@ class TestArray < Test::Unit::TestCase assert_nil(a.rindex('ca')) assert_nil(a.rindex([1,2])) - assert_equal(3, assert_warning(/given block not used/) {a.rindex(99) {|x| x == [1,2,3] }}) - - bug15951 = "[Bug #15951]" - o2 = Object.new - def o2.==(other) - other.replace([]) if Array === other - false - end - a = Array.new(10) - a.fill(o2) - assert_nil(a.rindex(a), bug15951) + assert_equal(3, a.rindex(99) {|x| x == [1,2,3] }) end def test_shift @@ -1479,71 +1439,34 @@ class TestArray < Test::Unit::TestCase assert_equal(1, a.slice(-100)) assert_nil(a.slice(-101)) - assert_equal_instance([1], a.slice(0,1)) - assert_equal_instance([100], a.slice(99,1)) - assert_equal_instance([], a.slice(100,1)) - assert_equal_instance([100], a.slice(99,100)) - assert_equal_instance([100], a.slice(-1,1)) - assert_equal_instance([99], a.slice(-2,1)) + assert_equal(@cls[1], a.slice(0,1)) + assert_equal(@cls[100], a.slice(99,1)) + assert_equal(@cls[], a.slice(100,1)) + assert_equal(@cls[100], a.slice(99,100)) + assert_equal(@cls[100], a.slice(-1,1)) + assert_equal(@cls[99], a.slice(-2,1)) - assert_equal_instance([10, 11, 12], a.slice(9, 3)) - assert_equal_instance([10, 11, 12], a.slice(-91, 3)) + assert_equal(@cls[10, 11, 12], a.slice(9, 3)) + assert_equal(@cls[10, 11, 12], a.slice(-91, 3)) assert_nil(a.slice(-101, 2)) - assert_equal_instance([1], a.slice(0..0)) - assert_equal_instance([100], a.slice(99..99)) - assert_equal_instance([], a.slice(100..100)) - assert_equal_instance([100], a.slice(99..200)) - assert_equal_instance([100], a.slice(-1..-1)) - assert_equal_instance([99], a.slice(-2..-2)) - - assert_equal_instance([10, 11, 12], a.slice(9..11)) - assert_equal_instance([98, 99, 100], a.slice(97..)) - assert_equal_instance([10, 11, 12], a.slice(-91..-89)) - assert_equal_instance([10, 11, 12], a.slice(-91..-89)) - - assert_equal_instance([5, 8, 11], a.slice((4..12)%3)) - assert_equal_instance([95, 97, 99], a.slice((94..)%2)) - - # [0] [1] [2] [3] [4] [5] [6] [7] - # ary = [ 1 2 3 4 5 6 7 8 ... ] - # (0) (1) (2) <- (..7) % 3 - # (2) (1) (0) <- (7..) % -3 - assert_equal_instance([1, 4, 7], a.slice((..7)%3)) - assert_equal_instance([8, 5, 2], a.slice((7..)% -3)) - - # [-98] [-97] [-96] [-95] [-94] [-93] [-92] [-91] [-90] - # ary = [ ... 3 4 5 6 7 8 9 10 11 ... ] - # (0) (1) (2) <- (-98..-90) % 3 - # (2) (1) (0) <- (-90..-98) % -3 - assert_equal_instance([3, 6, 9], a.slice((-98..-90)%3)) - assert_equal_instance([11, 8, 5], a.slice((-90..-98)% -3)) - - # [ 48] [ 49] [ 50] [ 51] [ 52] [ 53] - # [-52] [-51] [-50] [-49] [-48] [-47] - # ary = [ ... 49 50 51 52 53 54 ... ] - # (0) (1) (2) <- (48..-47) % 2 - # (2) (1) (0) <- (-47..48) % -2 - assert_equal_instance([49, 51, 53], a.slice((48..-47)%2)) - assert_equal_instance([54, 52, 50], a.slice((-47..48)% -2)) - - idx = ((3..90) % 2).to_a - assert_equal_instance(a.values_at(*idx), a.slice((3..90)%2)) - idx = 90.step(3, -2).to_a - assert_equal_instance(a.values_at(*idx), a.slice((90 .. 3)% -2)) - end - - def test_slice_out_of_range - a = @cls[*(1..100).to_a] + assert_equal(@cls[1], a.slice(0..0)) + assert_equal(@cls[100], a.slice(99..99)) + assert_equal(@cls[], a.slice(100..100)) + assert_equal(@cls[100], a.slice(99..200)) + assert_equal(@cls[100], a.slice(-1..-1)) + assert_equal(@cls[99], a.slice(-2..-2)) - assert_nil(a.slice(-101..-1)) - assert_nil(a.slice(-101..)) + assert_equal(@cls[10, 11, 12], a.slice(9..11)) + assert_equal(@cls[10, 11, 12], a.slice(-91..-89)) - assert_raise_with_message(RangeError, "((-101..-1).%(2)) out of range") { a.slice((-101..-1)%2) } - assert_raise_with_message(RangeError, "((-101..).%(2)) out of range") { a.slice((-101..)%2) } + assert_nil(a.slice(-101..-1)) assert_nil(a.slice(10, -3)) + # Ruby 1.8 feature change: + # Array#slice[size..x] always returns []. + #assert_nil(a.slice(10..7)) assert_equal @cls[], a.slice(10..7) end @@ -1557,18 +1480,15 @@ class TestArray < Test::Unit::TestCase assert_equal(@cls[1, 2, 3, 5], a) a = @cls[1, 2, 3, 4, 5] - s = a.slice!(2,2) - assert_equal_instance([3,4], s) + assert_equal(@cls[3,4], a.slice!(2,2)) assert_equal(@cls[1, 2, 5], a) a = @cls[1, 2, 3, 4, 5] - s = a.slice!(-2,2) - assert_equal_instance([4,5], s) + assert_equal(@cls[4,5], a.slice!(-2,2)) assert_equal(@cls[1, 2, 3], a) a = @cls[1, 2, 3, 4, 5] - s = a.slice!(2..3) - assert_equal_instance([3,4], s) + assert_equal(@cls[3,4], a.slice!(2..3)) assert_equal(@cls[1, 2, 5], a) a = @cls[1, 2, 3, 4, 5] @@ -1587,8 +1507,6 @@ class TestArray < Test::Unit::TestCase assert_equal(nil, a.slice!(-6,2)) assert_equal(@cls[1, 2, 3, 4, 5], a) - assert_equal("[2, 3]", [1,2,3].slice!(1,10000).inspect, "moved from btest/knownbug") - assert_raise(ArgumentError) { @cls[1].slice! } assert_raise(ArgumentError) { @cls[1].slice!(0, 0, 0) } end @@ -1652,21 +1570,13 @@ class TestArray < Test::Unit::TestCase end def test_sort_with_replace - bug = '[ruby-core:34732]' - assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}", timeout: 30) - bug = "#{bug}" - begin; - xary = (1..100).to_a - 100.times do - ary = (1..100).to_a - ary.sort! {|a,b| ary.replace(xary); a <=> b} - GC.start - assert_equal(xary, ary, '[ruby-dev:34732]') - end - assert_nothing_raised(SystemStackError, bug) do - assert_equal(:ok, Array.new(100_000, nil).permutation {break :ok}) - end - end; + xary = (1..100).to_a + 100.times do + ary = (1..100).to_a + ary.sort! {|a,b| ary.replace(xary); a <=> b} + GC.start + assert_equal(xary, ary, '[ruby-dev:34732]') + end end def test_sort_bang_with_freeze @@ -1695,13 +1605,6 @@ class TestArray < Test::Unit::TestCase TEST end - def test_sort_uncomparable - assert_raise(ArgumentError) {[1, Float::NAN].sort} - assert_raise(ArgumentError) {[1.0, Float::NAN].sort} - assert_raise(ArgumentError) {[Float::NAN, 1].sort} - assert_raise(ArgumentError) {[Float::NAN, 1.0].sort} - end - def test_to_a a = @cls[ 1, 2, 3 ] a_id = a.__id__ @@ -1729,40 +1632,38 @@ class TestArray < Test::Unit::TestCase def o.to_ary foo_bar() end - assert_raise_with_message(NoMethodError, /foo_bar/) {a.concat(o)} + assert_match(/foo_bar/, assert_raise(NoMethodError) {a.concat(o)}.message) end def test_to_s - assert_deprecated_warning {$, = ""} + $, = "" a = @cls[] assert_equal("[]", a.to_s) - assert_deprecated_warning {$, = ""} + $, = "" a = @cls[1, 2] assert_equal("[1, 2]", a.to_s) - assert_deprecated_warning {$, = ""} + $, = "" a = @cls[1, 2, 3] assert_equal("[1, 2, 3]", a.to_s) - assert_deprecated_warning {$, = ""} + $, = ":" a = @cls[1, 2, 3] assert_equal("[1, 2, 3]", a.to_s) ensure $, = nil end - StubToH = [ - [:key, :value], - Object.new.tap do |kvp| - def kvp.to_ary - [:obtained, :via_to_ary] - end - end, - ] - def test_to_h - array = StubToH + kvp = Object.new + def kvp.to_ary + [:obtained, :via_to_ary] + end + array = [ + [:key, :value], + kvp, + ] assert_equal({key: :value, obtained: :via_to_ary}, array.to_h) e = assert_raise(TypeError) { @@ -1777,34 +1678,11 @@ class TestArray < Test::Unit::TestCase assert_equal "wrong array length at 2 (expected 2, was 1)", e.message end - def test_to_h_block - array = StubToH - assert_equal({"key" => "value", "obtained" => "via_to_ary"}, - array.to_h {|k, v| [k.to_s, v.to_s]}) - - assert_equal({first_one: :ok, not_ok: :ng}, - [[:first_one, :ok], :not_ok].to_h {|k, v| [k, v || :ng]}) - - e = assert_raise(TypeError) { - [[:first_one, :ok], :not_ok].to_h {|k, v| v ? [k, v] : k} - } - assert_equal "wrong element type Symbol at 1 (expected array)", e.message - array = [1] - k = eval("class C\u{1f5ff}; self; end").new - assert_raise_with_message(TypeError, /C\u{1f5ff}/) {array.to_h {k}} - e = assert_raise(ArgumentError) { - [[:first_one, :ok], [1, 2], [:not_ok]].to_h {|kv| kv} - } - assert_equal "wrong array length at 2 (expected 2, was 1)", e.message - end - def test_min - assert_equal(3, [3].min) assert_equal(1, [1, 2, 3, 1, 2].min) assert_equal(3, [1, 2, 3, 1, 2].min {|a,b| b <=> a }) cond = ->((a, ia), (b, ib)) { (b <=> a).nonzero? or ia <=> ib } assert_equal([3, 2], [1, 2, 3, 1, 2].each_with_index.min(&cond)) - assert_equal(1.0, [3.0, 1.0, 2.0].min) ary = %w(albatross dog horse) assert_equal("albatross", ary.min) assert_equal("dog", ary.min {|a,b| a.length <=> b.length }) @@ -1822,20 +1700,11 @@ class TestArray < Test::Unit::TestCase assert_same(obj, [obj, 1.0].min) end - def test_min_uncomparable - assert_raise(ArgumentError) {[1, Float::NAN].min} - assert_raise(ArgumentError) {[1.0, Float::NAN].min} - assert_raise(ArgumentError) {[Float::NAN, 1].min} - assert_raise(ArgumentError) {[Float::NAN, 1.0].min} - end - def test_max - assert_equal(1, [1].max) assert_equal(3, [1, 2, 3, 1, 2].max) assert_equal(1, [1, 2, 3, 1, 2].max {|a,b| b <=> a }) cond = ->((a, ia), (b, ib)) { (b <=> a).nonzero? or ia <=> ib } assert_equal([1, 3], [1, 2, 3, 1, 2].each_with_index.max(&cond)) - assert_equal(3.0, [1.0, 3.0, 2.0].max) ary = %w(albatross dog horse) assert_equal("horse", ary.max) assert_equal("albatross", ary.max {|a,b| a.length <=> b.length }) @@ -1852,33 +1721,6 @@ class TestArray < Test::Unit::TestCase assert_same(obj, [obj, 1.0].max) end - def test_max_uncomparable - assert_raise(ArgumentError) {[1, Float::NAN].max} - assert_raise(ArgumentError) {[1.0, Float::NAN].max} - assert_raise(ArgumentError) {[Float::NAN, 1].max} - assert_raise(ArgumentError) {[Float::NAN, 1.0].max} - end - - def test_minmax - assert_equal([3, 3], [3].minmax) - assert_equal([1, 3], [1, 2, 3, 1, 2].minmax) - assert_equal([3, 1], [1, 2, 3, 1, 2].minmax {|a,b| b <=> a }) - cond = ->((a, ia), (b, ib)) { (b <=> a).nonzero? or ia <=> ib } - assert_equal([[3, 2], [1, 3]], [1, 2, 3, 1, 2].each_with_index.minmax(&cond)) - ary = %w(albatross dog horse) - assert_equal(["albatross", "horse"], ary.minmax) - assert_equal(["dog", "albatross"], ary.minmax {|a,b| a.length <=> b.length }) - assert_equal([1, 3], [3,2,1].minmax) - - class << (obj = Object.new) - def <=>(x) 1 <=> x end - def coerce(x) [x, 1] end - end - ary = [obj, 1.0].minmax - assert_same(obj, ary[0]) - assert_equal(obj, ary[1]) - end - def test_uniq a = [] b = a.uniq @@ -1927,27 +1769,6 @@ class TestArray < Test::Unit::TestCase ary = [bug9340, bug9340.dup, bug9340.dup] assert_equal 1, ary.uniq.size assert_same bug9340, ary.uniq[0] - - sc = Class.new(@cls) - a = sc[] - b = a.dup - assert_equal_instance([], a.uniq) - assert_equal(b, a) - - a = sc[1] - b = a.dup - assert_equal_instance([1], a.uniq) - assert_equal(b, a) - - a = sc[1, 1] - b = a.dup - assert_equal_instance([1], a.uniq) - assert_equal(b, a) - - a = sc[1, 1] - b = a.dup - assert_equal_instance([1], a.uniq{|x| x}) - assert_equal(b, a) end def test_uniq_with_block @@ -2144,44 +1965,6 @@ class TestArray < Test::Unit::TestCase assert_equal((1..128).to_a, b) end - def test_union - assert_equal(@cls[], @cls[].union(@cls[])) - assert_equal(@cls[1], @cls[1].union(@cls[])) - assert_equal(@cls[1], @cls[].union(@cls[1])) - assert_equal(@cls[1], @cls[].union(@cls[], @cls[1])) - assert_equal(@cls[1], @cls[1].union(@cls[1])) - assert_equal(@cls[1], @cls[1].union(@cls[1], @cls[1], @cls[1])) - - assert_equal(@cls[1,2], @cls[1].union(@cls[2])) - assert_equal(@cls[1,2], @cls[1, 1].union(@cls[2, 2])) - assert_equal(@cls[1,2], @cls[1, 2].union(@cls[1, 2])) - assert_equal(@cls[1,2], @cls[1, 1].union(@cls[1, 1], @cls[1, 2], @cls[2, 1], @cls[2, 2, 2])) - - a = %w(a b c) - b = %w(a b c d e) - c = a.union(b) - assert_equal(c, b) - assert_not_same(c, b) - assert_equal(%w(a b c), a) - assert_equal(%w(a b c d e), b) - assert(a.none?(&:frozen?)) - assert(b.none?(&:frozen?)) - assert(c.none?(&:frozen?)) - end - - def test_union_big_array - assert_equal(@cls[1,2], (@cls[1]*64).union(@cls[2]*64)) - assert_equal(@cls[1,2,3], (@cls[1, 2]*64).union(@cls[1, 2]*64, @cls[3]*60)) - - a = (1..64).to_a - b = (1..128).to_a - c = a | b - assert_equal(c, b) - assert_not_same(c, b) - assert_equal((1..64).to_a, a) - assert_equal((1..128).to_a, b) - end - def test_combination a = @cls[] assert_equal(1, a.combination(0).size) @@ -2361,23 +2144,23 @@ class TestArray < Test::Unit::TestCase end def test_take - assert_equal_instance([1,2,3], @cls[1,2,3,4,5,0].take(3)) + assert_equal([1,2,3], [1,2,3,4,5,0].take(3)) assert_raise(ArgumentError, '[ruby-dev:34123]') { [1,2].take(-1) } - assert_equal_instance([1,2], @cls[1,2].take(1000000000), '[ruby-dev:34123]') + assert_equal([1,2], [1,2].take(1000000000), '[ruby-dev:34123]') end def test_take_while - assert_equal_instance([1,2], @cls[1,2,3,4,5,0].take_while {|i| i < 3 }) + assert_equal([1,2], [1,2,3,4,5,0].take_while {|i| i < 3 }) end def test_drop - assert_equal_instance([4,5,0], @cls[1,2,3,4,5,0].drop(3)) + assert_equal([4,5,0], [1,2,3,4,5,0].drop(3)) assert_raise(ArgumentError, '[ruby-dev:34123]') { [1,2].drop(-1) } - assert_equal_instance([], @cls[1,2].drop(1000000000), '[ruby-dev:34123]') + assert_equal([], [1,2].drop(1000000000), '[ruby-dev:34123]') end def test_drop_while - assert_equal_instance([3,4,5,0], @cls[1,2,3,4,5,0].drop_while {|i| i < 3 }) + assert_equal([3,4,5,0], [1,2,3,4,5,0].drop_while {|i| i < 3 }) end LONGP = [127, 63, 31, 15, 7].map {|x| 2**x-1 }.find do |x| @@ -2402,13 +2185,13 @@ class TestArray < Test::Unit::TestCase def test_initialize assert_nothing_raised { [].instance_eval { initialize } } - assert_warning(/given block not used/) { Array.new { } } + assert_nothing_raised { Array.new { } } assert_equal([1, 2, 3], Array.new([1, 2, 3])) assert_raise(ArgumentError) { Array.new(-1, 1) } assert_raise(ArgumentError) { Array.new(LONGP, 1) } assert_equal([1, 1, 1], Array.new(3, 1)) assert_equal([1, 1, 1], Array.new(3) { 1 }) - assert_equal([1, 1, 1], assert_warning(/block supersedes default value argument/) {Array.new(3, 1) { 1 }}) + assert_equal([1, 1, 1], Array.new(3, 1) { 1 }) end def test_aset_error @@ -2416,7 +2199,6 @@ class TestArray < Test::Unit::TestCase assert_raise(IndexError) { [0][LONGP] = 2 } assert_raise(IndexError) { [0][(LONGP + 1) / 2 - 1] = 2 } assert_raise(IndexError) { [0][LONGP..-1] = 2 } - assert_raise(IndexError) { [0][LONGP..] = 2 } a = [0] a[2] = 4 assert_equal([0, nil, 4], a) @@ -2424,9 +2206,6 @@ class TestArray < Test::Unit::TestCase assert_raise(ArgumentError) { [0].freeze[0, 0, 0] = 0 } assert_raise(TypeError) { [0][:foo] = 0 } assert_raise(FrozenError) { [0].freeze[:foo] = 0 } - - # [Bug #17271] - assert_raise_with_message(RangeError, "-7.. out of range") { [*0..5][-7..] = 1 } end def test_first2 @@ -2457,11 +2236,10 @@ class TestArray < Test::Unit::TestCase def test_aref assert_raise(ArgumentError) { [][0, 0, 0] } - assert_raise(ArgumentError) { @cls[][0, 0, 0] } end def test_fetch - assert_equal(1, assert_warning(/block supersedes default value argument/) {[].fetch(0, 0) { 1 }}) + assert_equal(1, [].fetch(0, 0) { 1 }) assert_equal(1, [0, 1].fetch(-1)) assert_raise(IndexError) { [0, 1].fetch(2) } assert_raise(IndexError) { [0, 1].fetch(-3) } @@ -2530,27 +2308,6 @@ class TestArray < Test::Unit::TestCase assert_equal("12345", [1,[2,[3,4],5]].join) end - def test_join_recheck_elements_type - x = Struct.new(:ary).new - def x.to_str - ary[2] = [0, 1, 2] - "z" - end - (x.ary = ["a", "b", "c", x]) - assert_equal("ab012z", x.ary.join("")) - end - - def test_join_recheck_array_length - x = Struct.new(:ary).new - def x.to_str - ary.clear - ary[0] = "b" - "z" - end - x.ary = Array.new(1023) {"a"*1} << x - assert_equal("b", x.ary.join("")) - end - def test_to_a2 klass = Class.new(Array) a = klass.new.to_a @@ -2616,25 +2373,6 @@ class TestArray < Test::Unit::TestCase assert_equal(@cls[4, 5], a) end - def test_filter - assert_equal([0, 2], [0, 1, 2, 3].filter {|x| x % 2 == 0 }) - end - - # alias for select! - def test_filter! - a = @cls[ 1, 2, 3, 4, 5 ] - assert_equal(nil, a.filter! { true }) - assert_equal(@cls[1, 2, 3, 4, 5], a) - - a = @cls[ 1, 2, 3, 4, 5 ] - assert_equal(a, a.filter! { false }) - assert_equal(@cls[], a) - - a = @cls[ 1, 2, 3, 4, 5 ] - assert_equal(a, a.filter! { |i| i > 3 }) - assert_equal(@cls[4, 5], a) - end - def test_delete2 a = [0] * 1024 + [1] + [0] * 1024 a.delete(0) @@ -2679,7 +2417,7 @@ class TestArray < Test::Unit::TestCase def test_zip_bug bug8153 = "ruby-core:53650" - r = [1] + r = 1..1 def r.respond_to?(*) super end @@ -2712,21 +2450,25 @@ class TestArray < Test::Unit::TestCase assert_not_equal([0, 1, 2], [0, 1, 3]) end + A = Array.new(3, &:to_s) + B = A.dup + def test_equal_resize - $test_equal_resize_a = Array.new(3, &:to_s) - $test_equal_resize_b = $test_equal_resize_a.dup o = Object.new def o.==(o) - $test_equal_resize_a.clear - $test_equal_resize_b.clear + A.clear + B.clear true end - $test_equal_resize_a[1] = o - assert_equal($test_equal_resize_a, $test_equal_resize_b) + A[1] = o + assert_equal(A, B) end def test_flatten_error a = [] + a << a + assert_raise(ArgumentError) { a.flatten } + f = [].freeze assert_raise(ArgumentError) { a.flatten!(1, 2) } assert_raise(TypeError) { a.flatten!(:foo) } @@ -2961,6 +2703,22 @@ class TestArray < Test::Unit::TestCase end end + class Array2 < Array + end + + def test_array_subclass + assert_equal(Array2, Array2[1,2,3].uniq.class, "[ruby-dev:34581]") + assert_equal(Array2, Array2[1,2][0,1].class) # embedded + assert_equal(Array2, Array2[*(1..100)][1..99].class) #not embedded + end + + def test_inspect + a = @cls[1, 2, 3] + a.taint + s = a.inspect + assert_equal(true, s.tainted?) + end + def test_initialize2 a = [1] * 1000 a.instance_eval { initialize } @@ -3164,7 +2922,7 @@ class TestArray < Test::Unit::TestCase Bug11235 = '[ruby-dev:49043] [Bug #11235]' def test_push_over_ary_max - assert_separately(['-', ARY_MAX.to_s, Bug11235], "#{<<~"begin;"}\n#{<<~'end;'}", timeout: 120) + assert_separately(['-', ARY_MAX.to_s, Bug11235], "#{<<~"begin;"}\n#{<<~'end;'}", timeout: 30) begin; a = Array.new(ARGV[0].to_i) assert_raise(IndexError, ARGV[1]) {0x1000.times {a.push(1)}} @@ -3285,14 +3043,6 @@ class TestArray < Test::Unit::TestCase assert_raise(TypeError) {[1].sum("")} end - def test_big_array_literal_with_kwsplat - lit = "[" - 10000.times { lit << "{}," } - lit << "**{}]" - - assert_equal(10000, eval(lit).size) - end - private def need_continuation unless respond_to?(:callcc, true) @@ -3300,23 +3050,3 @@ class TestArray < Test::Unit::TestCase end end end - -class TestArraySubclass < TestArray - def setup - @verbose = $VERBOSE - @cls = Class.new(Array) - end - - def test_to_a - a = @cls[ 1, 2, 3 ] - a_id = a.__id__ - assert_equal_instance([1, 2, 3], a.to_a) - assert_not_equal(a_id, a.to_a.__id__) - end - - def test_array_subclass - assert_equal(Array, @cls[1,2,3].uniq.class, "[ruby-dev:34581]") - assert_equal(Array, @cls[1,2][0,1].class) # embedded - assert_equal(Array, @cls[*(1..100)][1..99].class) #not embedded - end -end diff --git a/test/ruby/test_assignment.rb b/test/ruby/test_assignment.rb index 5a6ec97e67..45c4d6e058 100644 --- a/test/ruby/test_assignment.rb +++ b/test/ruby/test_assignment.rb @@ -92,11 +92,6 @@ class TestAssignment < Test::Unit::TestCase a,b,*c = *[*[1,2]]; assert_equal([1,2,[]], [a,b,c]) end - def test_assign_rescue - a = raise rescue 2; assert_equal(2, a) - a, b = raise rescue [3,4]; assert_equal([3, 4], [a, b]) - end - def test_assign_abbreviated bug2050 = '[ruby-core:25629]' a = Hash.new {[]} @@ -119,32 +114,32 @@ class TestAssignment < Test::Unit::TestCase def []=(i, a); 42; end end - assert_raise(NoMethodError, bug11096) { + assert_raise(NoMethodError) { o.instance_eval {o.foo = 1} } - assert_nothing_raised(NoMethodError, bug11096) { + assert_nothing_raised(NoMethodError) { assert_equal(1, o.instance_eval {self.foo = 1}) } - assert_raise(NoMethodError, bug11096) { + assert_raise(NoMethodError) { o.instance_eval {o[0] = 1} } - assert_nothing_raised(NoMethodError, bug11096) { + assert_nothing_raised(NoMethodError) { assert_equal(1, o.instance_eval {self[0] = 1}) } - assert_nothing_raised(NoMethodError, bug11096) { - o.instance_eval {self.foo += 1} + assert_raise(NoMethodError, bug11096) { + assert_equal(43, o.instance_eval {self.foo += 1}) } - assert_nothing_raised(NoMethodError, bug11096) { - o.instance_eval {self.foo &&= 1} + assert_raise(NoMethodError, bug11096) { + assert_equal(1, o.instance_eval {self.foo &&= 1}) } - assert_nothing_raised(NoMethodError, bug11096) { - o.instance_eval {self[0] += 1} + assert_raise(NoMethodError, bug11096) { + assert_equal(43, o.instance_eval {self[0] += 1}) } - assert_nothing_raised(NoMethodError, bug11096) { - o.instance_eval {self[0] &&= 1} + assert_raise(NoMethodError, bug11096) { + assert_equal(1, o.instance_eval {self[0] &&= 1}) } end @@ -456,7 +451,7 @@ class TestAssignment < Test::Unit::TestCase assert(defined?(a)) assert_nil(a) - # multiple assignment + # multiple asignment a, b = 1, 2 assert_equal 1, a assert_equal 2, b @@ -485,10 +480,11 @@ class TestAssignment < Test::Unit::TestCase assert_equal 1, a assert_equal [2, 3], b - a, *b, c = 1, 2, 3, 4 - assert_equal 1, a - assert_equal [2,3], b - assert_equal 4, c + # not supported yet + #a, *b, c = 1, 2, 3, 4 + #assert_equal 1, a + #assert_equal [2,3], b + #assert_equal 4, c a = 1, 2 assert_equal [1, 2], a diff --git a/test/ruby/test_ast.rb b/test/ruby/test_ast.rb deleted file mode 100644 index 0d846b76e4..0000000000 --- a/test/ruby/test_ast.rb +++ /dev/null @@ -1,348 +0,0 @@ -# frozen_string_literal: false -require 'test/unit' -require 'tempfile' - -class RubyVM - module AbstractSyntaxTree - class Node - class CodePosition - include Comparable - attr_reader :lineno, :column - def initialize(lineno, column) - @lineno = lineno - @column = column - end - - def <=>(other) - case - when lineno < other.lineno - -1 - when lineno == other.lineno - column <=> other.column - when lineno > other.lineno - 1 - end - end - end - - def beg_pos - CodePosition.new(first_lineno, first_column) - end - - def end_pos - CodePosition.new(last_lineno, last_column) - end - - alias to_s inspect - end - end -end - -class TestAst < Test::Unit::TestCase - class Helper - attr_reader :errors - - def initialize(path, src: nil) - @path = path - @errors = [] - @debug = false - @ast = RubyVM::AbstractSyntaxTree.parse(src) if src - end - - def validate_range - @errors = [] - validate_range0(ast) - - @errors.empty? - end - - def validate_not_cared - @errors = [] - validate_not_cared0(ast) - - @errors.empty? - end - - def ast - return @ast if defined?(@ast) - @ast = RubyVM::AbstractSyntaxTree.parse_file(@path) - end - - private - - def validate_range0(node) - beg_pos, end_pos = node.beg_pos, node.end_pos - children = node.children.grep(RubyVM::AbstractSyntaxTree::Node) - - return true if children.empty? - # These NODE_D* has NODE_LIST as nd_next->nd_next whose last locations - # we can not update when item is appended. - return true if [:DSTR, :DXSTR, :DREGX, :DSYM].include? node.type - - min = children.map(&:beg_pos).min - max = children.map(&:end_pos).max - - unless beg_pos <= min - @errors << { type: :min_validation_error, min: min, beg_pos: beg_pos, node: node } - end - - unless max <= end_pos - @errors << { type: :max_validation_error, max: max, end_pos: end_pos, node: node } - end - - p "#{node} => #{children}" if @debug - - children.each do |child| - p child if @debug - validate_range0(child) - end - end - - def validate_not_cared0(node) - beg_pos, end_pos = node.beg_pos, node.end_pos - children = node.children.grep(RubyVM::AbstractSyntaxTree::Node) - - @errors << { type: :first_lineno, node: node } if beg_pos.lineno == 0 - @errors << { type: :first_column, node: node } if beg_pos.column == -1 - @errors << { type: :last_lineno, node: node } if end_pos.lineno == 0 - @errors << { type: :last_column, node: node } if end_pos.column == -1 - - children.each {|c| validate_not_cared0(c) } - end - end - - 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 - 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 - end - - private def parse(src) - EnvUtil.suppress_warning { - RubyVM::AbstractSyntaxTree.parse(src) - } - end - - def test_allocate - assert_raise(TypeError) {RubyVM::AbstractSyntaxTree::Node.allocate} - end - - def test_parse_argument_error - assert_raise(TypeError) {RubyVM::AbstractSyntaxTree.parse(0)} - assert_raise(TypeError) {RubyVM::AbstractSyntaxTree.parse(nil)} - assert_raise(TypeError) {RubyVM::AbstractSyntaxTree.parse(false)} - assert_raise(TypeError) {RubyVM::AbstractSyntaxTree.parse(true)} - assert_raise(TypeError) {RubyVM::AbstractSyntaxTree.parse(:foo)} - end - - def test_column_with_long_heredoc_identifier - term = "A"*257 - ast = parse("<<-#{term}\n""ddddddd\n#{term}\n") - node = ast.children[2] - assert_equal(:STR, node.type) - assert_equal(0, node.first_column) - end - - def test_column_of_heredoc - node = parse("<<-SRC\nddddddd\nSRC\n").children[2] - assert_equal(:STR, node.type) - assert_equal(0, node.first_column) - assert_equal(6, node.last_column) - - node = parse("<<SRC\nddddddd\nSRC\n").children[2] - assert_equal(:STR, node.type) - assert_equal(0, node.first_column) - assert_equal(5, node.last_column) - end - - def test_parse_raises_syntax_error - assert_raise_with_message(SyntaxError, /\bend\b/) do - RubyVM::AbstractSyntaxTree.parse("end") - end - end - - def test_parse_file_raises_syntax_error - Tempfile.create(%w"test_ast .rb") do |f| - f.puts "end" - f.close - assert_raise_with_message(SyntaxError, /\bend\b/) do - RubyVM::AbstractSyntaxTree.parse_file(f.path) - end - end - end - - def test_of - proc = Proc.new { 1 + 2 } - method = self.method(__method__) - - node_proc = RubyVM::AbstractSyntaxTree.of(proc) - node_method = RubyVM::AbstractSyntaxTree.of(method) - - assert_instance_of(RubyVM::AbstractSyntaxTree::Node, node_proc) - assert_instance_of(RubyVM::AbstractSyntaxTree::Node, node_method) - assert_raise(TypeError) { RubyVM::AbstractSyntaxTree.of("1 + 2") } - - Tempfile.create(%w"test_of .rb") do |tmp| - tmp.print "#{<<-"begin;"}\n#{<<-'end;'}" - begin; - SCRIPT_LINES__ = {} - assert_instance_of(RubyVM::AbstractSyntaxTree::Node, RubyVM::AbstractSyntaxTree.of(proc {|x| x})) - end; - tmp.close - assert_separately(["-", tmp.path], "#{<<~"begin;"}\n#{<<~'end;'}") - begin; - load ARGV[0] - assert_empty(SCRIPT_LINES__) - end; - end - end - - def test_scope_local_variables - node = RubyVM::AbstractSyntaxTree.parse("_x = 0") - lv, _, body = *node.children - assert_equal([:_x], lv) - assert_equal(:LASGN, body.type) - end - - def test_call - node = RubyVM::AbstractSyntaxTree.parse("nil.foo") - _, _, body = *node.children - assert_equal(:CALL, body.type) - recv, mid, args = body.children - assert_equal(:NIL, recv.type) - assert_equal(:foo, mid) - assert_nil(args) - end - - def test_fcall - node = RubyVM::AbstractSyntaxTree.parse("foo()") - _, _, body = *node.children - assert_equal(:FCALL, body.type) - mid, args = body.children - assert_equal(:foo, mid) - assert_nil(args) - end - - def test_vcall - node = RubyVM::AbstractSyntaxTree.parse("foo") - _, _, body = *node.children - assert_equal(:VCALL, body.type) - mid, args = body.children - assert_equal(:foo, mid) - assert_nil(args) - end - - def test_defn - node = RubyVM::AbstractSyntaxTree.parse("def a; end") - _, _, body = *node.children - assert_equal(:DEFN, body.type) - mid, defn = body.children - assert_equal(:a, mid) - assert_equal(:SCOPE, defn.type) - end - - def test_defs - node = RubyVM::AbstractSyntaxTree.parse("def a.b; end") - _, _, body = *node.children - assert_equal(:DEFS, body.type) - recv, mid, defn = body.children - assert_equal(:VCALL, recv.type) - assert_equal(:b, mid) - assert_equal(:SCOPE, defn.type) - end - - def test_dstr - node = parse('"foo#{1}bar"') - _, _, body = *node.children - assert_equal(:DSTR, body.type) - head, body = body.children - assert_equal("foo", head) - assert_equal(:EVSTR, body.type) - body, = body.children - assert_equal(:LIT, body.type) - assert_equal([1], body.children) - end - - def test_while - node = RubyVM::AbstractSyntaxTree.parse('1 while qux') - _, _, body = *node.children - assert_equal(:WHILE, body.type) - type1 = body.children[2] - node = RubyVM::AbstractSyntaxTree.parse('begin 1 end while qux') - _, _, body = *node.children - assert_equal(:WHILE, body.type) - type2 = body.children[2] - assert_not_equal(type1, type2) - end - - def test_until - node = RubyVM::AbstractSyntaxTree.parse('1 until qux') - _, _, body = *node.children - assert_equal(:UNTIL, body.type) - type1 = body.children[2] - node = RubyVM::AbstractSyntaxTree.parse('begin 1 end until qux') - _, _, body = *node.children - assert_equal(:UNTIL, body.type) - type2 = body.children[2] - assert_not_equal(type1, type2) - end - - def test_keyword_rest - kwrest = lambda do |arg_str| - node = RubyVM::AbstractSyntaxTree.parse("def a(#{arg_str}) end") - node = node.children.last.children.last.children[1].children[-2] - node ? node.children : node - end - - assert_equal(nil, kwrest.call('')) - assert_equal([nil], kwrest.call('**')) - assert_equal(false, kwrest.call('**nil')) - assert_equal([:a], kwrest.call('**a')) - end - - def test_ranges_numbered_parameter - helper = Helper.new(__FILE__, src: "1.times {_1}") - helper.validate_range - assert_equal([], helper.errors) - end - - def test_op_asgn2 - node = RubyVM::AbstractSyntaxTree.parse("struct.field += foo") - _, _, body = *node.children - assert_equal(:OP_ASGN2, body.type) - recv, _, mid, op, value = body.children - assert_equal(:VCALL, recv.type) - assert_equal(:field, mid) - assert_equal(:+, op) - assert_equal(:VCALL, value.type) - end - - def test_args - rest = 6 - node = RubyVM::AbstractSyntaxTree.parse("proc { |a| }") - _, args = *node.children.last.children[1].children - assert_equal(nil, args.children[rest]) - - node = RubyVM::AbstractSyntaxTree.parse("proc { |a,| }") - _, args = *node.children.last.children[1].children - assert_equal(:NODE_SPECIAL_EXCESSIVE_COMMA, args.children[rest]) - - node = RubyVM::AbstractSyntaxTree.parse("proc { |*a| }") - _, args = *node.children.last.children[1].children - assert_equal(:a, args.children[rest]) - end -end diff --git a/test/ruby/test_autoload.rb b/test/ruby/test_autoload.rb index 98d513da87..3095052a81 100644 --- a/test/ruby/test_autoload.rb +++ b/test/ruby/test_autoload.rb @@ -42,10 +42,8 @@ p Foo::Bar require 'tmpdir' Dir.mktmpdir('autoload') {|tmpdir| tmpfile = tmpdir + '/foo.rb' - tmpfile2 = tmpdir + '/bar.rb' a = Module.new do autoload :X, tmpfile - autoload :Y, tmpfile2 end b = Module.new do include a @@ -54,20 +52,10 @@ p Foo::Bar assert_equal(true, b.const_defined?(:X)) assert_equal(tmpfile, a.autoload?(:X), bug4565) assert_equal(tmpfile, b.autoload?(:X), bug4565) - assert_equal(tmpfile, a.autoload?(:X, false)) - assert_equal(tmpfile, a.autoload?(:X, nil)) - assert_nil(b.autoload?(:X, false)) - assert_nil(b.autoload?(:X, nil)) - assert_equal(true, a.const_defined?("Y")) - assert_equal(true, b.const_defined?("Y")) - assert_equal(tmpfile2, a.autoload?("Y")) - assert_equal(tmpfile2, b.autoload?("Y")) } end def test_autoload_with_unqualified_file_name # [ruby-core:69206] - Object.send(:remove_const, :A) if Object.const_defined?(:A) - lp = $LOAD_PATH.dup lf = $LOADED_FEATURES.dup @@ -78,12 +66,12 @@ p Foo::Bar eval <<-END class ::Object module A - autoload :C, 'test-ruby-core-69206' + autoload :C, 'b' end end END - File.write("test-ruby-core-69206.rb", 'module A; class C; end; end') + File.open('b.rb', 'w') {|file| file.puts 'module A; class C; end; end'} assert_kind_of Class, ::A::C end } @@ -259,7 +247,7 @@ p Foo::Bar def test_autoload_private_constant Dir.mktmpdir('autoload') do |tmpdir| - File.write(tmpdir+"/test-bug-14469.rb", "#{<<~"begin;"}\n#{<<~'end;'}") + File.write(tmpdir+"/zzz.rb", "#{<<~"begin;"}\n#{<<~'end;'}") begin; class AutoloadTest ZZZ = :ZZZ @@ -270,7 +258,7 @@ p Foo::Bar bug = '[ruby-core:85516] [Bug #14469]' begin; class AutoloadTest - autoload :ZZZ, "test-bug-14469.rb" + autoload :ZZZ, "zzz.rb" end assert_raise(NameError, bug) {AutoloadTest::ZZZ} end; @@ -279,7 +267,7 @@ p Foo::Bar def test_autoload_deprecate_constant Dir.mktmpdir('autoload') do |tmpdir| - File.write(tmpdir+"/test-bug-14469.rb", "#{<<~"begin;"}\n#{<<~'end;'}") + File.write(tmpdir+"/zzz.rb", "#{<<~"begin;"}\n#{<<~'end;'}") begin; class AutoloadTest ZZZ = :ZZZ @@ -290,67 +278,7 @@ p Foo::Bar bug = '[ruby-core:85516] [Bug #14469]' begin; class AutoloadTest - autoload :ZZZ, "test-bug-14469.rb" - end - assert_warning(/ZZZ is deprecated/, bug) {AutoloadTest::ZZZ} - end; - end - end - - def test_autoload_private_constant_before_autoload - Dir.mktmpdir('autoload') do |tmpdir| - File.write(tmpdir+"/test-bug-11055.rb", "#{<<~"begin;"}\n#{<<~'end;'}") - begin; - class AutoloadTest - ZZZ = :ZZZ - end - end; - assert_separately(%W[-I #{tmpdir}], "#{<<-"begin;"}\n#{<<-'end;'}") - bug = '[Bug #11055]' - begin; - class AutoloadTest - autoload :ZZZ, "test-bug-11055.rb" - private_constant :ZZZ - ZZZ - end - assert_raise(NameError, bug) {AutoloadTest::ZZZ} - end; - assert_separately(%W[-I #{tmpdir}], "#{<<-"begin;"}\n#{<<-'end;'}") - bug = '[Bug #11055]' - begin; - class AutoloadTest - autoload :ZZZ, "test-bug-11055.rb" - private_constant :ZZZ - end - assert_raise(NameError, bug) {AutoloadTest::ZZZ} - end; - end - end - - def test_autoload_deprecate_constant_before_autoload - Dir.mktmpdir('autoload') do |tmpdir| - File.write(tmpdir+"/test-bug-11055.rb", "#{<<~"begin;"}\n#{<<~'end;'}") - begin; - class AutoloadTest - ZZZ = :ZZZ - end - end; - assert_separately(%W[-I #{tmpdir}], "#{<<-"begin;"}\n#{<<-'end;'}") - bug = '[Bug #11055]' - begin; - class AutoloadTest - autoload :ZZZ, "test-bug-11055.rb" - deprecate_constant :ZZZ - end - assert_warning(/ZZZ is deprecated/, bug) {class AutoloadTest; ZZZ; end} - assert_warning(/ZZZ is deprecated/, bug) {AutoloadTest::ZZZ} - end; - assert_separately(%W[-I #{tmpdir}], "#{<<-"begin;"}\n#{<<-'end;'}") - bug = '[Bug #11055]' - begin; - class AutoloadTest - autoload :ZZZ, "test-bug-11055.rb" - deprecate_constant :ZZZ + autoload :ZZZ, "zzz.rb" end assert_warning(/ZZZ is deprecated/, bug) {AutoloadTest::ZZZ} end; @@ -366,7 +294,7 @@ p Foo::Bar begin thrs = [] 3.times do - thrs << Thread.new { AutoloadTest && nil } + thrs << Thread.new { AutoloadTest; nil } thrs << Thread.new { fork { AutoloadTest } } end thrs.each(&:join) @@ -383,79 +311,6 @@ p Foo::Bar end end if Process.respond_to?(:fork) - def test_autoload_same_file - Dir.mktmpdir('autoload') do |tmpdir| - File.write("#{tmpdir}/test-bug-14742.rb", "#{<<~'begin;'}\n#{<<~'end;'}") - begin; - module Foo; end - module Bar; end - end; - 3.times do # timing-dependent, needs a few times to hit [Bug #14742] - assert_separately(%W[-I #{tmpdir}], "#{<<-'begin;'}\n#{<<-'end;'}") - begin; - autoload :Foo, 'test-bug-14742' - autoload :Bar, 'test-bug-14742' - t1 = Thread.new do Foo end - t2 = Thread.new do Bar end - t1.join - t2.join - bug = '[ruby-core:86935] [Bug #14742]' - assert_instance_of Module, t1.value, bug - assert_instance_of Module, t2.value, bug - end; - end - end - end - - def test_autoload_same_file_with_raise - Dir.mktmpdir('autoload') do |tmpdir| - File.write("#{tmpdir}/test-bug-16177.rb", "#{<<~'begin;'}\n#{<<~'end;'}") - begin; - raise '[ruby-core:95055] [Bug #16177]' - end; - assert_raise(RuntimeError, '[ruby-core:95055] [Bug #16177]') do - assert_separately(%W[-I #{tmpdir}], "#{<<-'begin;'}\n#{<<-'end;'}") - begin; - autoload :Foo, 'test-bug-16177' - autoload :Bar, 'test-bug-16177' - t1 = Thread.new do Foo end - t2 = Thread.new do Bar end - t1.join - t2.join - end; - end - end - end - - def test_source_location - bug = "Bug16764" - Dir.mktmpdir('autoload') do |tmpdir| - path = "#{tmpdir}/test-#{bug}.rb" - File.write(path, "C::#{bug} = __FILE__\n") - assert_separately(%W[-I #{tmpdir}], "#{<<-"begin;"}\n#{<<-"end;"}") - begin; - class C; end - C.autoload(:Bug16764, #{path.dump}) - assert_equal [__FILE__, __LINE__-1], C.const_source_location(#{bug.dump}) - assert_equal #{path.dump}, C.const_get(#{bug.dump}) - assert_equal [#{path.dump}, 1], C.const_source_location(#{bug.dump}) - end; - end - end - - def test_no_memory_leak - assert_no_memory_leak([], '', "#{<<~"begin;"}\n#{<<~'end;'}", 'many autoloads', timeout: 60) - begin; - 200000.times do |i| - m = Module.new - m.instance_eval do - autoload :Foo, 'x' - autoload :Bar, i.to_s - end - end - end; - end - def add_autoload(path) (@autoload_paths ||= []) << path ::Object.class_eval {autoload(:AutoloadTest, path)} @@ -464,6 +319,5 @@ p Foo::Bar def remove_autoload_constant $".replace($" - @autoload_paths) ::Object.class_eval {remove_const(:AutoloadTest)} - TestAutoload.class_eval {remove_const(:AutoloadTest)} if defined? TestAutoload::AutoloadTest end end diff --git a/test/ruby/test_backtrace.rb b/test/ruby/test_backtrace.rb index 00c96b3b9f..d38628cdb2 100644 --- a/test/ruby/test_backtrace.rb +++ b/test/ruby/test_backtrace.rb @@ -297,50 +297,4 @@ class TestBacktrace < Test::Unit::TestCase end assert_not_match(/\Acore#/, e.backtrace_locations[0].base_label) end - - def test_notty_backtrace - err = ["-:1:in `<main>': unhandled exception"] - assert_in_out_err([], "raise", [], err) - - err = ["-:2:in `foo': foo! (RuntimeError)", - "\tfrom -:4:in `<main>'"] - assert_in_out_err([], <<-"end;", [], err) - def foo - raise "foo!" - end - foo - end; - - err = ["-:7:in `rescue in bar': bar! (RuntimeError)", - "\tfrom -:4:in `bar'", - "\tfrom -:9:in `<main>'", - "-:2:in `foo': foo! (RuntimeError)", - "\tfrom -:5:in `bar'", - "\tfrom -:9:in `<main>'"] - assert_in_out_err([], <<-"end;", [], err) - def foo - raise "foo!" - end - def bar - foo - rescue - raise "bar!" - end - bar - end; - end - - def test_caller_to_enum - err = ["-:3:in `foo': unhandled exception", "\tfrom -:in `each'"] - assert_in_out_err([], <<-"end;", [], err, "[ruby-core:91911]") - def foo - return to_enum(__method__) unless block_given? - raise - yield 1 - end - - enum = foo - enum.next - end; - end end diff --git a/test/ruby/test_basicinstructions.rb b/test/ruby/test_basicinstructions.rb index f6b69cc1e5..dd3ca4dd22 100644 --- a/test/ruby/test_basicinstructions.rb +++ b/test/ruby/test_basicinstructions.rb @@ -117,6 +117,7 @@ class TestBasicInstructions < Test::Unit::TestCase assert_equal({1=>2}, {1=>2}) assert_equal({1=>2, 3=>4}, {1=>2, 3=>4}) assert_equal({1=>2, 3=>4}, {3=>4, 1=>2}) + # assert_equal({1=>2, 3=>4}, {1,2, 3,4}) # 1.9 doesn't support assert_equal({"key"=>"val"}, {"key"=>"val"}) end @@ -428,9 +429,7 @@ class TestBasicInstructions < Test::Unit::TestCase end class CVarA - def self.setup - @@cv = 'CVarA@@cv' - end + @@cv = 'CVarA@@cv' def self.cv() @@cv end def self.cv=(v) @@cv = v end class << self @@ -451,7 +450,6 @@ class TestBasicInstructions < Test::Unit::TestCase end def test_class_variable - CVarA.setup assert_equal 'CVarA@@cv', CVarA.cv assert_equal 'CVarA@@cv', CVarA.cv2 assert_equal 'CVarA@@cv', CVarA.new.cv diff --git a/test/ruby/test_bignum.rb b/test/ruby/test_bignum.rb index a240c8e8af..65d974005e 100644 --- a/test/ruby/test_bignum.rb +++ b/test/ruby/test_bignum.rb @@ -10,6 +10,7 @@ class TestBignum < Test::Unit::TestCase FIXNUM_MAX = RbConfig::LIMITS['FIXNUM_MAX'] BIGNUM_MIN = FIXNUM_MAX + 1 + b = BIGNUM_MIN f = BIGNUM_MIN n = 0 @@ -35,6 +36,7 @@ class TestBignum < Test::Unit::TestCase def setup @verbose = $VERBOSE + $VERBOSE = nil @fmax = Float::MAX.to_i @fmax2 = @fmax * 2 @big = (1 << BIGNUM_MIN_BITS) - 1 @@ -213,11 +215,9 @@ class TestBignum < Test::Unit::TestCase def test_to_f assert_nothing_raised { T31P.to_f.to_i } - assert_raise(FloatDomainError) { - assert_warning(/out of Float range/) {(1024**1024).to_f}.to_i - } - assert_equal(1, assert_warning(/out of Float range/) {(2**50000).to_f}.infinite?) - assert_equal(-1, assert_warning(/out of Float range/) {(-(2**50000)).to_f}.infinite?) + assert_raise(FloatDomainError) { (1024**1024).to_f.to_i } + assert_equal(1, (2**50000).to_f.infinite?) + assert_equal(-1, (-(2**50000)).to_f.infinite?) end def test_cmp @@ -416,7 +416,7 @@ class TestBignum < Test::Unit::TestCase def test_divide bug5490 = '[ruby-core:40429]' assert_raise(ZeroDivisionError, bug5490) {T1024./(0)} - assert_equal(Float::INFINITY, assert_warning(/out of Float range/) {T1024./(0.0)}, bug5490) + assert_equal(Float::INFINITY, T1024./(0.0), bug5490) end def test_div @@ -467,8 +467,8 @@ class TestBignum < Test::Unit::TestCase def test_pow assert_equal(1.0, T32 ** 0.0) assert_equal(1.0 / T32, T32 ** -1) - assert_equal(1, assert_warning(/may be too big/) {T32 ** T32}.infinite?) - assert_equal(1, assert_warning(/may be too big/) {T32 ** (2**30-1)}.infinite?) + assert_equal(1, (T32 ** T32).infinite?) + assert_equal(1, (T32 ** (2**30-1)).infinite?) ### rational changes the behavior of Bignum#** #assert_raise(TypeError) { T32**"foo" } @@ -506,57 +506,39 @@ class TestBignum < Test::Unit::TestCase end def test_and_with_float - assert_raise(TypeError) { - assert_warning(/out of Float range/) {T1024 & 1.5} - } + assert_raise(TypeError) { T1024 & 1.5 } end def test_and_with_rational - assert_raise(TypeError, "#1792") { - assert_warn(/out of Float range/) {T1024 & Rational(3, 2)} - } + assert_raise(TypeError, "#1792") { T1024 & Rational(3, 2) } end def test_and_with_nonintegral_numeric - assert_raise(TypeError, "#1792") { - assert_warn(/out of Float range/) {T1024 & DummyNumeric.new} - } + assert_raise(TypeError, "#1792") { T1024 & DummyNumeric.new } end def test_or_with_float - assert_raise(TypeError) { - assert_warn(/out of Float range/) {T1024 | 1.5} - } + assert_raise(TypeError) { T1024 | 1.5 } end def test_or_with_rational - assert_raise(TypeError, "#1792") { - assert_warn(/out of Float range/) {T1024 | Rational(3, 2)} - } + assert_raise(TypeError, "#1792") { T1024 | Rational(3, 2) } end def test_or_with_nonintegral_numeric - assert_raise(TypeError, "#1792") { - assert_warn(/out of Float range/) {T1024 | DummyNumeric.new} - } + assert_raise(TypeError, "#1792") { T1024 | DummyNumeric.new } end def test_xor_with_float - assert_raise(TypeError) { - assert_warn(/out of Float range/) {T1024 ^ 1.5} - } + assert_raise(TypeError) { T1024 ^ 1.5 } end def test_xor_with_rational - assert_raise(TypeError, "#1792") { - assert_warn(/out of Float range/) {T1024 ^ Rational(3, 2)} - } + assert_raise(TypeError, "#1792") { T1024 ^ Rational(3, 2) } end def test_xor_with_nonintegral_numeric - assert_raise(TypeError, "#1792") { - assert_warn(/out of Float range/) {T1024 ^ DummyNumeric.new} - } + assert_raise(TypeError, "#1792") { T1024 ^ DummyNumeric.new } end def test_shift2 @@ -630,17 +612,17 @@ class TestBignum < Test::Unit::TestCase return # GMP doesn't support interrupt during an operation. end time = Time.now + start_flag = false end_flag = false num = (65536 ** 65536) - q = Queue.new thread = Thread.new do + start_flag = true assert_raise(RuntimeError) { - q << true num.to_s end_flag = true } end - q.pop # sync + sleep 0.001 until start_flag thread.raise thread.join time = Time.now - time diff --git a/test/ruby/test_call.rb b/test/ruby/test_call.rb index 67b3a936d4..2a1b671cac 100644 --- a/test/ruby/test_call.rb +++ b/test/ruby/test_call.rb @@ -99,13 +99,4 @@ class TestCall < Test::Unit::TestCase ary = [1, 2] assert_equal([0, 1, 2, 1], aaa(0, *ary, ary.shift), bug12860) end - - def test_call_block_order - bug16504 = '[ruby-core:96769] [Bug# 16504]' - b = proc{} - ary = [1, 2, b] - assert_equal([1, 2, b], aaa(*ary, &ary.pop), bug16504) - ary = [1, 2, b] - assert_equal([0, 1, 2, b], aaa(0, *ary, &ary.pop), bug16504) - end end diff --git a/test/ruby/test_class.rb b/test/ruby/test_class.rb index 6a8234a9d3..ad2caeb8be 100644 --- a/test/ruby/test_class.rb +++ b/test/ruby/test_class.rb @@ -131,48 +131,6 @@ class TestClass < Test::Unit::TestCase [:module_function, :extend_object, :append_features, :prepend_features]) end - def test_visibility_inside_method - assert_warn(/calling private without arguments inside a method may not have the intended effect/, '[ruby-core:79751]') do - Class.new do - def self.foo - private - end - foo - end - end - - assert_warn(/calling protected without arguments inside a method may not have the intended effect/, '[ruby-core:79751]') do - Class.new do - def self.foo - protected - end - foo - end - end - - assert_warn(/calling public without arguments inside a method may not have the intended effect/, '[ruby-core:79751]') do - Class.new do - def self.foo - public - end - foo - end - end - - assert_warn(/calling private without arguments inside a method may not have the intended effect/, '[ruby-core:79751]') do - Class.new do - class << self - alias priv private - end - - def self.foo - priv - end - foo - end - end - end - def test_method_redefinition feature2155 = '[ruby-dev:39400]' @@ -274,14 +232,6 @@ class TestClass < Test::Unit::TestCase assert_raise(TypeError) { Class.allocate.superclass } bug6863 = '[ruby-core:47148]' assert_raise(TypeError, bug6863) { Class.new(Class.allocate) } - - allocator = Class.instance_method(:allocate) - assert_raise_with_message(TypeError, /prohibited/) { - allocator.bind(Rational).call - } - assert_raise_with_message(TypeError, /prohibited/) { - allocator.bind_call(Rational) - } end def test_nonascii_name @@ -292,29 +242,27 @@ class TestClass < Test::Unit::TestCase end def test_invalid_next_from_class_definition - assert_syntax_error("class C; next; end", /Invalid next/) + assert_raise(SyntaxError) { eval("class C; next; end") } end def test_invalid_break_from_class_definition - assert_syntax_error("class C; break; end", /Invalid break/) + assert_raise(SyntaxError) { eval("class C; break; end") } end def test_invalid_redo_from_class_definition - assert_syntax_error("class C; redo; end", /Invalid redo/) + assert_raise(SyntaxError) { eval("class C; redo; end") } end def test_invalid_retry_from_class_definition - assert_syntax_error("class C; retry; end", /Invalid retry/) + assert_raise(SyntaxError) { eval("class C; retry; end") } end def test_invalid_return_from_class_definition - assert_syntax_error("class C; return; end", /Invalid return/) + assert_raise(SyntaxError) { eval("class C; return; end") } end def test_invalid_yield_from_class_definition - assert_raise(SyntaxError) { - EnvUtil.suppress_warning {eval("class C; yield; end")} - } + assert_raise(LocalJumpError) { eval("class C; yield; end") } end def test_clone @@ -379,22 +327,18 @@ class TestClass < Test::Unit::TestCase end; end - class CloneTest - def foo; TEST; end - end + module M + C = 1 - CloneTest1 = CloneTest.clone - CloneTest2 = CloneTest.clone - class CloneTest1 - TEST = :C1 - end - class CloneTest2 - TEST = :C2 + def self.m + C + end end - def test_constant_access_from_method_in_cloned_class - assert_equal :C1, CloneTest1.new.foo, '[Bug #15877]' - assert_equal :C2, CloneTest2.new.foo, '[Bug #15877]' + def test_constant_access_from_method_in_cloned_module # [ruby-core:47834] + m = M.dup + assert_equal 1, m::C + assert_equal 1, m.m end def test_invalid_superclass @@ -483,53 +427,6 @@ class TestClass < Test::Unit::TestCase assert_equal(:foo, d.foo) end - def test_clone_singleton_class_exists - klass = Class.new do - def self.bar; :bar; end - end - - o = klass.new - o.singleton_class - clone = o.clone - - assert_empty(o.singleton_class.instance_methods(false)) - assert_empty(clone.singleton_class.instance_methods(false)) - assert_empty(o.singleton_class.singleton_class.instance_methods(false)) - assert_empty(clone.singleton_class.singleton_class.instance_methods(false)) - end - - def test_clone_when_singleton_class_of_singleton_class_exists - klass = Class.new do - def self.bar; :bar; end - end - - o = klass.new - o.singleton_class.singleton_class - clone = o.clone - - assert_empty(o.singleton_class.instance_methods(false)) - assert_empty(clone.singleton_class.instance_methods(false)) - assert_empty(o.singleton_class.singleton_class.instance_methods(false)) - assert_empty(clone.singleton_class.singleton_class.instance_methods(false)) - end - - def test_clone_when_method_exists_on_singleton_class_of_singleton_class - klass = Class.new do - def self.bar; :bar; end - end - - o = klass.new - o.singleton_class.singleton_class.define_method(:s2_method) { :s2 } - clone = o.clone - - assert_empty(o.singleton_class.instance_methods(false)) - assert_empty(clone.singleton_class.instance_methods(false)) - assert_equal(:s2, o.singleton_class.s2_method) - assert_equal(:s2, clone.singleton_class.s2_method) - assert_equal([:s2_method], o.singleton_class.singleton_class.instance_methods(false)) - assert_equal([:s2_method], clone.singleton_class.singleton_class.instance_methods(false)) - end - def test_singleton_class_p feature7609 = '[ruby-core:51087] [Feature #7609]' assert_predicate(self.singleton_class, :singleton_class?, feature7609) @@ -688,17 +585,15 @@ class TestClass < Test::Unit::TestCase def test_redefinition_mismatch m = Module.new - m.module_eval "A = 1", __FILE__, line = __LINE__ - e = assert_raise_with_message(TypeError, /is not a class/) { + m.module_eval "A = 1" + assert_raise_with_message(TypeError, /is not a class/) { m.module_eval "class A; end" } - assert_include(e.message, "#{__FILE__}:#{line}: previous definition") n = "M\u{1f5ff}" - m.module_eval "#{n} = 42", __FILE__, line = __LINE__ - e = assert_raise_with_message(TypeError, /#{n} is not a class/) { + m.module_eval "#{n} = 42" + assert_raise_with_message(TypeError, "#{n} is not a class") { m.module_eval "class #{n}; end" } - assert_include(e.message, "#{__FILE__}:#{line}: previous definition") assert_separately([], "#{<<~"begin;"}\n#{<<~"end;"}") begin; diff --git a/test/ruby/test_clone.rb b/test/ruby/test_clone.rb index 321feb07c7..93ef438461 100644 --- a/test/ruby/test_clone.rb +++ b/test/ruby/test_clone.rb @@ -26,39 +26,4 @@ class TestClone < Test::Unit::TestCase assert_equal([M003, M002, M001], M003.ancestors) end - - def test_user_flags - assert_separately([], <<-EOS) - # - class Array - undef initialize_copy - def initialize_copy(*); end - end - x = [1, 2, 3].clone - assert_equal [], x, '[Bug #14847]' - EOS - - assert_separately([], <<-EOS) - # - class Array - undef initialize_copy - def initialize_copy(*); end - end - x = [1,2,3,4,5,6,7][1..-2].clone - x.push(1,1,1,1,1) - assert_equal [1, 1, 1, 1, 1], x, '[Bug #14847]' - EOS - - assert_separately([], <<-EOS) - # - class Hash - undef initialize_copy - def initialize_copy(*); end - end - h = {} - h.default_proc = proc { raise } - h = h.clone - assert_equal nil, h[:not_exist], '[Bug #14847]' - EOS - end end diff --git a/test/ruby/test_comparable.rb b/test/ruby/test_comparable.rb index b849217b7d..94c05d5f91 100644 --- a/test/ruby/test_comparable.rb +++ b/test/ruby/test_comparable.rb @@ -88,37 +88,7 @@ class TestComparable < Test::Unit::TestCase assert_raise_with_message(ArgumentError, 'min argument must be smaller than max argument') { @o.clamp(2, 1) } - end - - def test_clamp_with_range - cmp->(x) do 0 <=> x end - assert_equal(1, @o.clamp(1..2)) - assert_equal(-1, @o.clamp(-2..-1)) - assert_equal(@o, @o.clamp(-1..3)) - - assert_equal(1, @o.clamp(1..1)) - assert_equal(@o, @o.clamp(0..0)) - - assert_equal(1, @o.clamp(1..)) - assert_equal(1, @o.clamp(1...)) - assert_equal(@o, @o.clamp(0..)) - assert_equal(@o, @o.clamp(0...)) - assert_equal(@o, @o.clamp(..2)) - assert_equal(-1, @o.clamp(-2..-1)) - assert_equal(@o, @o.clamp(-2..0)) - assert_equal(@o, @o.clamp(-2..)) - assert_equal(@o, @o.clamp(-2...)) - - exc = [ArgumentError, 'cannot clamp with an exclusive range'] - assert_raise_with_message(*exc) {@o.clamp(1...2)} - assert_raise_with_message(*exc) {@o.clamp(0...2)} - assert_raise_with_message(*exc) {@o.clamp(-1...0)} - assert_raise_with_message(*exc) {@o.clamp(...2)} - - assert_raise_with_message(ArgumentError, 'min argument must be smaller than max argument') { - @o.clamp(2..1) - } - end + end def test_err assert_raise(ArgumentError) { 1.0 < nil } diff --git a/test/ruby/test_complex.rb b/test/ruby/test_complex.rb index a3a7546575..316e3e21ff 100644 --- a/test/ruby/test_complex.rb +++ b/test/ruby/test_complex.rb @@ -123,10 +123,6 @@ class Complex_Test < Test::Unit::TestCase assert_raise(TypeError){Complex(Object.new)} assert_raise(ArgumentError){Complex()} assert_raise(ArgumentError){Complex(1,2,3)} - c = Complex(1,0) - assert_same(c, Complex(c)) - assert_same(c, Complex(c, exception: false)) - assert_raise(ArgumentError){Complex(c, bad_keyword: true)} if (0.0/0).nan? assert_nothing_raised{Complex(0.0/0)} @@ -220,11 +216,6 @@ class Complex_Test < Test::Unit::TestCase def test_polar assert_equal([1,2], Complex.polar(1,2).polar) assert_equal(Complex.polar(1.0, Math::PI * 2 / 3), Complex.polar(1, Math::PI * 2 / 3)) - - assert_in_out_err([], <<-'end;', ['OK'], []) - Complex.polar(1, Complex(1, 0)) - puts :OK - end; end def test_uplus @@ -278,39 +269,6 @@ class Complex_Test < Test::Unit::TestCase assert_equal(Complex(Rational(5,3),Rational(2)), c + Rational(2,3)) end - def test_add_with_redefining_int_plus - assert_in_out_err([], <<-'end;', ['true'], []) - class Integer - remove_method :+ - def +(other); 42; end - end - a = Complex(1, 2) + Complex(0, 1) - puts a == Complex(42, 42) - end; - end - - def test_add_with_redefining_float_plus - assert_in_out_err([], <<-'end;', ['true'], []) - class Float - remove_method :+ - def +(other); 42.0; end - end - a = Complex(1.0, 2.0) + Complex(0, 1) - puts a == Complex(42.0, 42.0) - end; - end - - def test_add_with_redefining_rational_plus - assert_in_out_err([], <<-'end;', ['true'], []) - class Rational - remove_method :+ - def +(other); 355/113r; end - end - a = Complex(1r, 2r) + Complex(0, 1) - puts a == Complex(355/113r, 355/113r) - end; - end - def test_sub c = Complex(1,2) c2 = Complex(2,3) @@ -324,39 +282,6 @@ class Complex_Test < Test::Unit::TestCase assert_equal(Complex(Rational(1,3),Rational(2)), c - Rational(2,3)) end - def test_sub_with_redefining_int_minus - assert_in_out_err([], <<-'end;', ['true'], []) - class Integer - remove_method :- - def -(other); 42; end - end - a = Complex(1, 2) - Complex(0, 1) - puts a == Complex(42, 42) - end; - end - - def test_sub_with_redefining_float_minus - assert_in_out_err([], <<-'end;', ['true'], []) - class Float - remove_method :- - def -(other); 42.0; end - end - a = Complex(1.0, 2.0) - Complex(0, 1) - puts a == Complex(42.0, 42.0) - end; - end - - def test_sub_with_redefining_rational_minus - assert_in_out_err([], <<-'end;', ['true'], []) - class Rational - remove_method :- - def -(other); 355/113r; end - end - a = Complex(1r, 2r) - Complex(0, 1) - puts a == Complex(355/113r, 355/113r) - end; - end - def test_mul c = Complex(1,2) c2 = Complex(2,3) @@ -375,42 +300,6 @@ class Complex_Test < Test::Unit::TestCase c = Complex(0, Float::INFINITY) assert_equal(Complex(0, Float::INFINITY), c * Complex(1, 0)) assert_equal(Complex(-Float::INFINITY, 0), c * Complex(0, 1)) - - assert_equal(Complex(-0.0, -0.0), Complex(-0.0, 0) * Complex(0, 0)) - end - - def test_mul_with_redefining_int_mult - assert_in_out_err([], <<-'end;', ['true'], []) - class Integer - remove_method :* - def *(other); 42; end - end - a = Complex(2, 0) * Complex(1, 2) - puts a == Complex(0, 84) - end; - end - - def test_mul_with_redefining_float_mult - assert_in_out_err([], <<-'end;', ['true'], []) - class Float - remove_method :* - def *(other); 42.0; end - end - a = Complex(2.0, 0.0) * Complex(1, 2) - puts a == Complex(0.0, 84.0) - end; - end - - - def test_mul_with_redefining_rational_mult - assert_in_out_err([], <<-'end;', ['true'], []) - class Rational - remove_method :* - def *(other); 355/113r; end - end - a = Complex(2r, 0r) * Complex(1, 2) - puts a == Complex(0r, 2*355/113r) - end; end def test_div @@ -434,15 +323,6 @@ class Complex_Test < Test::Unit::TestCase assert_equal(Complex(Rational(1,2),Rational(1)), c / Rational(2)) assert_equal(Complex(Rational(3,2),Rational(3)), c / Rational(2,3)) - - c = Complex(1) - [ 1, Rational(1), c ].each do |d| - r = c / d - assert_instance_of(Complex, r) - assert_equal(1, r) - assert_predicate(r.real, :integer?) - assert_predicate(r.imag, :integer?) - end end def test_quo @@ -520,23 +400,12 @@ class Complex_Test < Test::Unit::TestCase r = c ** Rational(-2,3) assert_in_delta(0.432, r.real, 0.001) assert_in_delta(-0.393, r.imag, 0.001) - - c = Complex(0.0, -888888888888888.0)**8888 - assert_not_predicate(c.real, :nan?) - assert_not_predicate(c.imag, :nan?) end def test_cmp - assert_nil(Complex(5, 1) <=> Complex(2)) - assert_nil(5 <=> Complex(2, 1)) - - assert_equal(1, Complex(5) <=> Complex(2)) - assert_equal(-1, Complex(2) <=> Complex(3)) - assert_equal(0, Complex(2) <=> Complex(2)) - - assert_equal(1, Complex(5) <=> 2) - assert_equal(-1, Complex(2) <=> 3) - assert_equal(0, Complex(2) <=> 2) + assert_raise(NoMethodError){1 <=> Complex(1,1)} + assert_raise(NoMethodError){Complex(1,1) <=> 1} + assert_raise(NoMethodError){Complex(1,1) <=> Complex(1,1)} end def test_eqeq @@ -877,42 +746,10 @@ class Complex_Test < Test::Unit::TestCase end - def test_Complex_with_invalid_exception - assert_raise(ArgumentError) { - Complex("0", exception: 1) - } - end - - def test_Complex_without_exception - assert_nothing_raised(ArgumentError){ - assert_equal(nil, Complex('5x', exception: false)) - } - assert_nothing_raised(ArgumentError){ - assert_equal(nil, Complex(nil, exception: false)) - } - assert_nothing_raised(ArgumentError){ - assert_equal(nil, Complex(Object.new, exception: false)) - } - assert_nothing_raised(ArgumentError){ - assert_equal(nil, Complex(1, nil, exception: false)) - } - assert_nothing_raised(ArgumentError){ - assert_equal(nil, Complex(1, Object.new, exception: false)) - } - - o = Object.new - def o.to_c; raise; end - assert_nothing_raised(ArgumentError){ - assert_equal(nil, Complex(o, exception: false)) - } - assert_nothing_raised(ArgumentError){ - assert_equal(nil, Complex(1, o, exception: false)) - } - end - def test_respond c = Complex(1,1) assert_not_respond_to(c, :%) + assert_not_respond_to(c, :<=>) assert_not_respond_to(c, :div) assert_not_respond_to(c, :divmod) assert_not_respond_to(c, :floor) @@ -1121,30 +958,4 @@ class Complex_Test < Test::Unit::TestCase def test_known_bug end - def test_canonicalize_internal - obj = Class.new(Numeric) do - attr_accessor :real - alias real? real - end.new - obj.real = true - c = Complex.rect(obj, 1); - obj.real = false - c = c.conj - assert_equal(obj, c.real) - assert_equal(-1, c.imag) - end - - def test_canonicalize_polar - obj = Class.new(Numeric) do - def initialize - @x = 2 - end - def real? - (@x -= 1) > 0 - end - end.new - assert_raise(TypeError) do - Complex.polar(1, obj) - end - end end diff --git a/test/ruby/test_complexrational.rb b/test/ruby/test_complexrational.rb index bf4e2b1809..0360f5ee42 100644 --- a/test/ruby/test_complexrational.rb +++ b/test/ruby/test_complexrational.rb @@ -102,7 +102,7 @@ class ComplexRational_Test < Test::Unit::TestCase assert_equal(Complex(SimpleRat(4,3),SimpleRat(1,1)), c * 2) assert_equal(Complex(SimpleRat(1,3),SimpleRat(1,4)), c / 2) assert_equal(Complex(SimpleRat(7,36),SimpleRat(2,3)), c ** 2) - assert_nil(c <=> 2) + assert_raise(NoMethodError){c <=> 2} assert_equal(Complex(SimpleRat(8,3),SimpleRat(1,2)), 2 + c) assert_equal(Complex(SimpleRat(4,3),SimpleRat(-1,2)), 2 - c) @@ -111,7 +111,7 @@ class ComplexRational_Test < Test::Unit::TestCase r = 2 ** c assert_in_delta(1.4940, r.real, 0.001) assert_in_delta(0.5392, r.imag, 0.001) - assert_nil(2 <=> c) + assert_raise(NoMethodError){2 <=> c} assert_equal(Complex(SimpleRat(13,6),SimpleRat(5,2)), c + cc) assert_equal(Complex(SimpleRat(-5,6),SimpleRat(-3,2)), c - cc) @@ -120,7 +120,7 @@ class ComplexRational_Test < Test::Unit::TestCase r = c ** cc assert_in_delta(0.1732, r.real, 0.001) assert_in_delta(0.1186, r.imag, 0.001) - assert_nil(c <=> cc) + assert_raise(NoMethodError){c <=> cc} assert_equal(Complex(SimpleRat(13,6),SimpleRat(5,2)), cc + c) assert_equal(Complex(SimpleRat(5,6),SimpleRat(3,2)), cc - c) @@ -129,7 +129,7 @@ class ComplexRational_Test < Test::Unit::TestCase r = cc ** c assert_in_delta(0.5498, r.real, 0.001) assert_in_delta(1.0198, r.imag, 0.001) - assert_nil(cc <=> c) + assert_raise(NoMethodError){cc <=> c} assert_equal([SimpleRat,SimpleRat], (+c).instance_eval{[real.class, imag.class]}) diff --git a/test/ruby/test_const.rb b/test/ruby/test_const.rb index f6b9ea83d3..8784e0e988 100644 --- a/test/ruby/test_const.rb +++ b/test/ruby/test_const.rb @@ -3,30 +3,20 @@ require 'test/unit' class TestConst < Test::Unit::TestCase + TEST1 = 1 + TEST2 = 2 - Constants_Setup = -> do - remove_const :TEST1 if defined? ::TestConst::TEST1 - remove_const :TEST2 if defined? ::TestConst::TEST2 - remove_const :Const if defined? ::TestConst::Const - remove_const :Const2 if defined? ::TestConst::Const2 - - TEST1 = 1 - TEST2 = 2 - - module Const - TEST3 = 3 - TEST4 = 4 - end + module Const + TEST3 = 3 + TEST4 = 4 + end - module Const2 - TEST3 = 6 - TEST4 = 8 - end + module Const2 + TEST3 = 6 + TEST4 = 8 end def test_const - Constants_Setup.call - assert defined?(TEST1) assert_equal 1, TEST1 assert defined?(TEST2) @@ -58,17 +48,6 @@ class TestConst < Test::Unit::TestCase assert_equal 8, TEST4 end - def test_const_access_from_nil - assert_raise(TypeError) { eval("nil::Object") } - assert_nil eval("defined?(nil::Object)") - - assert_raise(TypeError) { eval("c = nil; c::Object") } - assert_nil eval("c = nil; defined?(c::Object)") - - assert_raise(TypeError) { eval("sc = Class.new; sc::C = nil; sc::C::Object") } - assert_nil eval("sc = Class.new; sc::C = nil; defined?(sc::C::Object)") - end - def test_redefinition c = Class.new name = "X\u{5b9a 6570}" diff --git a/test/ruby/test_continuation.rb b/test/ruby/test_continuation.rb index 8c62d20840..a06ac98c8c 100644 --- a/test/ruby/test_continuation.rb +++ b/test/ruby/test_continuation.rb @@ -88,16 +88,11 @@ class TestContinuation < Test::Unit::TestCase @memo += 1 c = cont cont = nil - begin - c.call(nil) - rescue RuntimeError - set_trace_func(nil) - end + c.call(nil) end end end cont = callcc { |cc| cc } - if cont set_trace_func(func) else @@ -105,12 +100,12 @@ class TestContinuation < Test::Unit::TestCase end end - def _test_tracing_with_set_trace_func + def test_tracing_with_set_trace_func @memo = 0 tracing_with_set_trace_func tracing_with_set_trace_func tracing_with_set_trace_func - assert_equal 0, @memo + assert_equal 3, @memo end def tracing_with_thread_set_trace_func @@ -120,11 +115,7 @@ class TestContinuation < Test::Unit::TestCase @memo += 1 c = cont cont = nil - begin - c.call(nil) - rescue RuntimeError - Thread.current.set_trace_func(nil) - end + c.call(nil) end end cont = callcc { |cc| cc } diff --git a/test/ruby/test_default_gems.rb b/test/ruby/test_default_gems.rb deleted file mode 100644 index 3c4aea1561..0000000000 --- a/test/ruby/test_default_gems.rb +++ /dev/null @@ -1,16 +0,0 @@ -# frozen_string_literal: false -require 'rubygems' - -class TestDefaultGems < Test::Unit::TestCase - - def test_validate_gemspec - skip "git not found" unless system("git", "rev-parse", %i[out err]=>IO::NULL) - srcdir = File.expand_path('../../..', __FILE__) - Dir.glob("#{srcdir}/{lib,ext}/**/*.gemspec").map do |src| - assert_nothing_raised do - raise("invalid spec in #{src}") unless Gem::Specification.load(src) - end - end - end - -end diff --git a/test/ruby/test_defined.rb b/test/ruby/test_defined.rb index 87f02055ab..9976db3b6f 100644 --- a/test/ruby/test_defined.rb +++ b/test/ruby/test_defined.rb @@ -23,80 +23,40 @@ class TestDefined < Test::Unit::TestCase return !defined?(yield) end - def test_defined_global_variable + def test_defined $x = nil assert(defined?($x)) # global variable assert_equal('global-variable', defined?($x))# returns description - end - def test_defined_local_variable assert_nil(defined?(foo)) # undefined foo=5 assert(defined?(foo)) # local variable - end - def test_defined_constant assert(defined?(Array)) # constant assert(defined?(::Array)) # toplevel constant assert(defined?(File::Constants)) # nested constant - end - - def test_defined_public_method assert(defined?(Object.new)) # method assert(defined?(Object::new)) # method - end - - def test_defined_private_method assert(!defined?(Object.print)) # private method - end - - def test_defined_operator assert(defined?(1 == 2)) # operator expression - end - def test_defined_protected_method f = Foo.new assert_nil(defined?(f.foo)) # protected method f.bar(f) { |v| assert(v) } - f.bar(Class.new(Foo).new) { |v| assert(v, "inherited protected method") } - end - - def test_defined_undefined_method - f = Foo.new assert_nil(defined?(f.quux)) # undefined method - end - - def test_defined_undefined_argument - f = Foo.new assert_nil(defined?(f.baz(x))) # undefined argument x = 0 assert(defined?(f.baz(x))) assert_nil(defined?(f.quux(x))) assert(defined?(print(x))) assert_nil(defined?(quux(x))) - end - - def test_defined_attrasgn - f = Foo.new assert(defined?(f.attr = 1)) f.attrasgn_test { |v| assert(v) } - end - - def test_defined_undef - x = Object.new - def x.foo; end - assert(defined?(x.foo)) - x.instance_eval {undef :foo} - assert(!defined?(x.foo), "undefed method should not be defined?") - end - def test_defined_yield assert(defined_test) # not iterator assert(!defined_test{}) # called as iterator - end - def test_defined_matchdata /a/ =~ '' assert_equal nil, defined?($&) assert_equal nil, defined?($`) @@ -125,16 +85,12 @@ class TestDefined < Test::Unit::TestCase assert_equal 'global-variable', defined?($+) assert_equal 'global-variable', defined?($1) assert_equal nil, defined?($2) - end - def test_defined_literal assert_equal("nil", defined?(nil)) assert_equal("true", defined?(true)) assert_equal("false", defined?(false)) assert_equal("expression", defined?(1)) - end - def test_defined_empty_paren_expr bug8224 = '[ruby-core:54024] [Bug #8224]' (1..3).each do |level| expr = "("*level+")"*level @@ -301,86 +257,4 @@ class TestDefined < Test::Unit::TestCase def test_top_level_constant_not_defined assert_nil(defined?(TestDefined::Object)) end - - def test_super_with_method_missing - c0 = EnvUtil.labeled_class("C0") do - attr_reader :calls - - def initialize - @calls = [] - end - - def method_missing(*args) - @calls << [:method_missing, *args] - end - - def respond_to_missing?(*args) - @calls << [:respond_to_missing?, *args] - true - end - end - - c1 = EnvUtil.labeled_class("C1", c0) do - def foo - super - defined?(super) - end - end - - c = c1.new - assert_not_nil(c.foo) - assert_equal([ - [:method_missing, :foo], - [:respond_to_missing?, :foo, true], - ], c.calls) - end - - class RefinedClass - end - - module RefiningModule - refine RefinedClass do - def pub - end - - private - - def priv - end - end - - def self.call_without_using(x = RefinedClass.new) - defined?(x.pub) - end - - def self.vcall_without_using(x = RefinedClass.new) - x.instance_eval {defined?(priv)} - end - - using self - - def self.call_with_using(x = RefinedClass.new) - defined?(x.pub) - end - - def self.vcall_with_using(x = RefinedClass.new) - x.instance_eval {defined?(priv)} - end - end - - def test_defined_refined_call_without_using - assert(!RefiningModule.call_without_using, "refined public method without using") - end - - def test_defined_refined_vcall_without_using - assert(!RefiningModule.vcall_without_using, "refined private method without using") - end - - def test_defined_refined_call_with_using - assert(RefiningModule.call_with_using, "refined public method with using") - end - - def test_defined_refined_vcall_with_using - assert(RefiningModule.vcall_with_using, "refined private method with using") - end end diff --git a/test/ruby/test_dir.rb b/test/ruby/test_dir.rb index e5bcbeac73..000bc24e85 100644 --- a/test/ruby/test_dir.rb +++ b/test/ruby/test_dir.rb @@ -8,15 +8,14 @@ class TestDir < Test::Unit::TestCase def setup @verbose = $VERBOSE + $VERBOSE = nil @root = File.realpath(Dir.mktmpdir('__test_dir__')) @nodir = File.join(@root, "dummy") - @dirs = [] for i in "a".."z" if i.ord % 2 == 0 FileUtils.touch(File.join(@root, i)) else FileUtils.mkdir(File.join(@root, i)) - @dirs << File.join(i, "") end end end @@ -87,72 +86,40 @@ class TestDir < Test::Unit::TestCase end def test_chdir - pwd = Dir.pwd - env_home = ENV["HOME"] - env_logdir = ENV["LOGDIR"] + @pwd = Dir.pwd + @env_home = ENV["HOME"] + @env_logdir = ENV["LOGDIR"] ENV.delete("HOME") ENV.delete("LOGDIR") assert_raise(Errno::ENOENT) { Dir.chdir(@nodir) } assert_raise(ArgumentError) { Dir.chdir } - ENV["HOME"] = pwd + ENV["HOME"] = @pwd Dir.chdir do - assert_warning(/conflicting chdir during another chdir block/) { Dir.chdir(pwd) } - - assert_warning(/conflicting chdir during another chdir block/) { Dir.chdir(@root) } - assert_equal(@root, Dir.pwd) - - assert_warning(/conflicting chdir during another chdir block/) { Dir.chdir(pwd) } - - assert_raise(RuntimeError) { Thread.new { Thread.current.report_on_exception = false; Dir.chdir(@root) }.join } - assert_raise(RuntimeError) { Thread.new { Thread.current.report_on_exception = false; Dir.chdir(@root) { } }.join } - - assert_warning(/conflicting chdir during another chdir block/) { Dir.chdir(pwd) } - - assert_warning(/conflicting chdir during another chdir block/) { Dir.chdir(@root) } + assert_equal(@pwd, Dir.pwd) + Dir.chdir(@root) assert_equal(@root, Dir.pwd) - - assert_warning(/conflicting chdir during another chdir block/) { Dir.chdir(pwd) } - Dir.chdir(@root) do - assert_equal(@root, Dir.pwd) - end - assert_equal(pwd, Dir.pwd) end ensure begin - Dir.chdir(pwd) + Dir.chdir(@pwd) rescue - abort("cannot return the original directory: #{ pwd }") + abort("cannot return the original directory: #{ @pwd }") end - ENV["HOME"] = env_home - ENV["LOGDIR"] = env_logdir - end - - def test_chdir_conflict - pwd = Dir.pwd - q = Queue.new - t = Thread.new do - q.pop - Dir.chdir(pwd) rescue $! - end - Dir.chdir(pwd) do - q.push nil - assert_instance_of(RuntimeError, t.value) + if @env_home + ENV["HOME"] = @env_home + else + ENV.delete("HOME") end - - t = Thread.new do - q.pop - Dir.chdir(pwd){} rescue $! - end - Dir.chdir(pwd) do - q.push nil - assert_instance_of(RuntimeError, t.value) + if @env_logdir + ENV["LOGDIR"] = @env_logdir + else + ENV.delete("LOGDIR") end end def test_chroot_nodir - skip if RUBY_PLATFORM =~ /android/ assert_raise(NotImplementedError, Errno::ENOENT, Errno::EPERM ) { Dir.chroot(File.join(@nodir, "")) } end @@ -166,17 +133,14 @@ class TestDir < Test::Unit::TestCase def test_glob assert_equal((%w(. ..) + ("a".."z").to_a).map{|f| File.join(@root, f) }, - Dir.glob(File.join(@root, "*"), File::FNM_DOTMATCH)) - assert_equal([@root] + ("a".."z").map {|f| File.join(@root, f) }, - Dir.glob([@root, File.join(@root, "*")])) - assert_equal([@root] + ("a".."z").map {|f| File.join(@root, f) }, - Dir.glob([@root, File.join(@root, "*")], sort: false).sort) - assert_raise_with_message(ArgumentError, /nul-separated/) do - Dir.glob(@root + "\0\0\0" + File.join(@root, "*")) - end - - assert_equal(("a".."z").step(2).map {|f| File.join(File.join(@root, f), "") }, - Dir.glob(File.join(@root, "*/"))) + Dir.glob(File.join(@root, "*"), File::FNM_DOTMATCH).sort) + assert_equal([@root] + ("a".."z").map {|f| File.join(@root, f) }.sort, + Dir.glob([@root, File.join(@root, "*")]).sort) + assert_equal([@root] + ("a".."z").map {|f| File.join(@root, f) }.sort, + Dir.glob(@root + "\0\0\0" + File.join(@root, "*")).sort) + + assert_equal(("a".."z").step(2).map {|f| File.join(File.join(@root, f), "") }.sort, + Dir.glob(File.join(@root, "*/")).sort) assert_equal([File.join(@root, '//a')], Dir.glob(@root + '//a')) FileUtils.touch(File.join(@root, "{}")) @@ -186,7 +150,7 @@ class TestDir < Test::Unit::TestCase assert_equal([], Dir.glob(File.join(@root, '[a-\\'))) assert_equal([File.join(@root, "a")], Dir.glob(File.join(@root, 'a\\'))) - assert_equal(("a".."f").map {|f| File.join(@root, f) }, Dir.glob(File.join(@root, '[abc/def]'))) + assert_equal(("a".."f").map {|f| File.join(@root, f) }.sort, Dir.glob(File.join(@root, '[abc/def]')).sort) open(File.join(@root, "}}{}"), "wb") {} open(File.join(@root, "}}a"), "wb") {} @@ -216,49 +180,13 @@ class TestDir < Test::Unit::TestCase dirs = ["a/.x", "a/b/.y"] FileUtils.mkdir_p(dirs) dirs.map {|dir| open("#{dir}/z", "w") {}} - assert_equal([], Dir.glob("a/**/z"), bug8283) + assert_equal([], Dir.glob("a/**/z").sort, bug8283) assert_equal(["a/.x/z"], Dir.glob("a/**/.x/z"), bug8283) assert_equal(["a/.x/z"], Dir.glob("a/.x/**/z"), bug8283) assert_equal(["a/b/.y/z"], Dir.glob("a/**/.y/z"), bug8283) end end - def test_glob_recursive_directory - Dir.chdir(@root) do - ['d', 'e'].each do |path| - FileUtils.mkdir_p("c/#{path}/a/b/c") - FileUtils.touch("c/#{path}/a/a.file") - FileUtils.touch("c/#{path}/a/b/b.file") - FileUtils.touch("c/#{path}/a/b/c/c.file") - end - bug15540 = '[ruby-core:91110] [Bug #15540]' - assert_equal(["c/d/a/", "c/d/a/b/", "c/d/a/b/c/", "c/e/a/", "c/e/a/b/", "c/e/a/b/c/"], - Dir.glob('c/{d,e}/a/**/'), bug15540) - - assert_equal(["c/e/a/", "c/e/a/b/", "c/e/a/b/c/", "c/d/a/", "c/d/a/b/", "c/d/a/b/c/"], - Dir.glob('c/{e,d}/a/**/')) - end - end - - def test_glob_starts_with_brace - Dir.chdir(@root) do - bug15649 = '[ruby-core:91728] [Bug #15649]' - assert_equal(["#{@root}/a", "#{@root}/b"], - Dir.glob("{#{@root}/a,#{@root}/b}"), bug15649) - end - end - - def test_glob_order - 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")) - assert_equal(["#{@root}/b", "#{@root}/a"], Dir.glob("#{@root}/{b,a}")) - end - assert_equal(["a", "b"], Dir.glob("[ba]", base: @root)) - assert_equal(["b", "a"], Dir.glob(%W"b a", base: @root)) - assert_equal(["b", "a"], Dir.glob("{b,a}", base: @root)) - end - if Process.const_defined?(:RLIMIT_NOFILE) def test_glob_too_may_open_files assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}", chdir: @root) @@ -280,63 +208,18 @@ class TestDir < Test::Unit::TestCase def test_glob_base files = %w[a/foo.c c/bar.c] files.each {|n| File.write(File.join(@root, n), "")} - Dir.mkdir(File.join(@root, "a/dir")) - dirs = @dirs + %w[a/dir/] - dirs.sort! - - assert_equal(files, Dir.glob("*/*.c", base: @root)) - assert_equal(files, Dir.chdir(@root) {Dir.glob("*/*.c", base: ".")}) - assert_equal(%w[foo.c], Dir.chdir(@root) {Dir.glob("*.c", base: "a")}) - assert_equal(files, Dir.chdir(@root) {Dir.glob("*/*.c", base: "")}) - assert_equal(files, Dir.chdir(@root) {Dir.glob("*/*.c", base: nil)}) - assert_equal(@dirs, Dir.glob("*/", base: @root)) - assert_equal(@dirs, Dir.chdir(@root) {Dir.glob("*/", base: ".")}) - assert_equal(%w[dir/], Dir.chdir(@root) {Dir.glob("*/", base: "a")}) - assert_equal(@dirs, Dir.chdir(@root) {Dir.glob("*/", base: "")}) - assert_equal(@dirs, Dir.chdir(@root) {Dir.glob("*/", base: nil)}) - assert_equal(dirs, Dir.glob("**/*/", base: @root)) - assert_equal(dirs, Dir.chdir(@root) {Dir.glob("**/*/", base: ".")}) - assert_equal(%w[dir/], Dir.chdir(@root) {Dir.glob("**/*/", base: "a")}) - assert_equal(dirs, Dir.chdir(@root) {Dir.glob("**/*/", base: "")}) - assert_equal(dirs, Dir.chdir(@root) {Dir.glob("**/*/", base: nil)}) - - assert_equal(files, Dir.glob("*/*.c", base: @root, sort: false).sort) - assert_equal(files, Dir.chdir(@root) {Dir.glob("*/*.c", base: ".", sort: false).sort}) - assert_equal(%w[foo.c], Dir.chdir(@root) {Dir.glob("*.c", base: "a", sort: false).sort}) - assert_equal(files, Dir.chdir(@root) {Dir.glob("*/*.c", base: "", sort: false).sort}) - assert_equal(files, Dir.chdir(@root) {Dir.glob("*/*.c", base: nil, sort: false).sort}) - assert_equal(@dirs, Dir.glob("*/", base: @root)) - assert_equal(@dirs, Dir.chdir(@root) {Dir.glob("*/", base: ".", sort: false).sort}) - assert_equal(%w[dir/], Dir.chdir(@root) {Dir.glob("*/", base: "a", sort: false).sort}) - assert_equal(@dirs, Dir.chdir(@root) {Dir.glob("*/", base: "", sort: false).sort}) - assert_equal(@dirs, Dir.chdir(@root) {Dir.glob("*/", base: nil, sort: false).sort}) - assert_equal(dirs, Dir.glob("**/*/", base: @root)) - assert_equal(dirs, Dir.chdir(@root) {Dir.glob("**/*/", base: ".", sort: false).sort}) - assert_equal(%w[dir/], Dir.chdir(@root) {Dir.glob("**/*/", base: "a", sort: false).sort}) - assert_equal(dirs, Dir.chdir(@root) {Dir.glob("**/*/", base: "", sort: false).sort}) - assert_equal(dirs, Dir.chdir(@root) {Dir.glob("**/*/", base: nil, sort: false).sort}) + assert_equal(files, Dir.glob("*/*.c", base: @root).sort) + assert_equal(files, Dir.chdir(@root) {Dir.glob("*/*.c", base: ".").sort}) + assert_equal(%w[foo.c], Dir.chdir(@root) {Dir.glob("*.c", base: "a").sort}) + assert_equal(files, Dir.chdir(@root) {Dir.glob("*/*.c", base: "").sort}) + assert_equal(files, Dir.chdir(@root) {Dir.glob("*/*.c", base: nil).sort}) end def test_glob_base_dir files = %w[a/foo.c c/bar.c] files.each {|n| File.write(File.join(@root, n), "")} - Dir.mkdir(File.join(@root, "a/dir")) - dirs = @dirs + %w[a/dir/] - dirs.sort! - - assert_equal(files, Dir.open(@root) {|d| Dir.glob("*/*.c", base: d)}) - assert_equal(%w[foo.c], Dir.chdir(@root) {Dir.open("a") {|d| Dir.glob("*.c", base: d)}}) - assert_equal(@dirs, Dir.open(@root) {|d| Dir.glob("*/", base: d)}) - assert_equal(%w[dir/], Dir.chdir(@root) {Dir.open("a") {|d| Dir.glob("*/", base: d)}}) - assert_equal(dirs, Dir.open(@root) {|d| Dir.glob("**/*/", base: d)}) - assert_equal(%w[dir/], Dir.chdir(@root) {Dir.open("a") {|d| Dir.glob("**/*/", base: d)}}) - - assert_equal(files, Dir.open(@root) {|d| Dir.glob("*/*.c", base: d, sort: false).sort}) - assert_equal(%w[foo.c], Dir.chdir(@root) {Dir.open("a") {|d| Dir.glob("*.c", base: d, sort: false).sort}}) - assert_equal(@dirs, Dir.open(@root) {|d| Dir.glob("*/", base: d, sort: false).sort}) - assert_equal(%w[dir/], Dir.chdir(@root) {Dir.open("a") {|d| Dir.glob("*/", base: d, sort: false).sort}}) - assert_equal(dirs, Dir.open(@root) {|d| Dir.glob("**/*/", base: d, sort: false).sort}) - assert_equal(%w[dir/], Dir.chdir(@root) {Dir.open("a") {|d| Dir.glob("**/*/", base: d, sort: false).sort}}) + assert_equal(files, Dir.open(@root) {|d| Dir.glob("*/*.c", base: d)}.sort) + assert_equal(%w[foo.c], Dir.chdir(@root) {Dir.open("a") {|d| Dir.glob("*", base: d)}}) end def assert_entries(entries, children_only = false) @@ -348,52 +231,24 @@ class TestDir < Test::Unit::TestCase def test_entries assert_entries(Dir.open(@root) {|dir| dir.entries}) - assert_entries(Dir.entries(@root)) + assert_entries(Dir.entries(@root).to_a) assert_raise(ArgumentError) {Dir.entries(@root+"\0")} - [Encoding::UTF_8, Encoding::ASCII_8BIT].each do |enc| - assert_equal(enc, Dir.entries(@root, encoding: enc).first.encoding) - end end def test_foreach assert_entries(Dir.open(@root) {|dir| dir.each.to_a}) assert_entries(Dir.foreach(@root).to_a) assert_raise(ArgumentError) {Dir.foreach(@root+"\0").to_a} - newdir = @root+"/new" - e = Dir.foreach(newdir) - assert_raise(Errno::ENOENT) {e.to_a} - Dir.mkdir(newdir) - File.write(newdir+"/a", "") - assert_equal(%w[. .. a], e.to_a.sort) - [Encoding::UTF_8, Encoding::ASCII_8BIT].each do |enc| - e = Dir.foreach(newdir, encoding: enc) - assert_equal(enc, e.to_a.first.encoding) - end end def test_children - assert_entries(Dir.open(@root) {|dir| dir.children}, true) assert_entries(Dir.children(@root), true) assert_raise(ArgumentError) {Dir.children(@root+"\0")} - [Encoding::UTF_8, Encoding::ASCII_8BIT].each do |enc| - assert_equal(enc, Dir.children(@root, encoding: enc).first.encoding) - end end def test_each_child - assert_entries(Dir.open(@root) {|dir| dir.each_child.to_a}, true) assert_entries(Dir.each_child(@root).to_a, true) assert_raise(ArgumentError) {Dir.each_child(@root+"\0").to_a} - newdir = @root+"/new" - e = Dir.each_child(newdir) - assert_raise(Errno::ENOENT) {e.to_a} - Dir.mkdir(newdir) - File.write(newdir+"/a", "") - assert_equal(%w[a], e.to_a) - [Encoding::UTF_8, Encoding::ASCII_8BIT].each do |enc| - e = Dir.each_child(newdir, encoding: enc) - assert_equal(enc, e.to_a.first.encoding) - end end def test_dir_enc @@ -434,10 +289,10 @@ class TestDir < Test::Unit::TestCase end assert_equal([*"a".."z", *"symlink-a".."symlink-z"].each_slice(2).map {|f, _| File.join(@root, f + "/") }.sort, - Dir.glob(File.join(@root, "*/"))) + Dir.glob(File.join(@root, "*/")).sort) - assert_equal([@root + "/", *[*"a".."z"].each_slice(2).map {|f, _| File.join(@root, f + "/") }], - Dir.glob(File.join(@root, "**/"))) + assert_equal([@root + "/", *[*"a".."z"].each_slice(2).map {|f, _| File.join(@root, f + "/") }.sort], + Dir.glob(File.join(@root, "**/")).sort) end def test_glob_metachar @@ -489,18 +344,14 @@ class TestDir < Test::Unit::TestCase ENV.delete("LOGDIR") ENV["HOME"] = @nodir - assert_nothing_raised(ArgumentError) do + assert_nothing_raised(ArgumentError) { assert_equal(@nodir, Dir.home) - end - assert_nothing_raised(ArgumentError) do assert_equal(@nodir, Dir.home("")) - end - if user = ENV["USER"] - tilde = windows? ? "~" : "~#{user}" - assert_nothing_raised(ArgumentError) do - assert_equal(File.expand_path(tilde), Dir.home(user)) + if user = ENV["USER"] + ENV["HOME"] = env_home + assert_equal(File.expand_path(env_home), Dir.home(user)) end - end + } %W[no:such:user \u{7559 5b88}:\u{756a}].each do |user| assert_raise_with_message(ArgumentError, /#{user}/) {Dir.home(user)} end @@ -521,8 +372,8 @@ class TestDir < Test::Unit::TestCase Dir.mkdir('some-dir') File.write('some-dir/foo', 'some content') - assert_equal [ 'dir-symlink', 'some-dir' ], Dir['*'] - assert_equal [ 'dir-symlink', 'some-dir', 'some-dir/foo' ], Dir['**/*'] + assert_equal [ 'dir-symlink', 'some-dir' ], Dir['*'].sort + assert_equal [ 'dir-symlink', 'some-dir', 'some-dir/foo' ], Dir['**/*'].sort end end end @@ -562,27 +413,12 @@ class TestDir < Test::Unit::TestCase begin; Process.setrlimit(Process::RLIMIT_NOFILE, 50) begin - fs = [] - tap {tap {tap {(0..100).each {fs << open(IO::NULL)}}}} + tap {tap {tap {(0..100).map {open(IO::NULL)}}}} rescue Errno::EMFILE - ensure - fs.clear end - list = Dir.glob("*") + list = Dir.glob("*").sort assert_not_empty(list) assert_equal([*"a".."z"], list) end; end if defined?(Process::RLIMIT_NOFILE) - - def test_glob_array_with_destructive_element - args = Array.new(100, "") - pat = Struct.new(:ary).new(args) - args.push(pat, *Array.new(100) {"."*40}) - def pat.to_path - ary.clear - GC.start - "" - end - assert_empty(Dir.glob(args)) - end end diff --git a/test/ruby/test_dir_m17n.rb b/test/ruby/test_dir_m17n.rb index 67bad8a514..7584074c7e 100644 --- a/test/ruby/test_dir_m17n.rb +++ b/test/ruby/test_dir_m17n.rb @@ -17,19 +17,27 @@ class TestDir_M17N < Test::Unit::TestCase assert_separately(["-E#{encoding}"], <<-EOS, :chdir=>dir) filename = #{code}.chr('UTF-8').force_encoding("#{encoding}") File.open(filename, "w") {} - ents = Dir.entries(".") - if /mswin|mingw/ =~ RUBY_PLATFORM - filename = filename.encode("UTF-8") - end + opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM + ents = Dir.entries(".", opts) assert_include(ents, filename) EOS return if /cygwin/ =~ RUBY_PLATFORM assert_separately(%w[-EASCII-8BIT], <<-EOS, :chdir=>dir) filename = #{code}.chr('UTF-8').force_encoding("ASCII-8BIT") - ents = Dir.entries(".") + opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM + ents = Dir.entries(".", opts) + expected_filename = #{code}.chr('UTF-8').encode(Encoding.find("filesystem")) rescue expected_filename = "?" + expected_filename = expected_filename.force_encoding("ASCII-8BIT") if /mswin|mingw/ =~ RUBY_PLATFORM - filename.force_encoding("UTF-8") + case + when ents.include?(filename) + when ents.include?(expected_filename) + filename = expected_filename + else + ents = Dir.entries(".", {:encoding => Encoding.find("filesystem")}) + filename = expected_filename + end end assert_include(ents, filename) EOS @@ -44,7 +52,7 @@ class TestDir_M17N < Test::Unit::TestCase filename = "\u3042" File.open(filename, "w") {} opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM - ents = Dir.entries(".", **(opts||{})) + ents = Dir.entries(".", opts) assert_include(ents, filename) EOS } @@ -59,7 +67,7 @@ class TestDir_M17N < Test::Unit::TestCase filename = "\xff".force_encoding("ASCII-8BIT") # invalid byte sequence as UTF-8 File.open(filename, "w") {} opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM - ents = Dir.entries(".", **(opts||{})) + ents = Dir.entries(".", opts) filename = "%FF" if /darwin/ =~ RUBY_PLATFORM && ents.include?("%FF") assert_include(ents, filename) EOS @@ -67,7 +75,7 @@ class TestDir_M17N < Test::Unit::TestCase filename = "\xff".force_encoding("UTF-8") # invalid byte sequence as UTF-8 File.open(filename, "w") {} opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM - ents = Dir.entries(".", **(opts||{})) + ents = Dir.entries(".", opts) filename = "%FF" if /darwin/ =~ RUBY_PLATFORM && ents.include?("%FF") assert_include(ents, filename) EOS @@ -80,7 +88,7 @@ class TestDir_M17N < Test::Unit::TestCase filename = "\xc2\xa1".force_encoding("utf-8") File.open(filename, "w") {} opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM - ents = Dir.entries(".", **(opts||{})) + ents = Dir.entries(".", opts) assert_include(ents, filename) EOS assert_separately(%w[-EUTF-8], <<-'EOS', :chdir=>d) @@ -117,13 +125,13 @@ class TestDir_M17N < Test::Unit::TestCase filename = "\u3042" File.open(filename, "w") {} opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM - ents = Dir.entries(".", **(opts||{})) + ents = Dir.entries(".", opts) assert_include(ents, filename) EOS assert_separately(%w[-EUTF-8:EUC-JP], <<-'EOS', :chdir=>d) filename = "\xA4\xA2".force_encoding("euc-jp") opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM - ents = Dir.entries(".", **(opts||{})) + ents = Dir.entries(".", opts) assert_include(ents, filename) EOS assert_separately(%w[-EUTF-8:EUC-JP], <<-'EOS', :chdir=>d) @@ -143,7 +151,7 @@ class TestDir_M17N < Test::Unit::TestCase File.open(filename1, "w") {} File.open(filename2, "w") {} opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM - ents = Dir.entries(".", **(opts||{})) + ents = Dir.entries(".", opts) assert_include(ents, filename1) assert_include(ents, filename2) EOS @@ -151,7 +159,7 @@ class TestDir_M17N < Test::Unit::TestCase filename1 = "\u2661" # WHITE HEART SUIT which is not representable in EUC-JP filename2 = "\xA4\xA2".force_encoding("euc-jp") # HIRAGANA LETTER A in EUC-JP opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM - ents = Dir.entries(".", **(opts||{})) + ents = Dir.entries(".", opts) assert_include(ents, filename1) assert_include(ents, filename2) EOS @@ -175,7 +183,7 @@ class TestDir_M17N < Test::Unit::TestCase filename = "\xA4\xA2".force_encoding("euc-jp") File.open(filename, "w") {} opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM - ents = Dir.entries(".", **(opts||{})) + ents = Dir.entries(".", opts) ents.each {|e| e.force_encoding("ASCII-8BIT") } if /darwin/ =~ RUBY_PLATFORM filename = filename.encode("utf-8") @@ -191,23 +199,27 @@ class TestDir_M17N < Test::Unit::TestCase assert_separately(%w[-EEUC-JP], <<-'EOS', :chdir=>d) filename = "\xA4\xA2".force_encoding("euc-jp") File.open(filename, "w") {} - ents = Dir.entries(".") + opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM + ents = Dir.entries(".", opts) if /darwin/ =~ RUBY_PLATFORM filename = filename.encode("utf-8").force_encoding("euc-jp") - elsif /mswin|mingw/ =~ RUBY_PLATFORM - filename = filename.encode("utf-8") end assert_include(ents, filename) EOS assert_separately(%w[-EASCII-8BIT], <<-'EOS', :chdir=>d) filename = "\xA4\xA2".force_encoding('ASCII-8BIT') - ents = Dir.entries(".") + win_expected_filename = filename.encode(Encoding.find("filesystem"), "euc-jp") rescue "?" + opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM + ents = Dir.entries(".", opts) unless ents.include?(filename) case RUBY_PLATFORM when /darwin/ filename = filename.encode("utf-8", "euc-jp").b when /mswin|mingw/ - filename = filename.encode("utf-8", "euc-jp") + if ents.include?(win_expected_filename.b) + ents = Dir.entries(".", {:encoding => Encoding.find("filesystem")}) + filename = win_expected_filename + end end end assert_include(ents, filename) @@ -234,7 +246,7 @@ class TestDir_M17N < Test::Unit::TestCase filename = "\xA4\xA2".force_encoding("euc-jp") File.open(filename, "w") {} opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM - ents = Dir.entries(".", **(opts||{})) + ents = Dir.entries(".", opts) if /darwin/ =~ RUBY_PLATFORM filename = filename.encode("utf-8", "euc-jp").force_encoding("euc-jp") end @@ -243,7 +255,7 @@ class TestDir_M17N < Test::Unit::TestCase assert_separately(%w[-EEUC-JP:UTF-8], <<-'EOS', :chdir=>d) filename = "\u3042" opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM - ents = Dir.entries(".", **(opts||{})) + ents = Dir.entries(".", opts) if /darwin/ =~ RUBY_PLATFORM filename = filename.force_encoding("euc-jp") end @@ -402,8 +414,13 @@ class TestDir_M17N < Test::Unit::TestCase orig.each {|n| open(n, "w") {}} enc = Encoding.find("filesystem") enc = Encoding::ASCII_8BIT if enc == Encoding::US_ASCII - orig.each {|o| o.force_encoding(enc) } - ents = Dir.entries(".").reject {|n| /\A\./ =~ n} + if /mswin|mingw/ =~ RUBY_PLATFORM + opts = {:encoding => enc} + orig.map! {|o| o.encode("filesystem") rescue o.tr("^a-z", "?")} + else + orig.each {|o| o.force_encoding(enc) } + end + ents = Dir.entries(".", opts).reject {|n| /\A\./ =~ n} ents.sort! PP.assert_equal(orig, ents, bug7267) } @@ -414,9 +431,13 @@ class TestDir_M17N < Test::Unit::TestCase expected = [] results = [] orig.each {|o| - enc = Encoding.find("filesystem") - enc = Encoding::ASCII_8BIT if enc == Encoding::US_ASCII - n = o.dup.force_encoding(enc) + if /mswin|mingw/ =~ RUBY_PLATFORM + n = (o.encode("filesystem") rescue next) + else + enc = Encoding.find("filesystem") + enc = Encoding::ASCII_8BIT if enc == Encoding::US_ASCII + n = o.dup.force_encoding(enc) + end expected << n with_tmpdir { Dir.mkdir(o) diff --git a/test/ruby/test_econv.rb b/test/ruby/test_econv.rb index a1ab1c8df6..6f098db454 100644 --- a/test/ruby/test_econv.rb +++ b/test/ruby/test_econv.rb @@ -3,12 +3,7 @@ require 'test/unit' class TestEncodingConverter < Test::Unit::TestCase def check_ec(edst, esrc, eres, dst, src, ec, off, len, opts=nil) - case opts - when Hash - res = ec.primitive_convert(src, dst, off, len, **opts) - else - res = ec.primitive_convert(src, dst, off, len, opts) - end + res = ec.primitive_convert(src, dst, off, len, opts) assert_equal([edst.b, esrc.b, eres], [dst.b, src.b, res]) end @@ -685,6 +680,7 @@ class TestEncodingConverter < Test::Unit::TestCase ec = Encoding::Converter.new("utf-8", "euc-jp") assert_raise(Encoding::InvalidByteSequenceError) { ec.convert("a\x80") } assert_raise(Encoding::UndefinedConversionError) { ec.convert("\ufffd") } + assert_predicate(ec.convert("abc".taint), :tainted?) ret = ec.primitive_convert(nil, "", nil, nil) assert_equal(:finished, ret) assert_raise(ArgumentError) { ec.convert("a") } @@ -803,7 +799,7 @@ class TestEncodingConverter < Test::Unit::TestCase assert_equal('', ec.finish) ec = Encoding::Converter.new("", "xml_attr_content_escape") - assert_equal('&<>"'', ec.convert("&<>\"'")) + assert_equal('&<>"', ec.convert("&<>\"")) assert_equal('', ec.finish) end @@ -844,7 +840,7 @@ class TestEncodingConverter < Test::Unit::TestCase def test_xml_hasharg assert_equal("&\e$B$&\e(B♥&\"'".force_encoding("iso-2022-jp"), "&\u3046\u2665&\"'".encode("iso-2022-jp", xml: :text)) - assert_equal("\"&\e$B$&\e(B♡&"'\"".force_encoding("iso-2022-jp"), + assert_equal("\"&\e$B$&\e(B♡&"'\"".force_encoding("iso-2022-jp"), "&\u3046\u2661&\"'".encode("iso-2022-jp", xml: :attr)) assert_equal("&\u3046\u2661&\"'".force_encoding("utf-8"), @@ -912,21 +908,6 @@ class TestEncodingConverter < Test::Unit::TestCase assert_raise_with_message(ArgumentError, /\u{3042}/) { Encoding::Converter.new("", "", newline: "\u{3042}".to_sym) } - newlines = %i[universal_newline crlf_newline cr_newline] - (2..newlines.size).each do |i| - newlines.combination(i) do |opts| - assert_raise(Encoding::ConverterNotFoundError, "#{opts} are mutually exclusive") do - Encoding::Converter.new("", "", **opts.inject({}) {|o,nl|o[nl]=true;o}) - end - end - end - newlines.each do |nl| - opts = {newline: :universal, nl => true} - ec2 = assert_warning(/:newline option preceds/, opts.inspect) do - Encoding::Converter.new("", "", **opts) - end - assert_equal(ec1, ec2) - end end def test_default_external diff --git a/test/ruby/test_encoding.rb b/test/ruby/test_encoding.rb index 2965c0bc7b..8f73a8fce1 100644 --- a/test/ruby/test_encoding.rb +++ b/test/ruby/test_encoding.rb @@ -34,6 +34,9 @@ class TestEncoding < Test::Unit::TestCase assert_raise(TypeError) { e.dup } assert_raise(TypeError) { e.clone } assert_equal(e.object_id, Marshal.load(Marshal.dump(e)).object_id) + assert_not_predicate(e, :tainted?) + Marshal.load(Marshal.dump(e).taint) + assert_not_predicate(e, :tainted?, '[ruby-core:71793] [Bug #11760]') end end @@ -56,36 +59,11 @@ class TestEncoding < Test::Unit::TestCase end def test_replicate - assert_separately([], "#{<<~'END;'}") - assert_instance_of(Encoding, Encoding::UTF_8.replicate("UTF-8-ANOTHER#{Time.now.to_f}")) - assert_instance_of(Encoding, Encoding::ISO_2022_JP.replicate("ISO-2022-JP-ANOTHER#{Time.now.to_f}")) + assert_instance_of(Encoding, Encoding::UTF_8.replicate('UTF-8-ANOTHER')) + assert_instance_of(Encoding, Encoding::ISO_2022_JP.replicate('ISO-2022-JP-ANOTHER')) bug3127 = '[ruby-dev:40954]' assert_raise(TypeError, bug3127) {Encoding::UTF_8.replicate(0)} - assert_raise_with_message(ArgumentError, /\bNUL\b/, bug3127) {Encoding::UTF_8.replicate("\0")} - END; - end - - def test_extra_encoding - assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") - begin; - 200.times {|i| - Encoding::UTF_8.replicate("dummy#{i}") - } - e = Encoding.list.last - format = "%d".force_encoding(e) - assert_equal("0", format % 0) - assert_equal(e, format.dup.encoding) - assert_equal(e, (format*1).encoding) - - assert_equal(e, (("x"*30).force_encoding(e)*1).encoding) - GC.start - - name = "A" * 64 - Encoding.list.each do |enc| - assert_raise(ArgumentError) {enc.replicate(name)} - name.succ! - end - end; + assert_raise(ArgumentError, bug3127) {Encoding::UTF_8.replicate("\0")} end def test_dummy_p @@ -142,21 +120,9 @@ class TestEncoding < Test::Unit::TestCase assert_separately(%w[--disable=gems], "#{<<~"begin;"}\n#{<<~'end;'}") bug9038 = '[ruby-core:57949] [Bug #9038]' begin; - e = assert_raise_with_message(SyntaxError, /unknown regexp option - Q/, bug9038) { + assert_raise_with_message(SyntaxError, /unknown regexp option - Q/, bug9038) { eval("/regexp/sQ") } - assert_include(e.message, "/regexp/sQ\n") - end; - end - - def test_nonascii_library_path - assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}".force_encoding("US-ASCII")) - begin; - assert_equal(Encoding::US_ASCII, __ENCODING__) - $:.unshift("/\x80") - assert_raise_with_message(LoadError, /\[Bug #16382\]/) do - $:.resolve_feature_path "[Bug #16382]" - end end; end end diff --git a/test/ruby/test_enum.rb b/test/ruby/test_enum.rb index 126b100b03..2167271886 100644 --- a/test/ruby/test_enum.rb +++ b/test/ruby/test_enum.rb @@ -27,6 +27,7 @@ class TestEnumerable < Test::Unit::TestCase end end @verbose = $VERBOSE + $VERBOSE = nil end def teardown @@ -62,32 +63,11 @@ class TestEnumerable < Test::Unit::TestCase assert_equal([[2, 1], [2, 4]], a) end - def test_grep_optimization - bug17030 = '[ruby-core:99156]' - 'set last match' =~ /set last (.*)/ - assert_equal([:a, 'b', :c], [:a, 'b', 'z', :c, 42, nil].grep(/[a-d]/), bug17030) - assert_equal(['z', 42, nil], [:a, 'b', 'z', :c, 42, nil].grep_v(/[a-d]/), bug17030) - assert_equal('match', $1, bug17030) - - regexp = Regexp.new('x') - assert_equal([], @obj.grep(regexp), bug17030) # sanity check - def regexp.===(other) - true - end - assert_equal([1, 2, 3, 1, 2], @obj.grep(regexp), bug17030) - - o = Object.new - def o.to_str - 'hello' - end - assert_same(o, [o].grep(/ll/).first, bug17030) - end - def test_count assert_equal(5, @obj.count) assert_equal(2, @obj.count(1)) assert_equal(3, @obj.count {|x| x % 2 == 1 }) - assert_equal(2, assert_warning(/given block not used/) {@obj.count(1) {|x| x % 2 == 1 }}) + assert_equal(2, @obj.count(1) {|x| x % 2 == 1 }) assert_raise(ArgumentError) { @obj.count(0, 1) } if RUBY_ENGINE == "ruby" @@ -115,7 +95,7 @@ class TestEnumerable < Test::Unit::TestCase assert_equal(1, @obj.find_index {|x| x % 2 == 0 }) assert_equal(nil, @obj.find_index {|x| false }) assert_raise(ArgumentError) { @obj.find_index(0, 1) } - assert_equal(1, assert_warning(/given block not used/) {@obj.find_index(2) {|x| x == 1 }}) + assert_equal(1, @obj.find_index(2) {|x| x == 1 }) end def test_find_all @@ -164,7 +144,8 @@ class TestEnumerable < Test::Unit::TestCase assert_equal([], inf.to_a) end - StubToH = Object.new.tap do |obj| + def test_to_h + obj = Object.new def obj.each(*args) yield(*args) yield [:key, :value] @@ -176,12 +157,6 @@ class TestEnumerable < Test::Unit::TestCase yield kvp end obj.extend Enumerable - obj.freeze - end - - def test_to_h - obj = StubToH - assert_equal({ :hello => :world, :key => :value, @@ -200,33 +175,12 @@ class TestEnumerable < Test::Unit::TestCase assert_equal "element has wrong array length (expected 2, was 1)", e.message end - def test_to_h_block - obj = StubToH - - assert_equal({ - "hello" => "world", - "key" => "value", - "other_key" => "other_value", - "obtained" => "via_to_ary", - }, obj.to_h(:hello, :world) {|k, v| [k.to_s, v.to_s]}) - - e = assert_raise(TypeError) { - obj.to_h {:not_an_array} - } - assert_equal "wrong element type Symbol (expected array)", e.message - - e = assert_raise(ArgumentError) { - obj.to_h {[1]} - } - assert_equal "element has wrong array length (expected 2, was 1)", e.message - end - def test_inject assert_equal(12, @obj.inject {|z, x| z * x }) assert_equal(48, @obj.inject {|z, x| z * 2 + x }) assert_equal(12, @obj.inject(:*)) assert_equal(24, @obj.inject(2) {|z, x| z * x }) - assert_equal(24, assert_warning(/given block not used/) {@obj.inject(2, :*) {|z, x| z * x }}) + assert_equal(24, @obj.inject(2, :*) {|z, x| z * x }) assert_equal(nil, @empty.inject() {9}) end @@ -259,62 +213,6 @@ class TestEnumerable < Test::Unit::TestCase assert_equal(2.0+3.0i, [2.0, 3.0i].inject(:+)) end - def test_inject_op_redefined - assert_separately([], "#{<<~"end;"}\n""end") - k = Class.new do - include Enumerable - def each - yield 1 - yield 2 - yield 3 - end - end - all_assertions_foreach("", *%i[+ * / - %]) do |op| - bug = '[ruby-dev:49510] [Bug#12178] should respect redefinition' - begin - Integer.class_eval do - alias_method :orig, op - define_method(op) do |x| - 0 - end - end - assert_equal(0, k.new.inject(op), bug) - ensure - Integer.class_eval do - undef_method op - alias_method op, :orig - end - end - end; - end - - def test_inject_op_private - assert_separately([], "#{<<~"end;"}\n""end") - k = Class.new do - include Enumerable - def each - yield 1 - yield 2 - yield 3 - end - end - all_assertions_foreach("", *%i[+ * / - %]) do |op| - bug = '[ruby-core:81349] [Bug #13592] should respect visibility' - assert_raise_with_message(NoMethodError, /private method/, bug) do - begin - Integer.class_eval do - private op - end - k.new.inject(op) - ensure - Integer.class_eval do - public op - end - end - end - end; - end - def test_inject_array_op_redefined assert_separately([], "#{<<~"end;"}\n""end") all_assertions_foreach("", *%i[+ * / - %]) do |op| @@ -355,25 +253,6 @@ class TestEnumerable < Test::Unit::TestCase end; end - def test_refine_Enumerable_then_include - assert_separately([], "#{<<~"end;"}\n") - module RefinementBug - refine Enumerable do - def refined_method - :rm - end - end - end - using RefinementBug - - class A - include Enumerable - end - - assert_equal(:rm, [].refined_method) - end; - end - def test_partition assert_equal([[1, 3, 1], [2, 2]], @obj.partition {|x| x % 2 == 1 }) cond = ->(x, i) { x % 2 == 1 } @@ -389,11 +268,6 @@ class TestEnumerable < Test::Unit::TestCase assert_equal(h, @obj.each_with_index.group_by(&cond)) end - def test_tally - h = {1 => 2, 2 => 2, 3 => 1} - assert_equal(h, @obj.tally) - end - def test_first assert_equal(1, @obj.first) assert_equal([1, 2, 3], @obj.first(3)) @@ -436,25 +310,10 @@ class TestEnumerable < Test::Unit::TestCase assert_equal(false, [true, true, false].all?) assert_equal(true, [].all?) assert_equal(true, @empty.all?) - assert_equal(true, @obj.all?(Integer)) + assert_equal(true, @obj.all?(Fixnum)) assert_equal(false, @obj.all?(1..2)) end - def test_all_with_unused_block - assert_in_out_err [], <<-EOS, [], ["-:1: warning: given block not used"] - [1, 2].all?(1) {|x| x == 3 } - EOS - assert_in_out_err [], <<-EOS, [], ["-:1: warning: given block not used"] - (1..2).all?(1) {|x| x == 3 } - EOS - assert_in_out_err [], <<-EOS, [], ["-:1: warning: given block not used"] - 3.times.all?(1) {|x| x == 3 } - EOS - assert_in_out_err [], <<-EOS, [], ["-:1: warning: given block not used"] - {a: 1, b: 2}.all?([:b, 2]) {|x| x == 4 } - EOS - end - def test_any assert_equal(true, @obj.any? {|x| x >= 3 }) assert_equal(false, @obj.any? {|x| x > 3 }) @@ -470,21 +329,6 @@ class TestEnumerable < Test::Unit::TestCase assert_equal(true, {a: 1, b: 2}.any?(->(kv) { kv == [:b, 2] })) end - def test_any_with_unused_block - assert_in_out_err [], <<-EOS, [], ["-:1: warning: given block not used"] - [1, 23].any?(1) {|x| x == 1 } - EOS - assert_in_out_err [], <<-EOS, [], ["-:1: warning: given block not used"] - (1..2).any?(34) {|x| x == 2 } - EOS - assert_in_out_err [], <<-EOS, [], ["-:1: warning: given block not used"] - 3.times.any?(1) {|x| x == 3 } - EOS - assert_in_out_err [], <<-EOS, [], ["-:1: warning: given block not used"] - {a: 1, b: 2}.any?([:b, 2]) {|x| x == 4 } - EOS - end - def test_one assert(@obj.one? {|x| x == 3 }) assert(!(@obj.one? {|x| x == 1 })) @@ -504,21 +348,6 @@ class TestEnumerable < Test::Unit::TestCase assert([ nil, true, 99 ].one?(Integer)) end - def test_one_with_unused_block - assert_in_out_err [], <<-EOS, [], ["-:1: warning: given block not used"] - [1, 2].one?(1) {|x| x == 3 } - EOS - assert_in_out_err [], <<-EOS, [], ["-:1: warning: given block not used"] - (1..2).one?(1) {|x| x == 3 } - EOS - assert_in_out_err [], <<-EOS, [], ["-:1: warning: given block not used"] - 3.times.one?(1) {|x| x == 3 } - EOS - assert_in_out_err [], <<-EOS, [], ["-:1: warning: given block not used"] - {a: 1, b: 2}.one?([:b, 2]) {|x| x == 4 } - EOS - end - def test_none assert(@obj.none? {|x| x == 4 }) assert(!(@obj.none? {|x| x == 1 })) @@ -536,21 +365,6 @@ class TestEnumerable < Test::Unit::TestCase assert(@empty.none?) end - def test_none_with_unused_block - assert_in_out_err [], <<-EOS, [], ["-:1: warning: given block not used"] - [1, 2].none?(1) {|x| x == 3 } - EOS - assert_in_out_err [], <<-EOS, [], ["-:1: warning: given block not used"] - (1..2).none?(1) {|x| x == 3 } - EOS - assert_in_out_err [], <<-EOS, [], ["-:1: warning: given block not used"] - 3.times.none?(1) {|x| x == 3 } - EOS - assert_in_out_err [], <<-EOS, [], ["-:1: warning: given block not used"] - {a: 1, b: 2}.none?([:b, 2]) {|x| x == 4 } - EOS - end - def test_min assert_equal(1, @obj.min) assert_equal(3, @obj.min {|a,b| b <=> a }) @@ -830,19 +644,6 @@ class TestEnumerable < Test::Unit::TestCase assert_equal([2,1,3,2,1], @obj.reverse_each.to_a) end - def test_reverse_each_memory_corruption - bug16354 = '[ruby-dev:50867]' - assert_normal_exit %q{ - size = 1000 - (0...size).reverse_each do |i| - i.inspect - ObjectSpace.each_object(Array) do |a| - a.clear if a.length == size - end - end - }, bug16354 - end - def test_chunk e = [].chunk {|elt| true } assert_equal([], e.to_a) @@ -1228,29 +1029,4 @@ class TestEnumerable < Test::Unit::TestCase assert_equal([1, 2, 3, 4, 5, 10], (1..100).uniq{|x| (x**2) % 10 }.first(6)) assert_equal([1, [1, 2]], Foo.new.to_enum.uniq) end - - def test_transient_heap_sort_by - klass = Class.new do - include Comparable - attr_reader :i - def initialize e - @i = e - end - def <=> other - GC.start - i <=> other.i - end - end - assert_equal [1, 2, 3, 4, 5], (1..5).sort_by{|e| klass.new e} - end - - def test_filter_map - @obj = (1..8).to_a - assert_equal([4, 8, 12, 16], @obj.filter_map { |i| i * 2 if i.even? }) - assert_equal([2, 4, 6, 8, 10, 12, 14, 16], @obj.filter_map { |i| i * 2 }) - assert_equal([0, 0, 0, 0, 0, 0, 0, 0], @obj.filter_map { 0 }) - assert_equal([], @obj.filter_map { false }) - assert_equal([], @obj.filter_map { nil }) - assert_instance_of(Enumerator, @obj.filter_map) - end end diff --git a/test/ruby/test_enumerator.rb b/test/ruby/test_enumerator.rb index eb15d4b616..66a45cc14e 100644 --- a/test/ruby/test_enumerator.rb +++ b/test/ruby/test_enumerator.rb @@ -69,16 +69,17 @@ class TestEnumerator < Test::Unit::TestCase def test_initialize assert_equal([1, 2, 3], @obj.to_enum(:foo, 1, 2, 3).to_a) - assert_raise(ArgumentError) { - Enumerator.new(@obj, :foo, 1, 2, 3) - } + _, err = capture_io do + assert_equal([1, 2, 3], Enumerator.new(@obj, :foo, 1, 2, 3).to_a) + end + assert_match 'Enumerator.new without a block is deprecated', err assert_equal([1, 2, 3], Enumerator.new { |y| i = 0; loop { y << (i += 1) } }.take(3)) assert_raise(ArgumentError) { Enumerator.new } enum = @obj.to_enum assert_raise(NoMethodError) { enum.each {} } enum.freeze - assert_raise(ArgumentError) { + assert_raise(FrozenError) { capture_io do # warning: Enumerator.new without a block is deprecated; use Object#to_enum enum.__send__(:initialize, @obj, :foo) @@ -112,11 +113,6 @@ class TestEnumerator < Test::Unit::TestCase assert_equal([[1,2,3],[4,5,6],[7,8,9],[10]], (1..10).each_slice(3).to_a) end - def test_each_slice_size - assert_equal(4, (1..10).each_slice(3).size) - assert_equal(Float::INFINITY, 1.step.each_slice(3).size) - end - def test_cons a = [[1,2,3], [2,3,4], [3,4,5], [4,5,6], [5,6,7], [6,7,8], [7,8,9], [8,9,10]] assert_equal(a, (1..10).each_cons(3).to_a) @@ -305,11 +301,8 @@ class TestEnumerator < Test::Unit::TestCase yield end ary = [] - e = o.to_enum { 1 } - assert_equal(1, e.size) - e_arg = e.each(ary) - assert_equal(nil, e_arg.size) - e_arg.next + e = o.to_enum.each(ary) + e.next assert_equal([1], ary) end @@ -411,12 +404,6 @@ class TestEnumerator < Test::Unit::TestCase e = (0..10).each_cons(2) assert_equal("#<Enumerator: 0..10:each_cons(2)>", e.inspect) - e = (0..10).each_with_object({}) - assert_equal("#<Enumerator: 0..10:each_with_object({})>", e.inspect) - - e = (0..10).each_with_object(a: 1) - assert_equal("#<Enumerator: 0..10:each_with_object(a: 1)>", e.inspect) - e = Enumerator.new {|y| y.yield; 10 } assert_match(/\A#<Enumerator: .*:each>/, e.inspect) @@ -489,29 +476,8 @@ class TestEnumerator < Test::Unit::TestCase assert_equal([1], y.yield(1)) assert_equal([1, 2], y.yield(2)) assert_equal([1, 2, 3], y.yield(3)) - assert_equal([1, 2, 3, 4], y.yield(4, 5)) - - a = [] - y = Enumerator::Yielder.new {|*x| a.concat(x) } - assert_equal([1], y.yield(1)) - assert_equal([1, 2, 3], y.yield(2, 3)) assert_raise(LocalJumpError) { Enumerator::Yielder.new } - - # to_proc (explicit) - a = [] - y = Enumerator::Yielder.new {|x| a << x } - b = y.to_proc - assert_kind_of(Proc, b) - assert_equal([1], b.call(1)) - assert_equal([1], a) - - # to_proc (implicit) - e = Enumerator.new { |y| - assert_kind_of(Enumerator::Yielder, y) - [1, 2, 3].each(&y) - } - assert_equal([1, 2, 3], e.to_a) end def test_size @@ -539,14 +505,14 @@ class TestEnumerator < Test::Unit::TestCase def test_size_for_enum_created_from_array arr = %w[hello world] %i[each each_with_index reverse_each sort_by! sort_by map map! - keep_if reject! reject select! select filter! filter delete_if].each do |method| + keep_if reject! reject select! select delete_if].each do |method| assert_equal arr.size, arr.send(method).size end end def test_size_for_enum_created_from_enumerable %i[find_all reject map flat_map partition group_by sort_by min_by max_by - minmax_by each_with_index reverse_each each_entry filter_map].each do |method| + minmax_by each_with_index reverse_each each_entry].each do |method| assert_equal nil, @obj.send(method).size assert_equal 42, @sized.send(method).size end @@ -556,7 +522,7 @@ class TestEnumerator < Test::Unit::TestCase def test_size_for_enum_created_from_hash h = {a: 1, b: 2, c: 3} - methods = %i[delete_if reject reject! select select! filter filter! keep_if each each_key each_pair] + methods = %i[delete_if reject reject! select select! keep_if each each_key each_pair] enums = methods.map {|method| h.send(method)} s = enums.group_by(&:size) assert_equal([3], s.keys, ->{s.reject!{|k| k==3}.inspect}) @@ -566,7 +532,7 @@ class TestEnumerator < Test::Unit::TestCase end def test_size_for_enum_created_from_env - %i[each_pair reject! delete_if select select! filter filter! keep_if].each do |method| + %i[each_pair reject! delete_if select select! keep_if].each do |method| assert_equal ENV.size, ENV.send(method).size end end @@ -666,7 +632,7 @@ class TestEnumerator < Test::Unit::TestCase assert_equal 4, (1..10).step(3).size assert_equal 3, (1...10).step(3).size assert_equal Float::INFINITY, (42..Float::INFINITY).step(2).size - assert_equal 0, (1..10).step(-2).size + assert_raise(ArgumentError){ (1..10).step(-2).size } end def test_size_for_downup_to @@ -695,188 +661,5 @@ class TestEnumerator < Test::Unit::TestCase assert_equal([0, 1], u.force) assert_equal([0, 1], u.force) end - - def test_enum_chain_and_plus - r = 1..5 - - e1 = r.chain() - assert_kind_of(Enumerator::Chain, e1) - assert_equal(5, e1.size) - ary = [] - e1.each { |x| ary << x } - assert_equal([1, 2, 3, 4, 5], ary) - - e2 = r.chain([6, 7, 8]) - assert_kind_of(Enumerator::Chain, e2) - assert_equal(8, e2.size) - ary = [] - e2.each { |x| ary << x } - assert_equal([1, 2, 3, 4, 5, 6, 7, 8], ary) - - e3 = r.chain([6, 7], 8.step) - assert_kind_of(Enumerator::Chain, e3) - assert_equal(Float::INFINITY, e3.size) - ary = [] - e3.take(10).each { |x| ary << x } - assert_equal([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], ary) - - # `a + b + c` should not return `Enumerator::Chain.new(a, b, c)` - # because it is expected that `(a + b).each` be called. - e4 = e2.dup - class << e4 - attr_reader :each_is_called - def each - super - @each_is_called = true - end - end - e5 = e4 + 9.step - assert_kind_of(Enumerator::Chain, e5) - assert_equal(Float::INFINITY, e5.size) - ary = [] - e5.take(10).each { |x| ary << x } - assert_equal([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], ary) - assert_equal(true, e4.each_is_called) - end - - def test_chained_enums - a = (1..5).each - - e0 = Enumerator::Chain.new() - assert_kind_of(Enumerator::Chain, e0) - assert_equal(0, e0.size) - ary = [] - e0.each { |x| ary << x } - assert_equal([], ary) - - e1 = Enumerator::Chain.new(a) - assert_kind_of(Enumerator::Chain, e1) - assert_equal(5, e1.size) - ary = [] - e1.each { |x| ary << x } - assert_equal([1, 2, 3, 4, 5], ary) - - e2 = Enumerator::Chain.new(a, [6, 7, 8]) - assert_kind_of(Enumerator::Chain, e2) - assert_equal(8, e2.size) - ary = [] - e2.each { |x| ary << x } - assert_equal([1, 2, 3, 4, 5, 6, 7, 8], ary) - - e3 = Enumerator::Chain.new(a, [6, 7], 8.step) - assert_kind_of(Enumerator::Chain, e3) - assert_equal(Float::INFINITY, e3.size) - ary = [] - e3.take(10).each { |x| ary << x } - assert_equal([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], ary) - - e4 = Enumerator::Chain.new(a, Enumerator.new { |y| y << 6 << 7 << 8 }) - assert_kind_of(Enumerator::Chain, e4) - assert_equal(nil, e4.size) - ary = [] - e4.each { |x| ary << x } - assert_equal([1, 2, 3, 4, 5, 6, 7, 8], ary) - - e5 = Enumerator::Chain.new(e1, e2) - assert_kind_of(Enumerator::Chain, e5) - assert_equal(13, e5.size) - ary = [] - e5.each { |x| ary << x } - assert_equal([1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 6, 7, 8], ary) - - rewound = [] - e1.define_singleton_method(:rewind) { rewound << object_id } - e2.define_singleton_method(:rewind) { rewound << object_id } - e5.rewind - assert_equal(rewound, [e2.object_id, e1.object_id]) - - rewound = [] - a = [1] - e6 = Enumerator::Chain.new(a) - a.define_singleton_method(:rewind) { rewound << object_id } - e6.rewind - assert_equal(rewound, []) - - assert_equal( - '#<Enumerator::Chain: [' + - '#<Enumerator::Chain: [' + - '#<Enumerator: 1..5:each>' + - ']>, ' + - '#<Enumerator::Chain: [' + - '#<Enumerator: 1..5:each>, ' + - '[6, 7, 8]' + - ']>' + - ']>', - e5.inspect - ) - end - - def test_produce - assert_raise(ArgumentError) { Enumerator.produce } - - # Without initial object - passed_args = [] - enum = Enumerator.produce { |obj| passed_args << obj; (obj || 0).succ } - assert_instance_of(Enumerator, enum) - assert_equal Float::INFINITY, enum.size - assert_equal [1, 2, 3], enum.take(3) - assert_equal [nil, 1, 2], passed_args - - # With initial object - passed_args = [] - enum = Enumerator.produce(1) { |obj| passed_args << obj; obj.succ } - assert_instance_of(Enumerator, enum) - assert_equal Float::INFINITY, enum.size - assert_equal [1, 2, 3], enum.take(3) - assert_equal [1, 2], passed_args - - # With initial keyword arguments - passed_args = [] - enum = Enumerator.produce(a: 1, b: 1) { |obj| passed_args << obj; obj.shift if obj.respond_to?(:shift)} - assert_instance_of(Enumerator, enum) - assert_equal Float::INFINITY, enum.size - assert_equal [{b: 1}, [1], :a, nil], enum.take(4) - assert_equal [{b: 1}, [1], :a], passed_args - - # Raising StopIteration - words = "The quick brown fox jumps over the lazy dog.".scan(/\w+/) - enum = Enumerator.produce { words.shift or raise StopIteration } - assert_equal Float::INFINITY, enum.size - assert_instance_of(Enumerator, enum) - assert_equal %w[The quick brown fox jumps over the lazy dog], enum.to_a - - # Raising StopIteration - object = [[[["abc", "def"], "ghi", "jkl"], "mno", "pqr"], "stuv", "wxyz"] - enum = Enumerator.produce(object) { |obj| - obj.respond_to?(:first) or raise StopIteration - obj.first - } - assert_equal Float::INFINITY, enum.size - assert_instance_of(Enumerator, enum) - assert_nothing_raised { - assert_equal [ - [[[["abc", "def"], "ghi", "jkl"], "mno", "pqr"], "stuv", "wxyz"], - [[["abc", "def"], "ghi", "jkl"], "mno", "pqr"], - [["abc", "def"], "ghi", "jkl"], - ["abc", "def"], - "abc", - ], enum.to_a - } - end - - def test_chain_each_lambda - c = Class.new do - include Enumerable - attr_reader :is_lambda - def each(&block) - return to_enum unless block - @is_lambda = block.lambda? - end - end - e = c.new - e.chain.each{} - assert_equal(false, e.is_lambda) - e.chain.each(&->{}) - assert_equal(true, e.is_lambda) - end end + diff --git a/test/ruby/test_env.rb b/test/ruby/test_env.rb index 6779c94dde..ffed94efa6 100644 --- a/test/ruby/test_env.rb +++ b/test/ruby/test_env.rb @@ -22,6 +22,7 @@ class TestEnv < Test::Unit::TestCase def setup @verbose = $VERBOSE + $VERBOSE = nil @backup = ENV.to_hash ENV.delete('test') ENV.delete('TEST') @@ -45,6 +46,7 @@ class TestEnv < Test::Unit::TestCase end ENV['TEST'] = 'bar' assert_equal('bar', ENV['TEST']) + assert_predicate(ENV['TEST'], :tainted?) if IGNORE_CASE assert_equal('bar', ENV['test']) else @@ -83,6 +85,7 @@ class TestEnv < Test::Unit::TestCase ENV['test'] = val[0...-1] assert_nil(ENV.key(val)) + assert_nil(ENV.index(val)) assert_nil(ENV.key(val.upcase)) ENV['test'] = val if IGNORE_CASE @@ -104,13 +107,13 @@ class TestEnv < Test::Unit::TestCase assert_invalid_env {|v| ENV.delete(v)} assert_nil(ENV.delete("TEST")) assert_nothing_raised { ENV.delete(PATH_ENV) } - assert_equal("NO TEST", ENV.delete("TEST") {|name| "NO "+name}) end def test_getenv assert_invalid_env {|v| ENV[v]} ENV[PATH_ENV] = "" assert_equal("", ENV[PATH_ENV]) + assert_predicate(ENV[PATH_ENV], :tainted?) assert_nil(ENV[""]) end @@ -119,7 +122,7 @@ class TestEnv < Test::Unit::TestCase assert_equal("foo", ENV.fetch("test")) ENV.delete("test") feature8649 = '[ruby-core:56062] [Feature #8649]' - e = assert_raise_with_message(KeyError, /key not found: "test"/, feature8649) do + e = assert_raise_with_message(KeyError, 'key not found: "test"', feature8649) do ENV.fetch("test") end assert_same(ENV, e.receiver) @@ -133,6 +136,7 @@ class TestEnv < Test::Unit::TestCase assert_nothing_raised { ENV.fetch(PATH_ENV, "foo") } ENV[PATH_ENV] = "" assert_equal("", ENV.fetch(PATH_ENV)) + assert_predicate(ENV.fetch(PATH_ENV), :tainted?) end def test_aset @@ -150,6 +154,9 @@ class TestEnv < Test::Unit::TestCase assert_equal("test", ENV["foo"]) rescue Errno::EINVAL end + + ENV[PATH_ENV] = "/tmp/".taint + assert_equal("/tmp/", ENV[PATH_ENV]) end def test_keys @@ -215,18 +222,6 @@ class TestEnv < Test::Unit::TestCase assert_nil(ENV.select! {|k, v| IGNORE_CASE ? k.upcase != "TEST" : k != "test" }) end - def test_filter_bang - h1 = {} - ENV.each_pair {|k, v| h1[k] = v } - ENV["test"] = "foo" - ENV.filter! {|k, v| IGNORE_CASE ? k.upcase != "TEST" : k != "test" } - h2 = {} - ENV.each_pair {|k, v| h2[k] = v } - assert_equal(h1, h2) - - assert_nil(ENV.filter! {|k, v| IGNORE_CASE ? k.upcase != "TEST" : k != "test" }) - end - def test_keep_if h1 = {} ENV.each_pair {|k, v| h1[k] = v } @@ -259,43 +254,6 @@ class TestEnv < Test::Unit::TestCase end end - def test_filter - ENV["test"] = "foo" - h = ENV.filter {|k| IGNORE_CASE ? k.upcase == "TEST" : k == "test" } - assert_equal(1, h.size) - k = h.keys.first - v = h.values.first - if IGNORE_CASE - assert_equal("TEST", k.upcase) - assert_equal("FOO", v.upcase) - else - assert_equal("test", k) - assert_equal("foo", v) - end - end - - def test_slice - ENV.clear - ENV["foo"] = "bar" - ENV["baz"] = "qux" - ENV["bar"] = "rab" - assert_equal({}, ENV.slice()) - assert_equal({}, ENV.slice("")) - assert_equal({}, ENV.slice("unknown")) - assert_equal({"foo"=>"bar", "baz"=>"qux"}, ENV.slice("foo", "baz")) - end - - def test_except - ENV.clear - ENV["foo"] = "bar" - ENV["baz"] = "qux" - ENV["bar"] = "rab" - assert_equal({"bar"=>"rab", "baz"=>"qux", "foo"=>"bar"}, ENV.except()) - assert_equal({"bar"=>"rab", "baz"=>"qux", "foo"=>"bar"}, ENV.except("")) - assert_equal({"bar"=>"rab", "baz"=>"qux", "foo"=>"bar"}, ENV.except("unknown")) - assert_equal({"bar"=>"rab"}, ENV.except("foo", "baz")) - end - def test_clear ENV.clear assert_equal(0, ENV.size) @@ -368,8 +326,8 @@ class TestEnv < Test::Unit::TestCase assert_equal("foo", v) end assert_invalid_env {|var| ENV.assoc(var)} - encoding = /mswin|mingw/ =~ RUBY_PLATFORM ? Encoding::UTF_8 : Encoding.find("locale") - assert_equal(encoding, v.encoding) + assert_predicate(v, :tainted?) + assert_equal(Encoding.find("locale"), v.encoding) end def test_has_value2 @@ -403,8 +361,6 @@ class TestEnv < Test::Unit::TestCase def test_to_h assert_equal(ENV.to_hash, ENV.to_h) - assert_equal(ENV.map {|k, v| ["$#{k}", v.size]}.to_h, - ENV.to_h {|k, v| ["$#{k}", v.size]}) end def test_reject @@ -417,8 +373,8 @@ class TestEnv < Test::Unit::TestCase def check(as, bs) if IGNORE_CASE - as = as.map {|k, v| [k.upcase, v] } - bs = bs.map {|k, v| [k.upcase, v] } + as = as.map {|xs| xs.map {|x| x.upcase } } + bs = bs.map {|xs| xs.map {|x| x.upcase } } end assert_equal(as.sort, bs.sort) end @@ -444,8 +400,6 @@ class TestEnv < Test::Unit::TestCase ENV["foo"] = "xxx" ENV.replace({"foo"=>"bar", "baz"=>"qux"}) check(ENV.to_hash.to_a, [%w(foo bar), %w(baz qux)]) - ENV.replace({"Foo"=>"Bar", "Baz"=>"Qux"}) - check(ENV.to_hash.to_a, [%w(Foo Bar), %w(Baz Qux)]) end def test_update @@ -458,14 +412,14 @@ class TestEnv < Test::Unit::TestCase ENV.clear ENV["foo"] = "bar" ENV["baz"] = "qux" - ENV.update({"baz"=>"quux","a"=>"b"}) {|k, v1, v2| k + "_" + v1 + "_" + v2 } + ENV.update({"baz"=>"quux","a"=>"b"}) {|k, v1, v2| v1 ? k + "_" + v1 + "_" + v2 : v2 } check(ENV.to_hash.to_a, [%w(foo bar), %w(baz baz_qux_quux), %w(a b)]) end def test_huge_value huge_value = "bar" * 40960 ENV["foo"] = "bar" - if /mswin/ =~ RUBY_PLATFORM + if /mswin|mingw/ =~ RUBY_PLATFORM assert_raise(Errno::EINVAL) { ENV["foo"] = huge_value } assert_equal("bar", ENV["foo"]) else @@ -475,10 +429,6 @@ class TestEnv < Test::Unit::TestCase end if /mswin|mingw/ =~ RUBY_PLATFORM - def windows_version - @windows_version ||= %x[ver][/Version (\d+)/, 1].to_i - end - def test_win32_blocksize keys = [] len = 32767 - ENV.to_a.flatten.inject(1) {|r,e| r + e.bytesize + 1} @@ -488,24 +438,14 @@ class TestEnv < Test::Unit::TestCase keys << key ENV[key] = val end - if windows_version < 6 - 1.upto(12) {|i| - assert_raise(Errno::EINVAL) { ENV[key] = val } - } - else - 1.upto(12) {|i| - assert_nothing_raised(Errno::EINVAL) { ENV[key] = val } - } - end + 1.upto(12) {|i| + assert_raise(Errno::EINVAL) { ENV[key] = val } + } ensure keys.each {|k| ENV.delete(k)} end end - def test_frozen_env - assert_raise(TypeError) { ENV.freeze } - end - def test_frozen ENV[PATH_ENV] = "/" ENV.each do |k, v| @@ -579,13 +519,15 @@ class TestEnv < Test::Unit::TestCase end; end - def test_utf8 - text = "testing \u{e5 e1 e2 e4 e3 101 3042}" - test = ENV["test"] - ENV["test"] = text - assert_equal text, ENV["test"] - ensure - ENV["test"] = test + if Encoding.find("locale") == Encoding::UTF_8 + def test_utf8 + text = "testing \u{e5 e1 e2 e4 e3 101 3042}" + test = ENV["test"] + ENV["test"] = text + assert_equal text, ENV["test"] + ensure + ENV["test"] = test + end end end end diff --git a/test/ruby/test_eval.rb b/test/ruby/test_eval.rb index bf551c6845..0bc0390d64 100644 --- a/test/ruby/test_eval.rb +++ b/test/ruby/test_eval.rb @@ -320,6 +320,20 @@ class TestEval < Test::Unit::TestCase end assert(!bad) + if false + # Ruby 2.0 doesn't see Proc as Binding + x = proc{} + eval "i4 = 1", x + assert_equal(1, eval("i4", x)) + x = proc{proc{}}.call + eval "i4 = 22", x + assert_equal(22, eval("i4", x)) + t = [] + x = proc{proc{}}.call + eval "(0..9).each{|i5| t[i5] = proc{i5*2}}", x + assert_equal(8, t[4].call) + end + x = binding eval "i = 1", x assert_equal(1, eval("i", x)) @@ -345,11 +359,27 @@ class TestEval < Test::Unit::TestCase # assert_equal(1, eval("foo11")) assert_equal(eval("foo22"), eval("foo22", p)) assert_equal(55, eval("foo22")) - assert_equal(55, foo22) }.call - self.class.class_eval do - remove_const :EvTest + if false + # Ruby 2.0 doesn't see Proc as Binding + p1 = proc{i7 = 0; proc{i7}}.call + assert_equal(0, p1.call) + eval "i7=5", p1 + assert_equal(5, p1.call) + assert(!defined?(i7)) + end + + if false + # Ruby 2.0 doesn't see Proc as Binding + p1 = proc{i7 = 0; proc{i7}}.call + i7 = nil + assert_equal(0, p1.call) + eval "i7=1", p1 + assert_equal(1, p1.call) + eval "i7=5", p1 + assert_equal(5, p1.call) + assert_nil(i7) end end @@ -473,15 +503,6 @@ class TestEval < Test::Unit::TestCase assert_same a, b end - def test_eval_location_binding - assert_equal(['(eval)', 1], eval("[__FILE__, __LINE__]", nil)) - assert_equal(['(eval)', 1], eval("[__FILE__, __LINE__]", binding)) - assert_equal(['foo', 1], eval("[__FILE__, __LINE__]", nil, 'foo')) - assert_equal(['foo', 1], eval("[__FILE__, __LINE__]", binding, 'foo')) - assert_equal(['foo', 2], eval("[__FILE__, __LINE__]", nil, 'foo', 2)) - assert_equal(['foo', 2], eval("[__FILE__, __LINE__]", binding, 'foo', 2)) - end - def test_fstring_instance_eval bug = "[ruby-core:78116] [Bug #12930]".freeze assert_same bug, (bug.instance_eval {self}) @@ -505,17 +526,6 @@ class TestEval < Test::Unit::TestCase }, '[Bug #10368]' end - def test_gced_eval_location - Dir.mktmpdir do |d| - File.write("#{d}/2.rb", "") - File.write("#{d}/1.rb", "require_relative '2'\n""__FILE__\n") - file = "1.rb" - path = File.expand_path(file, d) - assert_equal(path, eval(File.read(path), nil, File.expand_path(file, d))) - assert_equal(path, eval(File.read(path), nil, File.expand_path(file, d))) - end - end - def orphan_proc proc {eval("return :ng")} end diff --git a/test/ruby/test_exception.rb b/test/ruby/test_exception.rb index 087bcda5ac..605248aebd 100644 --- a/test/ruby/test_exception.rb +++ b/test/ruby/test_exception.rb @@ -352,7 +352,6 @@ class TestException < Test::Unit::TestCase end def test_thread_signal_location - skip _, stderr, _ = EnvUtil.invoke_ruby(%w"--disable-gems -d", <<-RUBY, false, true) Thread.start do Thread.current.report_on_exception = false @@ -438,6 +437,16 @@ end.join assert_not_send([e, :success?], "abort means failure") end + def test_nomethoderror + bug3237 = '[ruby-core:29948]' + str = "\u2600" + id = :"\u2604" + msg = "undefined method `#{id}' for \"#{str}\":String" + assert_raise_with_message(NoMethodError, msg, bug3237) do + str.__send__(id) + end + end + def test_errno assert_equal(Encoding.find("locale"), Errno::EINVAL.new.message.encoding) end @@ -478,15 +487,20 @@ end.join end def test_exception_in_name_error_to_str - assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") bug5575 = '[ruby-core:41612]' - begin; + Tempfile.create(["test_exception_in_name_error_to_str", ".rb"]) do |t| + t.puts <<-EOC begin BasicObject.new.inspect rescue - assert_nothing_raised(NameError, bug5575) {$!.inspect} + $!.inspect end - end; + EOC + t.close + assert_nothing_raised(NameError, bug5575) do + load(t.path) + end + end end def test_equal @@ -496,28 +510,19 @@ end.join end def test_exception_in_exception_equal - assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") bug5865 = '[ruby-core:41979]' - begin; + Tempfile.create(["test_exception_in_exception_equal", ".rb"]) do |t| + t.puts <<-EOC o = Object.new def o.exception(arg) end + _ = RuntimeError.new("a") == o + EOC + t.close assert_nothing_raised(ArgumentError, bug5865) do - RuntimeError.new("a") == o + load(t.path) end - end; - end - - def test_backtrace_by_exception - begin - line = __LINE__; raise "foo" - rescue => e end - e2 = e.exception("bar") - assert_not_equal(e.message, e2.message) - assert_equal(e.backtrace, e2.backtrace) - loc = e2.backtrace_locations[0] - assert_equal([__FILE__, line], [loc.path, loc.lineno]) end Bug4438 = '[ruby-core:35364]' @@ -540,6 +545,28 @@ end.join end end + def test_to_s_taintness_propagation + for exc in [Exception, NameError] + m = "abcdefg" + e = exc.new(m) + e.taint + s = e.to_s + assert_equal(false, m.tainted?, + "#{exc}#to_s should not propagate taintness") + assert_equal(false, s.tainted?, + "#{exc}#to_s should not propagate taintness") + end + + o = Object.new + def o.to_str + "foo" + end + o.taint + e = NameError.new(o) + s = e.to_s + assert_equal(false, s.tainted?) + end + def m m(&->{return 0}) 42 @@ -672,11 +699,7 @@ end.join end def test_cause_at_end - errs = [ - /-: unexpected return\n/, - /.*undefined local variable or method `n'.*\n/, - ] - assert_in_out_err([], <<-'end;', [], errs) + assert_in_out_err([], <<-'end;', [], [/-: unexpected return\n/, /.*undefined local variable or method `n'.*\n/]) END{n}; END{return} end; end @@ -780,7 +803,7 @@ end.join e = assert_raise(exc, bug) {raise exc, "foo" => "bar", foo: "bar"} assert_equal({"foo" => "bar", foo: "bar"}, e.arg, bug) - e = assert_raise(exc, bug) {raise exc, "foo" => "bar", foo: "bar", cause: RuntimeError.new("zzz")} + e = assert_raise(exc, bug) {raise exc, "foo" => "bar", foo: "bar", cause: "zzz"} assert_equal({"foo" => "bar", foo: "bar"}, e.arg, bug) e = assert_raise(exc, bug) {raise exc, {}} @@ -814,28 +837,101 @@ end.join } end - def test_cause_exception_in_cause_message - assert_in_out_err([], "#{<<~"begin;"}\n#{<<~'end;'}") do |outs, errs, status| - begin; - exc = Class.new(StandardError) do - def initialize(obj, cnt) - super(obj) - @errcnt = cnt - end - def to_s - return super if @errcnt <= 0 - @errcnt -= 1 - raise "xxx" - end - end.new("ok", 10) - raise "[Bug #17033]", cause: exc - end; - assert_equal(1, errs.count {|m| m.include?("[Bug #17033]")}, proc {errs.pretty_inspect}) + def test_anonymous_message + assert_in_out_err([], "raise Class.new(RuntimeError), 'foo'", [], /foo\n/) + end + + PrettyObject = + Class.new(BasicObject) do + alias object_id __id__ + def pretty_inspect; "`obj'"; end + alias inspect pretty_inspect end + + def test_name_error_info_const + obj = PrettyObject.new + + e = assert_raise(NameError) { + obj.instance_eval("Object") + } + assert_equal(:Object, e.name) + + e = assert_raise(NameError) { + BasicObject::X + } + assert_same(BasicObject, e.receiver) + assert_equal(:X, e.name) end - def test_anonymous_message - assert_in_out_err([], "raise Class.new(RuntimeError), 'foo'", [], /foo\n/) + def test_name_error_info_method + obj = PrettyObject.new + + e = assert_raise(NameError) { + obj.instance_eval {foo} + } + assert_equal(:foo, e.name) + assert_same(obj, e.receiver) + + e = assert_raise(NoMethodError) { + obj.foo(1, 2) + } + assert_equal(:foo, e.name) + assert_equal([1, 2], e.args) + assert_same(obj, e.receiver) + assert_not_predicate(e, :private_call?) + + e = assert_raise(NoMethodError) { + obj.instance_eval {foo(1, 2)} + } + assert_equal(:foo, e.name) + assert_equal([1, 2], e.args) + assert_same(obj, e.receiver) + assert_predicate(e, :private_call?) + end + + def test_name_error_info_local_variables + obj = PrettyObject.new + def obj.test(a, b=nil, *c, &d) + e = a + 1.times {|f| g = foo; g} + e + end + + e = assert_raise(NameError) { + obj.test(3) + } + assert_equal(:foo, e.name) + assert_same(obj, e.receiver) + assert_equal(%i[a b c d e f g], e.local_variables.sort) + end + + def test_name_error_info_method_missing + obj = PrettyObject.new + def obj.method_missing(*) + super + end + + e = assert_raise(NoMethodError) { + obj.foo(1, 2) + } + assert_equal(:foo, e.name) + assert_equal([1, 2], e.args) + assert_same(obj, e.receiver) + assert_not_predicate(e, :private_call?) + + e = assert_raise(NoMethodError) { + obj.instance_eval {foo(1, 2)} + } + assert_equal(:foo, e.name) + assert_equal([1, 2], e.args) + assert_same(obj, e.receiver) + assert_predicate(e, :private_call?) + end + + def test_name_error_info_parent_iseq_mark + assert_separately(['-', File.join(__dir__, 'bug-11928.rb')], <<-'end;') + -> {require ARGV[0]}.call + end; end def test_output_string_encoding @@ -863,43 +959,6 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status| end; end - def assert_null_char(src, *args, **opts) - begin - eval(src) - rescue => e - end - assert_not_nil(e) - assert_include(e.message, "\0") - assert_in_out_err([], src, [], [], *args, **opts) do |_, err,| - err.each do |e| - assert_not_include(e, "\0") - end - end - e - end - - def test_control_in_message - bug7574 = '[ruby-dev:46749]' - assert_null_char("#{<<~"begin;"}\n#{<<~'end;'}", bug7574) - begin; - Object.const_defined?("String\0") - end; - assert_null_char("#{<<~"begin;"}\n#{<<~'end;'}", bug7574) - begin; - Object.const_get("String\0") - end; - end - - def test_encoding_in_message - name = "\u{e9}t\u{e9}" - e = EnvUtil.with_default_external("US-ASCII") do - assert_raise(NameError) do - Object.const_get(name) - end - end - assert_include(e.message, name) - end - def test_method_missing_reason_clear bug10969 = '[ruby-core:68515] [Bug #10969]' a = Class.new {def method_missing(*) super end}.new @@ -915,37 +974,25 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status| end end - def capture_warning_warn(category: false) + def capture_warning_warn verbose = $VERBOSE - deprecated = Warning[:deprecated] - experimental = Warning[:experimental] warning = [] ::Warning.class_eval do alias_method :warn2, :warn remove_method :warn - if category - define_method(:warn) do |str, category: nil| - warning << [str, category] - end - else - define_method(:warn) do |str| - warning << str - end + define_method(:warn) do |str| + warning << str end end $VERBOSE = true - Warning[:deprecated] = true - Warning[:experimental] = true yield return warning ensure $VERBOSE = verbose - Warning[:deprecated] = deprecated - Warning[:experimental] = experimental ::Warning.class_eval do remove_method :warn @@ -955,55 +1002,19 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status| end def test_warning_warn - warning = capture_warning_warn {$asdfasdsda_test_warning_warn} - assert_match(/global variable `\$asdfasdsda_test_warning_warn' not initialized/, warning[0]) + warning = capture_warning_warn {@a} + assert_match(/instance variable @a not initialized/, warning[0]) assert_equal(["a\nz\n"], capture_warning_warn {warn "a\n", "z"}) assert_equal([], capture_warning_warn {warn}) assert_equal(["\n"], capture_warning_warn {warn ""}) end - def test_warn_deprecated_backwards_compatibility_category - warning = capture_warning_warn { Dir.exists?("non-existent") } - - assert_match(/deprecated/, warning[0]) - end - - def test_warn_deprecated_category - warning = capture_warning_warn(category: true) { Dir.exists?("non-existent") } - - assert_equal :deprecated, warning[0][1] - end - - def test_warn_deprecated_to_remove_backwards_compatibility_category - warning = capture_warning_warn { Object.new.tainted? } - - assert_match(/deprecated/, warning[0]) - end - - def test_warn_deprecated_to_remove_category - warning = capture_warning_warn(category: true) { Object.new.tainted? } - - assert_equal :deprecated, warning[0][1] - end - def test_kernel_warn_uplevel warning = capture_warning_warn {warn("test warning", uplevel: 0)} assert_equal("#{__FILE__}:#{__LINE__-1}: warning: test warning\n", warning[0]) - def (obj = Object.new).w(n) warn("test warning", uplevel: n) end - warning = capture_warning_warn {obj.w(0)} - assert_equal("#{__FILE__}:#{__LINE__-2}: warning: test warning\n", warning[0]) - warning = capture_warning_warn {obj.w(1)} - assert_equal("#{__FILE__}:#{__LINE__-1}: warning: test warning\n", warning[0]) assert_raise(ArgumentError) {warn("test warning", uplevel: -1)} assert_in_out_err(["-e", "warn 'ok', uplevel: 1"], '', [], /warning:/) - warning = capture_warning_warn {warn("test warning", {uplevel: 0})} - assert_match(/test warning.*{:uplevel=>0}/m, warning[0]) - warning = capture_warning_warn {warn("test warning", **{uplevel: 0})} - assert_equal("#{__FILE__}:#{__LINE__-1}: warning: test warning\n", warning[0]) - warning = capture_warning_warn {warn("test warning", {uplevel: 0}, **{})} - assert_equal("test warning\n{:uplevel=>0}\n", warning[0]) - assert_raise(ArgumentError) {warn("test warning", foo: 1)} end def test_warning_warn_invalid_argument @@ -1027,12 +1038,10 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status| t.puts "require '#{basename}'" t.close $LOAD_PATH.push(File.dirname(t)) - warning = capture_warning_warn { - assert require(basename) - } + warning = capture_warning_warn {require basename} ensure $LOAD_PATH.pop - $LOADED_FEATURES.delete(t.path) + $LOADED_FEATURES.delete(t) end assert_equal(1, warning.size) assert_match(/circular require/, warning.first) @@ -1040,7 +1049,7 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status| end def test_warning_warn_super - assert_in_out_err(%[-W0], "#{<<~"{#"}\n#{<<~'};'}", [], /global variable `\$asdfiasdofa_test_warning_warn_super' not initialized/) + assert_in_out_err(%[-W0], "#{<<~"{#"}\n#{<<~'};'}", [], /instance variable @a not initialized/) {# module Warning def warn(message) @@ -1049,57 +1058,10 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status| end $VERBOSE = true - $asdfiasdofa_test_warning_warn_super + @a }; end - def test_warning_category - assert_raise(TypeError) {Warning[nil]} - assert_raise(ArgumentError) {Warning[:XXXX]} - assert_include([true, false], Warning[:deprecated]) - assert_include([true, false], Warning[:experimental]) - end - - def test_warning_category_deprecated - warning = EnvUtil.verbose_warning do - deprecated = Warning[:deprecated] - Warning[:deprecated] = true - Warning.warn "deprecated feature", category: :deprecated - ensure - Warning[:deprecated] = deprecated - end - assert_equal "deprecated feature", warning - - warning = EnvUtil.verbose_warning do - deprecated = Warning[:deprecated] - Warning[:deprecated] = false - Warning.warn "deprecated feature", category: :deprecated - ensure - Warning[:deprecated] = deprecated - end - assert_empty warning - end - - def test_warning_category_experimental - warning = EnvUtil.verbose_warning do - experimental = Warning[:experimental] - Warning[:experimental] = true - Warning.warn "experimental feature", category: :experimental - ensure - Warning[:experimental] = experimental - end - assert_equal "experimental feature", warning - - warning = EnvUtil.verbose_warning do - experimental = Warning[:experimental] - Warning[:experimental] = false - Warning.warn "experimental feature", category: :experimental - ensure - Warning[:experimental] = experimental - end - assert_empty warning - end - def test_undefined_backtrace assert_separately([], "#{<<-"begin;"}\n#{<<-"end;"}") begin; @@ -1179,39 +1141,16 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status| end end - def test_backtrace_in_eval - bug = '[ruby-core:84434] [Bug #14229]' - assert_in_out_err(['-e', 'eval("raise")'], "", [], /^\(eval\):1:/, bug) - end - def test_full_message - message = RuntimeError.new("testerror").full_message - assert_operator(message, :end_with?, "\n") - 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") + assert(status1.success?) + assert(err1.empty?, "expected nothing wrote to $stdout by #long_message") _, err2, status1 = EnvUtil.invoke_ruby(['-e', "#{test_method}; begin; foo; end"], '', true, true) assert_equal(err2, out1) - e = RuntimeError.new("a\n") - message = assert_nothing_raised(ArgumentError, proc {e.pretty_inspect}) do - e.full_message - end - assert_operator(message, :end_with?, "\n") - message = message.gsub(/\e\[[\d;]*m/, '') - assert_not_operator(message, :end_with?, "\n\n") - e = RuntimeError.new("a\n\nb\n\nc") - message = assert_nothing_raised(ArgumentError, proc {e.pretty_inspect}) do - e.full_message - end - assert_all?(message.lines) do |m| - /\e\[\d[;\d]*m[^\e]*\n/ !~ m - end - e = RuntimeError.new("testerror") message = e.full_message(highlight: false) assert_not_match(/\e/, message) @@ -1219,41 +1158,20 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status| bt = ["test:100", "test:99", "test:98", "test:1"] e = assert_raise(RuntimeError) {raise RuntimeError, "testerror", bt} - bottom = "test:100: testerror (RuntimeError)\n" - top = "test:1\n" - remark = "Traceback (most recent call last):" - message = e.full_message(highlight: false, order: :top) assert_not_match(/\e/, message) assert_operator(message.count("\n"), :>, 2) - assert_operator(message, :start_with?, bottom) - assert_operator(message, :end_with?, top) + assert_operator(message, :start_with?, "test:100: testerror (RuntimeError)\n") + assert_operator(message, :end_with?, "test:1\n") message = e.full_message(highlight: false, order: :bottom) assert_not_match(/\e/, message) assert_operator(message.count("\n"), :>, 2) - assert_operator(message, :start_with?, remark) - assert_operator(message, :end_with?, bottom) - - assert_raise_with_message(ArgumentError, /:top or :bottom/) { - e.full_message(highlight: false, order: :middle) - } + assert_operator(message, :start_with?, "Traceback (most recent call last):") + assert_operator(message, :end_with?, "test:100: testerror (RuntimeError)\n") message = e.full_message(highlight: true) assert_match(/\e/, message) - assert_not_match(/(\e\[1)m\1/, message) - e2 = assert_raise(RuntimeError) {raise RuntimeError, "", bt} - assert_not_match(/(\e\[1)m\1/, e2.full_message(highlight: true)) - - message = e.full_message - if Exception.to_tty? - assert_match(/\e/, message) - message = message.gsub(/\e\[[\d;]*m/, '') - else - assert_not_match(/\e/, message) - end - assert_operator(message, :start_with?, bottom) - assert_operator(message, :end_with?, top) end def test_exception_in_message @@ -1264,39 +1182,6 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status| end raise Bug14566 end; - assert_in_out_err([], code, [], /Bug14566/, success: false, timeout: 2) - end - - def test_non_exception_cause - assert_raise_with_message(TypeError, /exception/) do - raise "foo", cause: 1 - end; - end - - def test_circular_cause_handle - assert_raise_with_message(ArgumentError, /circular cause/) do - begin - raise "error 1" - rescue => e1 - raise "error 2" rescue raise e1, cause: $! - end - end; - end - - def test_super_in_method_missing - assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") - begin; - $VERBOSE = nil - class Object - def method_missing(name, *args, &block) - super - end - end - - bug14670 = '[ruby-dev:50522] [Bug #14670]' - assert_raise_with_message(NoMethodError, /`foo'/, bug14670) do - Object.new.foo - end - end; + assert_in_out_err([], code, [], /Bug14566/, success: false, timeout: 1) end end diff --git a/test/ruby/test_fiber.rb b/test/ruby/test_fiber.rb index e0cc59bd3c..0d070dcbc4 100644 --- a/test/ruby/test_fiber.rb +++ b/test/ruby/test_fiber.rb @@ -34,7 +34,6 @@ class TestFiber < Test::Unit::TestCase end def test_many_fibers - skip 'This is unstable on GitHub Actions --jit-wait. TODO: debug it' if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? max = 10_000 assert_equal(max, max.times{ Fiber.new{} @@ -50,7 +49,7 @@ class TestFiber < Test::Unit::TestCase end def test_many_fibers_with_threads - assert_normal_exit <<-SRC, timeout: 180 + assert_normal_exit <<-SRC, timeout: 60 max = 1000 @cnt = 0 (1..100).map{|ti| @@ -110,15 +109,6 @@ class TestFiber < Test::Unit::TestCase } fib.resume } - assert_raise(FiberError){ - fib = Fiber.new{} - fib.raise "raise in unborn fiber" - } - assert_raise(FiberError){ - fib = Fiber.new{} - fib.resume - fib.raise "raise in dead fiber" - } end def test_return @@ -137,48 +127,6 @@ class TestFiber < Test::Unit::TestCase } end - def test_raise - assert_raise(ZeroDivisionError){ - Fiber.new do - 1/0 - end.resume - } - assert_raise(RuntimeError){ - fib = Fiber.new{ Fiber.yield } - fib.resume - fib.raise "raise and propagate" - } - assert_nothing_raised{ - fib = Fiber.new do - begin - Fiber.yield - rescue - end - end - fib.resume - fib.raise "rescue in fiber" - } - fib = Fiber.new do - begin - Fiber.yield - rescue - Fiber.yield :ok - end - end - fib.resume - assert_equal(:ok, fib.raise) - end - - def test_raise_transferring_fiber - root = Fiber.current - fib = Fiber.new { root.transfer } - fib.transfer - assert_raise(RuntimeError){ - fib.raise "can raise with transfer: true" - } - assert_not_predicate(fib, :alive?) - end - def test_transfer ary = [] f2 = nil @@ -194,33 +142,6 @@ class TestFiber < Test::Unit::TestCase assert_equal([:baz], ary) end - def test_terminate_transferred_fiber - log = [] - fa1 = fa2 = fb1 = r1 = nil - - fa1 = Fiber.new{ - fa2 = Fiber.new{ - log << :fa2_terminate - } - fa2.resume - log << :fa1_terminate - } - fb1 = Fiber.new{ - fa1.transfer - log << :fb1_terminate - } - - r1 = Fiber.new{ - fb1.transfer - log << :r1_terminate - } - - r1.resume - log << :root_terminate - - assert_equal [:fa2_terminate, :fa1_terminate, :r1_terminate, :root_terminate], log - end - def test_tls # def tvar(var, val) @@ -315,93 +236,42 @@ class TestFiber < Test::Unit::TestCase assert_instance_of(Class, Fiber.new(&Class.new.method(:undef_method)).resume(:to_s), bug5083) end - def test_prohibit_transfer_to_resuming_fiber - root_fiber = Fiber.current - - assert_raise(FiberError){ - fiber = Fiber.new{ root_fiber.transfer } - fiber.resume - } - - fa1 = Fiber.new{ - _fa2 = Fiber.new{ root_fiber.transfer } - } - fb1 = Fiber.new{ - _fb2 = Fiber.new{ root_fiber.transfer } - } - fa1.transfer - fb1.transfer - + def test_prohibit_resume_transferred_fiber assert_raise(FiberError){ - fa1.transfer - } - assert_raise(FiberError){ - fb1.transfer - } - end - - def test_prohibit_transfer_to_yielding_fiber - f1 = f2 = f3 = nil - - f1 = Fiber.new{ - f2 = Fiber.new{ - f3 = Fiber.new{ - p f3: Fiber.yield - } - f3.resume + root_fiber = Fiber.current + f = Fiber.new{ + root_fiber.transfer } - f2.resume - } - f1.resume - - assert_raise(FiberError){ f3.transfer 10 } - end - - def test_prohibit_resume_to_transferring_fiber - root_fiber = Fiber.current - - assert_raise(FiberError){ - Fiber.new{ - root_fiber.resume - }.transfer + f.transfer + f.resume } - - f1 = f2 = nil - f1 = Fiber.new do - f2.transfer - end - f2 = Fiber.new do - f1.resume # attempt to resume transferring fiber - end - assert_raise(FiberError){ - f1.transfer + g=nil + f=Fiber.new{ + g.resume + g.resume + } + g=Fiber.new{ + f.resume + f.resume + } + f.transfer } end - def test_fork_from_fiber - skip 'fork not supported' unless Process.respond_to?(:fork) - pid = nil + begin + pid = Process.fork{} + rescue NotImplementedError + return + else + Process.wait(pid) + end bug5700 = '[ruby-core:41456]' assert_nothing_raised(bug5700) do Fiber.new do pid = fork do - xpid = nil - Fiber.new { - xpid = fork do - # enough to trigger GC on old root fiber - count = 10000 - count = 1000 if /openbsd/i =~ RUBY_PLATFORM - count.times do - Fiber.new {}.transfer - Fiber.new { Fiber.yield } - end - exit!(0) - end - }.transfer - _, status = Process.waitpid2(xpid) - exit!(status.success?) + Fiber.new {}.transfer end end.resume end @@ -426,6 +296,48 @@ class TestFiber < Test::Unit::TestCase EOS end + def invoke_rec script, vm_stack_size, machine_stack_size, use_length = true + env = {} + env['RUBY_FIBER_VM_STACK_SIZE'] = vm_stack_size.to_s if vm_stack_size + env['RUBY_FIBER_MACHINE_STACK_SIZE'] = machine_stack_size.to_s if machine_stack_size + out, _ = Dir.mktmpdir("test_fiber") {|tmpdir| + EnvUtil.invoke_ruby([env, '-e', script], '', true, true, chdir: tmpdir, timeout: 30) + } + use_length ? out.length : out + end + + def test_stack_size + h_default = eval(invoke_rec('p RubyVM::DEFAULT_PARAMS', nil, nil, false)) + h_0 = eval(invoke_rec('p RubyVM::DEFAULT_PARAMS', 0, 0, false)) + h_large = eval(invoke_rec('p RubyVM::DEFAULT_PARAMS', 1024 * 1024 * 10, 1024 * 1024 * 10, false)) + + assert_operator(h_default[:fiber_vm_stack_size], :>, h_0[:fiber_vm_stack_size]) + assert_operator(h_default[:fiber_vm_stack_size], :<, h_large[:fiber_vm_stack_size]) + assert_operator(h_default[:fiber_machine_stack_size], :>=, h_0[:fiber_machine_stack_size]) + assert_operator(h_default[:fiber_machine_stack_size], :<=, h_large[:fiber_machine_stack_size]) + + # check VM machine stack size + script = '$stdout.sync=true; def rec; print "."; rec; end; Fiber.new{rec}.resume' + size_default = invoke_rec script, nil, nil + assert_operator(size_default, :>, 0) + size_0 = invoke_rec script, 0, nil + assert_operator(size_default, :>, size_0) + size_large = invoke_rec script, 1024 * 1024 * 10, nil + assert_operator(size_default, :<, size_large) + + return if /mswin|mingw/ =~ RUBY_PLATFORM + + # check machine stack size + # Note that machine stack size may not change size (depend on OSs) + script = '$stdout.sync=true; def rec; print "."; 1.times{1.times{1.times{rec}}}; end; Fiber.new{rec}.resume' + vm_stack_size = 1024 * 1024 + size_default = invoke_rec script, vm_stack_size, nil + size_0 = invoke_rec script, vm_stack_size, 0 + assert_operator(size_default, :>=, size_0) + size_large = invoke_rec script, vm_stack_size, 1024 * 1024 * 10 + assert_operator(size_default, :<=, size_large) + end + def test_separate_lastmatch bug7678 = '[ruby-core:51331]' /a/ =~ "a" @@ -471,15 +383,6 @@ class TestFiber < Test::Unit::TestCase assert_match(/resumed/, Fiber.current.to_s) end - def test_create_fiber_in_new_thread - ret = Thread.new{ - Thread.new{ - Fiber.new{Fiber.yield :ok}.resume - }.value - }.value - assert_equal :ok, ret, '[Bug #14642]' - end - def test_machine_stack_gc assert_normal_exit <<-RUBY, '[Bug #14561]', timeout: 10 enum = Enumerator.new { |y| y << 1 } diff --git a/test/ruby/test_file.rb b/test/ruby/test_file.rb index d570b6f6fb..10bfbd9ae0 100644 --- a/test/ruby/test_file.rb +++ b/test/ruby/test_file.rb @@ -147,8 +147,8 @@ class TestFile < Test::Unit::TestCase end def test_read_all_extended_file - [{}, {:textmode=>true}, {:binmode=>true}].each do |mode| - Tempfile.create("test-extended-file", **mode) {|f| + [nil, {:textmode=>true}, {:binmode=>true}].each do |mode| + Tempfile.create("test-extended-file", mode) {|f| assert_nil(f.getc) f.print "a" f.rewind @@ -158,8 +158,8 @@ class TestFile < Test::Unit::TestCase end def test_gets_extended_file - [{}, {:textmode=>true}, {:binmode=>true}].each do |mode| - Tempfile.create("test-extended-file", **mode) {|f| + [nil, {:textmode=>true}, {:binmode=>true}].each do |mode| + Tempfile.create("test-extended-file", mode) {|f| assert_nil(f.getc) f.print "a" f.rewind @@ -169,8 +169,8 @@ class TestFile < Test::Unit::TestCase end def test_gets_para_extended_file - [{}, {:textmode=>true}, {:binmode=>true}].each do |mode| - Tempfile.create("test-extended-file", **mode) {|f| + [nil, {:textmode=>true}, {:binmode=>true}].each do |mode| + Tempfile.create("test-extended-file", mode) {|f| assert_nil(f.getc) f.print "\na" f.rewind @@ -180,8 +180,8 @@ class TestFile < Test::Unit::TestCase end def test_each_char_extended_file - [{}, {:textmode=>true}, {:binmode=>true}].each do |mode| - Tempfile.create("test-extended-file", **mode) {|f| + [nil, {:textmode=>true}, {:binmode=>true}].each do |mode| + Tempfile.create("test-extended-file", mode) {|f| assert_nil(f.getc) f.print "a" f.rewind @@ -193,8 +193,8 @@ class TestFile < Test::Unit::TestCase end def test_each_byte_extended_file - [{}, {:textmode=>true}, {:binmode=>true}].each do |mode| - Tempfile.create("test-extended-file", **mode) {|f| + [nil, {:textmode=>true}, {:binmode=>true}].each do |mode| + Tempfile.create("test-extended-file", mode) {|f| assert_nil(f.getc) f.print "a" f.rewind @@ -206,8 +206,8 @@ class TestFile < Test::Unit::TestCase end def test_getc_extended_file - [{}, {:textmode=>true}, {:binmode=>true}].each do |mode| - Tempfile.create("test-extended-file", **mode) {|f| + [nil, {:textmode=>true}, {:binmode=>true}].each do |mode| + Tempfile.create("test-extended-file", mode) {|f| assert_nil(f.getc) f.print "a" f.rewind @@ -217,8 +217,8 @@ class TestFile < Test::Unit::TestCase end def test_getbyte_extended_file - [{}, {:textmode=>true}, {:binmode=>true}].each do |mode| - Tempfile.create("test-extended-file", **mode) {|f| + [nil, {:textmode=>true}, {:binmode=>true}].each do |mode| + Tempfile.create("test-extended-file", mode) {|f| assert_nil(f.getc) f.print "a" f.rewind @@ -233,9 +233,11 @@ class TestFile < Test::Unit::TestCase end def test_chown - Tempfile.create("test-chown") {|f| - assert_nothing_raised {f.chown(-1, -1)} - assert_nothing_raised("[ruby-dev:27140]") {f.chown(nil, nil)} + assert_nothing_raised { + File.open(__FILE__) {|f| f.chown(-1, -1) } + } + assert_nothing_raised("[ruby-dev:27140]") { + File.open(__FILE__) {|f| f.chown nil, nil } } end @@ -250,10 +252,6 @@ class TestFile < Test::Unit::TestCase 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(".")}) - realpath = File.join(realdir, "test") - File.write(realpath, "") - assert_equal(realpath, Dir.chdir(realdir) {File.realpath("test")}) if File::ALT_SEPARATOR bug2961 = '[ruby-core:28653]' assert_equal(realdir, File.realpath(realdir.tr(File::SEPARATOR, File::ALT_SEPARATOR)), bug2961) @@ -285,6 +283,26 @@ class TestFile < Test::Unit::TestCase } end + def test_realpath_taintedness + Dir.mktmpdir('rubytest-realpath') {|tmpdir| + dir = File.realpath(tmpdir).untaint + File.write(File.join(dir, base = "test.file"), '') + base.taint + dir.taint + assert_predicate(File.realpath(base, dir), :tainted?) + base.untaint + dir.taint + assert_predicate(File.realpath(base, dir), :tainted?) + base.taint + dir.untaint + assert_predicate(File.realpath(base, dir), :tainted?) + base.untaint + dir.untaint + assert_predicate(File.realpath(base, dir), :tainted?) + assert_predicate(Dir.chdir(dir) {File.realpath(base)}, :tainted?) + } + end + def test_realpath_special_symlink IO.pipe do |r, w| if File.pipe?(path = "/dev/fd/#{r.fileno}") @@ -300,8 +318,6 @@ class TestFile < Test::Unit::TestCase 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")}) } begin result = File.realdirpath("bar", "//:/foo") @@ -449,7 +465,17 @@ class TestFile < Test::Unit::TestCase end end - if /mswin|mingw/ =~ RUBY_PLATFORM + def test_untainted_path + bug5374 = '[ruby-core:39745]' + cwd = ("./"*40+".".taint).dup.untaint + in_safe = proc {|safe| $SAFE = safe; File.stat(cwd)} + assert_not_send([cwd, :tainted?]) + (0..1).each do |level| + assert_nothing_raised(SecurityError, bug5374) {in_safe[level]} + end + end + + if /(bcc|ms|cyg)win|mingw|emx/ =~ RUBY_PLATFORM def test_long_unc feature3399 = '[ruby-core:30623]' path = File.expand_path(__FILE__) @@ -476,8 +502,6 @@ class TestFile < Test::Unit::TestCase io = File.open(tmpdir, File::RDWR | File::TMPFILE) rescue Errno::EINVAL skip 'O_TMPFILE not supported (EINVAL)' - rescue Errno::EISDIR - skip 'O_TMPFILE not supported (EISDIR)' rescue Errno::EOPNOTSUPP skip 'O_TMPFILE not supported (EOPNOTSUPP)' end @@ -491,25 +515,4 @@ class TestFile < Test::Unit::TestCase end end if File::Constants.const_defined?(:TMPFILE) - def test_absolute_path? - assert_file.absolute_path?(File.absolute_path(__FILE__)) - assert_file.absolute_path?("//foo/bar\\baz") - assert_file.not_absolute_path?(File.basename(__FILE__)) - assert_file.not_absolute_path?("C:foo\\bar") - assert_file.not_absolute_path?("~") - assert_file.not_absolute_path?("~user") - - if /cygwin|mswin|mingw/ =~ RUBY_PLATFORM - assert_file.absolute_path?("C:\\foo\\bar") - assert_file.absolute_path?("C:/foo/bar") - else - assert_file.not_absolute_path?("C:\\foo\\bar") - assert_file.not_absolute_path?("C:/foo/bar") - end - if /mswin|mingw/ =~ RUBY_PLATFORM - assert_file.not_absolute_path?("/foo/bar\\baz") - else - assert_file.absolute_path?("/foo/bar\\baz") - end - end end diff --git a/test/ruby/test_file_exhaustive.rb b/test/ruby/test_file_exhaustive.rb index ac11e0cc85..817c3580d1 100644 --- a/test/ruby/test_file_exhaustive.rb +++ b/test/ruby/test_file_exhaustive.rb @@ -18,7 +18,7 @@ class TestFileExhaustive < Test::Unit::TestCase end def setup - @dir = Dir.mktmpdir("ruby-test") + @dir = Dir.mktmpdir("rubytest-file") File.chown(-1, Process.gid, @dir) end @@ -70,7 +70,7 @@ class TestFileExhaustive < Test::Unit::TestCase def notownedfile return @notownedfile if defined? @notownedfile - if Process.euid != File.stat("/").uid + if Process.euid != 0 @notownedfile = '/' else @notownedfile = nil @@ -130,7 +130,7 @@ class TestFileExhaustive < Test::Unit::TestCase @hardlinkfile = make_tmp_filename("hardlinkfile") begin File.link(regular_file, @hardlinkfile) - rescue NotImplementedError, Errno::EINVAL, Errno::EACCES # EINVAL for Windows Vista, EACCES for Android Termux + rescue NotImplementedError, Errno::EINVAL # EINVAL for Windows Vista @hardlinkfile = nil end @hardlinkfile @@ -495,39 +495,22 @@ class TestFileExhaustive < Test::Unit::TestCase assert_file.grpowned?(utf8_file) end if POSIX - def io_open(file_name) - # avoid File.open since we do not want #to_path - io = IO.for_fd(IO.sysopen(file_name)) - yield io - ensure - io&.close - end - def test_suid assert_file.not_setuid?(regular_file) assert_file.not_setuid?(utf8_file) - if suidfile - assert_file.setuid?(suidfile) - io_open(suidfile) { |io| assert_file.setuid?(io) } - end + assert_file.setuid?(suidfile) if suidfile end def test_sgid assert_file.not_setgid?(regular_file) assert_file.not_setgid?(utf8_file) - if sgidfile - assert_file.setgid?(sgidfile) - io_open(sgidfile) { |io| assert_file.setgid?(io) } - end + assert_file.setgid?(sgidfile) if sgidfile end def test_sticky assert_file.not_sticky?(regular_file) assert_file.not_sticky?(utf8_file) - if stickyfile - assert_file.sticky?(stickyfile) - io_open(stickyfile) { |io| assert_file.sticky?(io) } - end + assert_file.sticky?(stickyfile) if stickyfile end def test_path_identical_p @@ -623,23 +606,6 @@ class TestFileExhaustive < Test::Unit::TestCase assert_raise(Errno::ENOENT) { File.ctime(nofile) } end - def test_birthtime - skip if RUBY_PLATFORM =~ /android/ - [regular_file, utf8_file].each do |file| - t1 = File.birthtime(file) - t2 = File.open(file) {|f| f.birthtime} - assert_kind_of(Time, t1) - assert_kind_of(Time, t2) - assert_equal(t1, t2) - rescue Errno::ENOSYS, NotImplementedError - # ignore unsupporting filesystems - rescue Errno::EPERM - # Docker prohibits statx syscall by the default. - skip("statx(2) is prohibited by seccomp") - end - assert_raise(Errno::ENOENT) { File.birthtime(nofile) } - end if File.respond_to?(:birthtime) - def test_chmod [regular_file, utf8_file].each do |file| assert_equal(1, File.chmod(0444, file)) @@ -684,6 +650,7 @@ class TestFileExhaustive < Test::Unit::TestCase def test_utime_symlinkfile return unless symlinkfile t = Time.local(2000) + stat = File.lstat(symlinkfile) assert_equal(1, File.utime(t, t, symlinkfile)) assert_equal(t, File.stat(regular_file).atime) assert_equal(t, File.stat(regular_file).mtime) @@ -797,10 +764,7 @@ class TestFileExhaustive < Test::Unit::TestCase def test_expand_path assert_equal(regular_file, File.expand_path(File.basename(regular_file), File.dirname(regular_file))) assert_equal(utf8_file, File.expand_path(File.basename(utf8_file), File.dirname(utf8_file))) - end - - if NTFS - def test_expand_path_ntfs + if NTFS [regular_file, utf8_file].each do |file| assert_equal(file, File.expand_path(file + " ")) assert_equal(file, File.expand_path(file + ".")) @@ -811,11 +775,8 @@ class TestFileExhaustive < Test::Unit::TestCase assert_match(/\Ae:\//i, File.expand_path('e:foo', 'd:/bar')) assert_match(%r'\Ac:/bar/foo\z'i, File.expand_path('c:foo', 'c:/bar')) end - end - - case RUBY_PLATFORM - when /darwin/ - def test_expand_path_hfs + case RUBY_PLATFORM + when /darwin/ ["\u{feff}", *"\u{2000}"..."\u{2100}"].each do |c| file = regular_file + c full_path = File.expand_path(file) @@ -831,16 +792,11 @@ class TestFileExhaustive < Test::Unit::TestCase end end end - end - - if DRIVE - def test_expand_path_absolute + if DRIVE assert_match(%r"\Az:/foo\z"i, File.expand_path('/foo', "z:/bar")) assert_match(%r"\A//host/share/foo\z"i, File.expand_path('/foo', "//host/share/bar")) assert_match(%r"\A#{DRIVE}/foo\z"i, File.expand_path('/foo')) - end - else - def test_expand_path_absolute + else assert_equal("/foo", File.expand_path('/foo')) end end @@ -1059,6 +1015,32 @@ class TestFileExhaustive < Test::Unit::TestCase assert_match(%r"\A#{DRIVE}/foo\z"i, File.expand_path('/foo')) end + def test_expand_path_returns_tainted_strings_or_not + assert_equal(true, File.expand_path('foo').tainted?) + assert_equal(true, File.expand_path('foo'.taint).tainted?) + assert_equal(true, File.expand_path('/foo'.taint).tainted?) + assert_equal(true, File.expand_path('foo', 'bar').tainted?) + assert_equal(true, File.expand_path('foo', '/bar'.taint).tainted?) + assert_equal(true, File.expand_path('foo'.taint, '/bar').tainted?) + assert_equal(true, File.expand_path('~').tainted?) if ENV["HOME"] + + if DRIVE + assert_equal(true, File.expand_path('/foo').tainted?) + assert_equal(false, File.expand_path('//foo').tainted?) + assert_equal(true, File.expand_path('C:/foo'.taint).tainted?) + assert_equal(false, File.expand_path('C:/foo').tainted?) + assert_equal(true, File.expand_path('foo', '/bar').tainted?) + assert_equal(true, File.expand_path('foo', 'C:/bar'.taint).tainted?) + assert_equal(true, File.expand_path('foo'.taint, 'C:/bar').tainted?) + assert_equal(false, File.expand_path('foo', 'C:/bar').tainted?) + assert_equal(false, File.expand_path('C:/foo/../bar').tainted?) + assert_equal(false, File.expand_path('foo', '//bar').tainted?) + else + assert_equal(false, File.expand_path('/foo').tainted?) + assert_equal(false, File.expand_path('foo', '/bar').tainted?) + end + end + def test_expand_path_converts_a_pathname_to_an_absolute_pathname_using_home_as_base old_home = ENV["HOME"] home = ENV["HOME"] = "#{DRIVE}/UserHome" @@ -1184,10 +1166,7 @@ class TestFileExhaustive < Test::Unit::TestCase assert_equal("foo", File.basename("foo", ".ext")) assert_equal("foo", File.basename("foo.ext", ".ext")) assert_equal("foo", File.basename("foo.ext", ".*")) - end - - if NTFS - def test_basename_strip + if NTFS [regular_file, utf8_file].each do |file| basename = File.basename(file) assert_equal(basename, File.basename(file + " ")) @@ -1201,9 +1180,7 @@ class TestFileExhaustive < Test::Unit::TestCase assert_equal(basename, File.basename(file + ".", ".*")) assert_equal(basename, File.basename(file + "::$DATA", ".*")) end - end - else - def test_basename_strip + else [regular_file, utf8_file].each do |file| basename = File.basename(file) assert_equal(basename + " ", File.basename(file + " ")) @@ -1218,18 +1195,13 @@ class TestFileExhaustive < Test::Unit::TestCase assert_equal(basename, File.basename(file + "::$DATA", ".*")) end end - end - - if File::ALT_SEPARATOR == '\\' - def test_basename_backslash + if File::ALT_SEPARATOR == '\\' a = "foo/\225\\\\" [%W"cp437 \225", %W"cp932 \225\\"].each do |cp, expected| assert_equal(expected.force_encoding(cp), File.basename(a.dup.force_encoding(cp)), cp) end end - end - def test_basename_encoding assert_incompatible_encoding {|d| File.basename(d)} assert_incompatible_encoding {|d| File.basename(d, ".*")} assert_raise(Encoding::CompatibilityError) {File.basename("foo.ext", ".*".encode("utf-16le"))} @@ -1245,14 +1217,8 @@ class TestFileExhaustive < Test::Unit::TestCase assert_equal(@dir, File.dirname(regular_file)) assert_equal(@dir, File.dirname(utf8_file)) assert_equal(".", File.dirname("")) - end - - def test_dirname_encoding assert_incompatible_encoding {|d| File.dirname(d)} - end - - if File::ALT_SEPARATOR == '\\' - def test_dirname_backslash + if File::ALT_SEPARATOR == '\\' a = "\225\\\\foo" [%W"cp437 \225", %W"cp932 \225\\"].each do |cp, expected| assert_equal(expected.force_encoding(cp), File.dirname(a.dup.force_encoding(cp)), cp) @@ -1264,23 +1230,21 @@ class TestFileExhaustive < Test::Unit::TestCase assert_equal(".test", File.extname(regular_file)) assert_equal(".test", File.extname(utf8_file)) prefixes = ["", "/", ".", "/.", "bar/.", "/bar/."] - infixes = ["", " "] + infixes = ["", " ", "."] infixes2 = infixes + [".ext "] appendixes = [""] if NTFS appendixes << " " << "." << "::$DATA" << "::$DATA.bar" - else - appendixes << [".", "."] end prefixes.each do |prefix| - appendixes.each do |appendix, ext = ""| + appendixes.each do |appendix| infixes.each do |infix| path = "#{prefix}foo#{infix}#{appendix}" - assert_equal(ext, File.extname(path), "File.extname(#{path.inspect})") + assert_equal("", File.extname(path), "File.extname(#{path.inspect})") end infixes2.each do |infix| path = "#{prefix}foo#{infix}.ext#{appendix}" - assert_equal(ext.empty? ? ".ext" : appendix, File.extname(path), "File.extname(#{path.inspect})") + assert_equal(".ext", File.extname(path), "File.extname(#{path.inspect})") end end end @@ -1513,7 +1477,11 @@ class TestFileExhaustive < Test::Unit::TestCase assert_integer_or_nil(fs1.rdev_minor) assert_integer(fs1.ino) assert_integer(fs1.mode) - assert_equal(hardlinkfile ? 2 : 1, fs1.nlink) + unless /emx|mswin|mingw/ =~ RUBY_PLATFORM + # on Windows, nlink is always 1. but this behavior will be changed + # in the future. + assert_equal(hardlinkfile ? 2 : 1, fs1.nlink) + end assert_integer(fs1.uid) assert_integer(fs1.gid) assert_equal(3, fs1.size) diff --git a/test/ruby/test_fixnum.rb b/test/ruby/test_fixnum.rb index 2878258920..bd18067dda 100644 --- a/test/ruby/test_fixnum.rb +++ b/test/ruby/test_fixnum.rb @@ -4,6 +4,7 @@ require 'test/unit' class TestFixnum < Test::Unit::TestCase def setup @verbose = $VERBOSE + $VERBOSE = nil end def teardown diff --git a/test/ruby/test_flip.rb b/test/ruby/test_flip.rb index 9c58f5f497..b8b05aed6d 100644 --- a/test/ruby/test_flip.rb +++ b/test/ruby/test_flip.rb @@ -19,7 +19,7 @@ class TestFlip < Test::Unit::TestCase assert_nothing_raised(NotImplementedError, bug6899) do 2000.times {eval %[(foo..bar) ? 1 : 2]} end - [foo, bar] + foo = bar end def test_shared_eval @@ -28,7 +28,6 @@ class TestFlip < Test::Unit::TestCase vs.select {|n| if n==2..n==16 then 1 end} v = eval("vs.select {|n| if n==3..n==6 then 1 end}") assert_equal([*3..6], v, bug7671) - vs end def test_shared_thread diff --git a/test/ruby/test_float.rb b/test/ruby/test_float.rb index fbf0d87f8e..7fabfd351d 100644 --- a/test/ruby/test_float.rb +++ b/test/ruby/test_float.rb @@ -305,7 +305,6 @@ class TestFloat < Test::Unit::TestCase assert_equal(1.0, 1.0 ** (2**32)) assert_equal(1.0, 1.0 ** 1.0) assert_raise(TypeError) { 1.0 ** nil } - assert_equal(9.0, 3.0 ** 2) end def test_eql @@ -765,9 +764,6 @@ class TestFloat < Test::Unit::TestCase assert_raise_with_message(ArgumentError, /xxx/) { 1.0.round(half: "\0xxx") } - assert_raise_with_message(Encoding::CompatibilityError, /ASCII incompatible/) { - 1.0.round(half: "up".force_encoding("utf-16be")) - } end def test_Float @@ -792,15 +788,9 @@ class TestFloat < Test::Unit::TestCase assert_raise(ArgumentError) { Float('0xf.p0') } assert_raise(ArgumentError) { Float('0xf.f') } assert_raise(ArgumentError) { Float('0xf.fp') } - begin - verbose_bak, $VERBOSE = $VERBOSE, nil - assert_equal(Float::INFINITY, Float('0xf.fp1000000000000000')) - ensure - $VERBOSE = verbose_bak - end + assert_equal(Float::INFINITY, Float('0xf.fp1000000000000000')) assert_equal(1, suppress_warning {Float("1e10_00")}.infinite?) assert_raise(TypeError) { Float(nil) } - assert_raise(TypeError) { Float(:test) } o = Object.new def o.to_f; inf = Float::INFINITY; inf/inf; end assert_predicate(Float(o), :nan?) @@ -811,49 +801,6 @@ class TestFloat < Test::Unit::TestCase assert_raise(ArgumentError, bug4310) {under_gc_stress {Float('a'*10000)}} end - def test_Float_with_invalid_exception - assert_raise(ArgumentError) { - Float("0", exception: 1) - } - end - - def test_Float_with_exception_keyword - assert_raise(ArgumentError) { - Float(".", exception: true) - } - assert_nothing_raised(ArgumentError) { - assert_equal(nil, Float(".", exception: false)) - } - assert_raise(RangeError) { - Float(1i, exception: true) - } - assert_nothing_raised(RangeError) { - assert_equal(nil, Float(1i, exception: false)) - } - assert_raise(TypeError) { - Float(nil, exception: true) - } - assert_nothing_raised(TypeError) { - assert_equal(nil, Float(nil, exception: false)) - } - assert_nothing_raised(TypeError) { - assert_equal(nil, Float(:test, exception: false)) - } - assert_nothing_raised(TypeError) { - assert_equal(nil, Float(Object.new, exception: false)) - } - assert_nothing_raised(TypeError) { - o = Object.new - def o.to_f; 3.14; end - assert_equal(3.14, Float(o, exception: false)) - } - assert_nothing_raised(RuntimeError) { - o = Object.new - def o.to_f; raise; end - assert_equal(nil, Float(o, exception: false)) - } - end - def test_num2dbl assert_raise(ArgumentError, "comparison of String with 0 failed") do 1.0.step(2.0, "0.5") {} @@ -893,8 +840,7 @@ class TestFloat < Test::Unit::TestCase a = rand b = a+rand*1000 s = (b - a) / 10 - seq = (a...b).step(s) - assert_equal(10, seq.to_a.length, seq.inspect) + assert_equal(10, (a...b).step(s).to_a.length) end assert_equal([1.0, 2.9, 4.8, 6.699999999999999], (1.0...6.8).step(1.9).to_a) diff --git a/test/ruby/test_fnmatch.rb b/test/ruby/test_fnmatch.rb index 16f1076e48..30250b5a19 100644 --- a/test/ruby/test_fnmatch.rb +++ b/test/ruby/test_fnmatch.rb @@ -10,7 +10,6 @@ class TestFnmatch < Test::Unit::TestCase assert_equal(t.include?(i.chr), !File.fnmatch("[!#{s}]", i.chr, File::FNM_DOTMATCH)) end end - def test_fnmatch assert_file.for("[ruby-dev:22819]").fnmatch('\[1\]' , '[1]') assert_file.for("[ruby-dev:22815]").fnmatch('*?', 'a') @@ -18,16 +17,10 @@ class TestFnmatch < Test::Unit::TestCase assert_file.fnmatch('\[1\]' , '[1]', File::FNM_PATHNAME) assert_file.fnmatch('*?', 'a', File::FNM_PATHNAME) assert_file.fnmatch('*/', 'a/', File::FNM_PATHNAME) - end - - def test_text # text assert_file.fnmatch('cat', 'cat') assert_file.not_fnmatch('cat', 'category') assert_file.not_fnmatch('cat', 'wildcat') - end - - def test_any_one # '?' matches any one character assert_file.fnmatch('?at', 'cat') assert_file.fnmatch('c?t', 'cat') @@ -36,9 +29,6 @@ class TestFnmatch < Test::Unit::TestCase assert_file.not_fnmatch('c??t', 'cat') assert_file.not_fnmatch('??at', 'cat') assert_file.not_fnmatch('ca??', 'cat') - end - - def test_any_chars # '*' matches any number (including 0) of any characters assert_file.fnmatch('c*', 'cats') assert_file.fnmatch('c*ts', 'cats') @@ -50,15 +40,9 @@ class TestFnmatch < Test::Unit::TestCase assert_file.not_fnmatch('a*abc', 'abc') assert_file.fnmatch('a*bc', 'abc') assert_file.not_fnmatch('a*bc', 'abcd') - end - - def test_char_class # [seq] : matches any character listed between bracket # [!seq] or [^seq] : matches any character except those listed between bracket bracket_test("bd-gikl-mosv-x", "bdefgiklmosvwx") - end - - def test_escape # escaping character assert_file.fnmatch('\?', '?') assert_file.not_fnmatch('\?', '\?') @@ -75,9 +59,6 @@ class TestFnmatch < Test::Unit::TestCase assert_file.fnmatch('[a\-c]', 'c') assert_file.not_fnmatch('[a\-c]', 'b') assert_file.not_fnmatch('[a\-c]', '\\') - end - - def test_fnm_escape # escaping character loses its meaning if FNM_NOESCAPE is set assert_file.not_fnmatch('\?', '?', File::FNM_NOESCAPE) assert_file.fnmatch('\?', '\?', File::FNM_NOESCAPE) @@ -94,9 +75,6 @@ class TestFnmatch < Test::Unit::TestCase assert_file.fnmatch('[a\-c]', 'c', File::FNM_NOESCAPE) assert_file.fnmatch('[a\-c]', 'b', File::FNM_NOESCAPE) # '\\' < 'b' < 'c' assert_file.fnmatch('[a\-c]', '\\', File::FNM_NOESCAPE) - end - - def test_fnm_casefold # case is ignored if FNM_CASEFOLD is set assert_file.not_fnmatch('cat', 'CAT') assert_file.fnmatch('cat', 'CAT', File::FNM_CASEFOLD) @@ -104,17 +82,11 @@ class TestFnmatch < Test::Unit::TestCase assert_file.fnmatch('[a-z]', 'D', File::FNM_CASEFOLD) assert_file.not_fnmatch('[abc]', 'B') assert_file.fnmatch('[abc]', 'B', File::FNM_CASEFOLD) - end - - def test_fnm_pathname # wildcard doesn't match '/' if FNM_PATHNAME is set assert_file.fnmatch('foo?boo', 'foo/boo') assert_file.fnmatch('foo*', 'foo/boo') assert_file.not_fnmatch('foo?boo', 'foo/boo', File::FNM_PATHNAME) assert_file.not_fnmatch('foo*', 'foo/boo', File::FNM_PATHNAME) - end - - def test_fnm_dotmatch # wildcard matches leading period if FNM_DOTMATCH is set assert_file.not_fnmatch('*', '.profile') assert_file.fnmatch('*', '.profile', File::FNM_DOTMATCH) @@ -123,9 +95,6 @@ class TestFnmatch < Test::Unit::TestCase assert_file.fnmatch('*/*', 'dave/.profile') assert_file.not_fnmatch('*/*', 'dave/.profile', File::FNM_PATHNAME) assert_file.fnmatch('*/*', 'dave/.profile', File::FNM_PATHNAME | File::FNM_DOTMATCH) - end - - def test_recursive # recursive matching assert_file.fnmatch('**/foo', 'a/b/c/foo', File::FNM_PATHNAME) assert_file.fnmatch('**/foo', '/foo', File::FNM_PATHNAME) diff --git a/test/ruby/test_frozen_error.rb b/test/ruby/test_frozen_error.rb deleted file mode 100644 index ace1e4c775..0000000000 --- a/test/ruby/test_frozen_error.rb +++ /dev/null @@ -1,57 +0,0 @@ -require 'test/unit' - -class TestFrozenError < Test::Unit::TestCase - def test_new_default - exc = FrozenError.new - assert_equal("FrozenError", exc.message) - assert_raise_with_message(ArgumentError, "no receiver is available") { - exc.receiver - } - end - - def test_new_message - exc = FrozenError.new("bar") - assert_equal("bar", exc.message) - assert_raise_with_message(ArgumentError, "no receiver is available") { - exc.receiver - } - end - - def test_new_receiver - obj = Object.new - exc = FrozenError.new("bar", receiver: obj) - assert_equal("bar", exc.message) - assert_same(obj, exc.receiver) - end - - def test_message - obj = Object.new.freeze - e = assert_raise_with_message(FrozenError, /can't modify frozen #{obj.class}/) { - obj.instance_variable_set(:@test, true) - } - assert_include(e.message, obj.inspect) - - klass = Class.new do - def init - @x = true - end - def inspect - init - super - end - end - obj = klass.new.freeze - e = assert_raise_with_message(FrozenError, /can't modify frozen #{obj.class}/) { - obj.init - } - assert_include(e.message, klass.inspect) - end - - def test_receiver - obj = Object.new.freeze - e = assert_raise(FrozenError) {def obj.foo; end} - assert_same(obj, e.receiver) - e = assert_raise(FrozenError) {obj.singleton_class.const_set(:A, 2)} - assert_same(obj.singleton_class, e.receiver) - end -end diff --git a/test/ruby/test_gc.rb b/test/ruby/test_gc.rb index 1823538f73..b3528ddacd 100644 --- a/test/ruby/test_gc.rb +++ b/test/ruby/test_gc.rb @@ -17,7 +17,6 @@ class TestGc < Test::Unit::TestCase 1.upto(10000) { tmp = [0,1,2,3,4,5,6,7,8,9] } - tmp end l=nil 100000.times { @@ -54,9 +53,7 @@ class TestGc < Test::Unit::TestCase def test_start_full_mark return unless use_rgengc? - skip 'stress' if GC.stress - 3.times { GC.start } # full mark and next time it should be minor mark GC.start(full_mark: false) assert_nil GC.latest_gc_info(:major_by) @@ -65,8 +62,6 @@ class TestGc < Test::Unit::TestCase end def test_start_immediate_sweep - skip 'stress' if GC.stress - GC.start(immediate_sweep: false) assert_equal false, GC.latest_gc_info(:immediate_sweep) @@ -95,9 +90,6 @@ class TestGc < Test::Unit::TestCase GC.start GC.stat(stat) ObjectSpace.count_objects(count) - # repeat same methods invocation for cache object creation. - GC.stat(stat) - ObjectSpace.count_objects(count) assert_equal(count[:TOTAL]-count[:FREE], stat[:heap_live_slots]) assert_equal(count[:FREE], stat[:heap_free_slots]) @@ -113,16 +105,12 @@ class TestGc < Test::Unit::TestCase end def test_stat_single - skip 'stress' if GC.stress - stat = GC.stat assert_equal stat[:count], GC.stat(:count) assert_raise(ArgumentError){ GC.stat(:invalid) } end def test_stat_constraints - skip 'stress' if GC.stress - stat = GC.stat assert_equal stat[:total_allocated_pages], stat[:heap_allocated_pages] + stat[:total_freed_pages] assert_operator stat[:heap_sorted_length], :>=, stat[:heap_eden_pages] + stat[:heap_allocatable_pages], "stat is: " + stat.inspect @@ -136,8 +124,6 @@ class TestGc < Test::Unit::TestCase end def test_latest_gc_info - skip 'stress' if GC.stress - assert_separately %w[--disable-gem], __FILE__, __LINE__, <<-'eom' GC.start count = GC.stat(:heap_free_slots) + GC.stat(:heap_allocatable_pages) * GC::INTERNAL_CONSTANTS[:HEAP_PAGE_OBJ_LIMIT] @@ -145,15 +131,10 @@ class TestGc < Test::Unit::TestCase assert_equal :newobj, GC.latest_gc_info[:gc_by] eom - GC.latest_gc_info(h = {}) # allocate hash and rehearsal - GC.start GC.start - GC.start - GC.latest_gc_info(h) - - assert_equal :force, h[:major_by] if use_rgengc? - assert_equal :method, h[:gc_by] - assert_equal true, h[:immediate_sweep] + assert_equal :force, GC.latest_gc_info[:major_by] if use_rgengc? + assert_equal :method, GC.latest_gc_info[:gc_by] + assert_equal true, GC.latest_gc_info[:immediate_sweep] GC.stress = true assert_equal :force, GC.latest_gc_info[:major_by] @@ -233,6 +214,12 @@ class TestGc < Test::Unit::TestCase # always full GC when RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR < 1.0 assert_in_out_err([env, "-e", "1000_000.times{Object.new}; p(GC.stat[:minor_gc_count] < GC.stat[:major_gc_count])"], "", ['true'], //, "") if use_rgengc? + # check obsolete + assert_in_out_err([{'RUBY_FREE_MIN' => '100'}, '-w', '-eexit'], '', [], + /RUBY_FREE_MIN is obsolete. Use RUBY_GC_HEAP_FREE_SLOTS instead/) + assert_in_out_err([{'RUBY_HEAP_MIN_SLOTS' => '100'}, '-w', '-eexit'], '', [], + /RUBY_HEAP_MIN_SLOTS is obsolete. Use RUBY_GC_HEAP_INIT_SLOTS instead/) + env = { "RUBY_GC_MALLOC_LIMIT" => "60000000", "RUBY_GC_MALLOC_LIMIT_MAX" => "160000000", @@ -266,7 +253,6 @@ class TestGc < Test::Unit::TestCase end def test_profiler_clear - skip "for now" assert_separately %w[--disable-gem], __FILE__, __LINE__, <<-'eom', timeout: 30 GC::Profiler.enable @@ -325,7 +311,7 @@ class TestGc < Test::Unit::TestCase def test_sweep_in_finalizer bug9205 = '[ruby-core:58833] [Bug #9205]' 2.times do - assert_ruby_status([], <<-'end;', bug9205, timeout: 120) + assert_ruby_status([], <<-'end;', bug9205, timeout: 60) raise_proc = proc do |id| GC.start end @@ -375,14 +361,6 @@ class TestGc < Test::Unit::TestCase assert_empty(out) end - def test_finalizer_passed_object_id - assert_in_out_err(%w[--disable-gems], <<-EOS, ["true"], []) - o = Object.new - obj_id = o.object_id - ObjectSpace.define_finalizer(o, ->(id){ p id == obj_id }) - EOS - end - def test_verify_internal_consistency assert_nil(GC.verify_internal_consistency) end @@ -406,7 +384,8 @@ class TestGc < Test::Unit::TestCase end def test_gc_stress_at_startup - assert_in_out_err([{"RUBY_DEBUG"=>"gc_stress"}], '', [], [], '[Bug #15784]', success: true, timeout: 60) + skip # it'll be fixed later + assert_in_out_err([{"RUBY_DEBUG"=>"gc_stress"}], '', [], [], '[Bug #15784]', success: true) end def test_gc_disabled_start @@ -472,12 +451,4 @@ class TestGc < Test::Unit::TestCase skip "finalizers did not get run" if @result.empty? assert_equal([:c1, :c2], @result) end - - def test_object_ids_never_repeat - GC.start - a = 1000.times.map { Object.new.object_id } - GC.start - b = 1000.times.map { Object.new.object_id } - assert_empty(a & b) - end end diff --git a/test/ruby/test_gc_compact.rb b/test/ruby/test_gc_compact.rb deleted file mode 100644 index 4a8cff33f4..0000000000 --- a/test/ruby/test_gc_compact.rb +++ /dev/null @@ -1,155 +0,0 @@ -# frozen_string_literal: true -require 'test/unit' -require 'fiddle' -require 'etc' - -class TestGCCompact < Test::Unit::TestCase - class AutoCompact < Test::Unit::TestCase - def setup - skip "autocompact not supported on this platform" unless supports_auto_compact? - super - end - - def test_enable_autocompact - before = GC.auto_compact - GC.auto_compact = true - assert GC.auto_compact - ensure - GC.auto_compact = before - end - - def test_disable_autocompact - before = GC.auto_compact - GC.auto_compact = false - refute GC.auto_compact - ensure - GC.auto_compact = before - end - - def test_major_compacts - before = GC.auto_compact - GC.auto_compact = true - compact = GC.stat :compact_count - GC.start - assert_operator GC.stat(:compact_count), :>, compact - ensure - GC.auto_compact = before - end - - def test_implicit_compaction_does_something - before = GC.auto_compact - list = [] - list2 = [] - - # Try to make some fragmentation - 500.times { - list << Object.new - Object.new - Object.new - } - count = GC.stat :compact_count - GC.auto_compact = true - loop do - break if count < GC.stat(:compact_count) - list2 << Object.new - end - compact_stats = GC.latest_compact_info - refute_predicate compact_stats[:considered], :empty? - refute_predicate compact_stats[:moved], :empty? - ensure - GC.auto_compact = before - end - - private - - def supports_auto_compact? - return true unless defined?(Etc::SC_PAGE_SIZE) - - begin - return GC::INTERNAL_CONSTANTS[:HEAP_PAGE_SIZE] % Etc.sysconf(Etc::SC_PAGE_SIZE) == 0 - rescue NotImplementedError - rescue ArgumentError - end - - true - end - end - - def os_page_size - return true unless defined?(Etc::SC_PAGE_SIZE) - end - - def test_gc_compact_stats - list = [] - - # Try to make some fragmentation - 500.times { - list << Object.new - Object.new - Object.new - } - compact_stats = GC.compact - refute_predicate compact_stats[:considered], :empty? - refute_predicate compact_stats[:moved], :empty? - end - - def memory_location(obj) - (Fiddle.dlwrap(obj) >> 1) - end - - def big_list(level = 10) - if level > 0 - big_list(level - 1) - else - 1000.times.map { - # try to make some empty slots by allocating an object and discarding - Object.new - Object.new - } # likely next to each other - end - end - - # Find an object that's allocated in a slot that had a previous - # tenant, and that tenant moved and is still alive - def find_object_in_recycled_slot(addresses) - new_object = nil - - 100_000.times do - new_object = Object.new - if addresses.index memory_location(new_object) - break - end - end - - new_object - end - - def test_complex_hash_keys - list_of_objects = big_list - hash = list_of_objects.hash - GC.verify_compaction_references(toward: :empty) - assert_equal hash, list_of_objects.hash - GC.verify_compaction_references(double_heap: false) - assert_equal hash, list_of_objects.hash - end - - def walk_ast ast - children = ast.children.grep(RubyVM::AbstractSyntaxTree::Node) - children.each do |child| - assert child.type - walk_ast child - end - end - - def test_ast_compacts - ast = RubyVM::AbstractSyntaxTree.parse_file __FILE__ - assert GC.compact - walk_ast ast - end - - def test_compact_count - count = GC.stat(:compact_count) - GC.compact - assert_equal count + 1, GC.stat(:compact_count) - end -end diff --git a/test/ruby/test_hash.rb b/test/ruby/test_hash.rb index c4b93836c6..bdcf022668 100644 --- a/test/ruby/test_hash.rb +++ b/test/ruby/test_hash.rb @@ -86,6 +86,7 @@ class TestHash < Test::Unit::TestCase 'nil' => nil ] @verbose = $VERBOSE + $VERBOSE = nil end def teardown @@ -148,9 +149,10 @@ class TestHash < Test::Unit::TestCase assert_equal(nil, h['b']) assert_equal(300, h['c']) - assert_raise(ArgumentError) do - @cls[[["a", 100], "b", ["c", 300]]] - end + h = @cls[[["a", 100], "b", ["c", 300]]] + assert_equal(100, h['a']) + assert_equal(nil, h['b']) + assert_equal(300, h['c']) end def test_s_AREF_duplicated_key @@ -265,13 +267,10 @@ class TestHash < Test::Unit::TestCase end def test_AREF_fstring_key - # warmup ObjectSpace.count_objects - ObjectSpace.count_objects - h = {"abc" => 1} - before = ObjectSpace.count_objects[:T_STRING] + before = GC.stat(:total_allocated_objects) 5.times{ h["abc"] } - assert_equal before, ObjectSpace.count_objects[:T_STRING] + assert_equal before, GC.stat(:total_allocated_objects) end def test_ASET_fstring_key @@ -281,24 +280,6 @@ class TestHash < Test::Unit::TestCase assert_same a.keys[0], b.keys[0] end - def test_ASET_fstring_non_literal_key - underscore = "_" - non_literal_strings = Proc.new{ ["abc#{underscore}def", "abc" * 5, "abc" + "def", "" << "ghi" << "jkl"] } - - a, b = {}, {} - non_literal_strings.call.each do |string| - assert_equal 1, a[string] = 1 - end - - non_literal_strings.call.each do |string| - assert_equal 1, b[string] = 1 - end - - [a.keys, b.keys].transpose.each do |key_a, key_b| - assert_same key_a, key_b - end - end - def test_hash_aset_fstring_identity h = {}.compare_by_identity h['abc'] = 1 @@ -317,9 +298,17 @@ class TestHash < Test::Unit::TestCase b = {"ABC" => :t} assert_same a.keys[0], b.keys[0] assert_same "ABC".freeze, a.keys[0] - var = +'ABC' - c = { var => :t } - assert_same "ABC".freeze, c.keys[0] + end + + def test_tainted_string_key + str = 'str'.taint + h = {} + h[str] = nil + key = h.keys.first + assert_equal true, str.tainted? + assert_equal false, str.frozen? + assert_equal true, key.tainted? + assert_equal true, key.frozen? end def test_EQUAL # '==' @@ -344,14 +333,18 @@ class TestHash < Test::Unit::TestCase end def test_clone - for frozen in [ false, true ] - a = @h.clone - a.freeze if frozen - b = a.clone - - assert_equal(a, b) - assert_not_same(a, b) - assert_equal(a.frozen?, b.frozen?) + for taint in [ false, true ] + for frozen in [ false, true ] + a = @h.clone + a.taint if taint + a.freeze if frozen + b = a.clone + + assert_equal(a, b) + assert_not_same(a, b) + assert_equal(a.frozen?, b.frozen?) + assert_equal(a.tainted?, b.tainted?) + end end end @@ -438,14 +431,18 @@ class TestHash < Test::Unit::TestCase end def test_dup - for frozen in [ false, true ] - a = @h.dup - a.freeze if frozen - b = a.dup - - assert_equal(a, b) - assert_not_same(a, b) - assert_equal(false, b.frozen?) + for taint in [ false, true ] + for frozen in [ false, true ] + a = @h.dup + a.taint if taint + a.freeze if frozen + b = a.dup + + assert_equal(a, b) + assert_not_same(a, b) + assert_equal(false, b.frozen?) + assert_equal(a.tainted?, b.tainted?) + end end end @@ -653,21 +650,12 @@ class TestHash < Test::Unit::TestCase assert_not_send([@h, :member?, 'gumby']) end - def hash_hint hv - hv & 0xff - end - def test_rehash a = [ "a", "b" ] c = [ "c", "d" ] h = @cls[ a => 100, c => 300 ] assert_equal(100, h[a]) - - hv = a.hash - begin - a[0] << "z" - end while hash_hint(a.hash) == hash_hint(hv) - + a[0] = "z" assert_nil(h[a]) h.rehash assert_equal(100, h[a]) @@ -695,8 +683,10 @@ class TestHash < Test::Unit::TestCase h.instance_variable_set(:@foo, :foo) h.default = 42 + h.taint h = EnvUtil.suppress_warning {h.reject {false}} assert_instance_of(Hash, h) + assert_not_predicate(h, :tainted?) assert_nil(h.default) assert_not_send([h, :instance_variable_defined?, :@foo]) end @@ -744,14 +734,6 @@ class TestHash < Test::Unit::TestCase assert_predicate(h, :compare_by_identity?) end - def test_replace_bug15358 - h1 = {} - h2 = {a:1,b:2,c:3,d:4,e:5} - h2.replace(h1) - GC.start - assert(true) - end - def test_shift h = @h.dup @@ -821,6 +803,11 @@ class TestHash < Test::Unit::TestCase assert_equal([3,4], a.delete([3,4])) assert_equal([5,6], a.delete([5,6])) assert_equal(0, a.length) + + h = @cls[ 1=>2, 3=>4, 5=>6 ] + h.taint + a = h.to_a + assert_equal(true, a.tainted?) end def test_to_hash @@ -857,16 +844,6 @@ class TestHash < Test::Unit::TestCase assert_equal("nope42", h[42]) end - def test_to_h_block - h = @h.to_h {|k, v| [k.to_s, v.to_s]} - assert_equal({ - "1"=>"one", "2"=>"two", "3"=>"three", to_s=>"self", - "true"=>"true", ""=>"nil", "nil"=>"" - }, - h) - assert_instance_of(Hash, h) - end - def test_nil_to_h h = nil.to_h assert_equal({}, h) @@ -877,7 +854,7 @@ class TestHash < Test::Unit::TestCase def test_to_s h = @cls[ 1 => 2, "cat" => "dog", 1.5 => :fred ] assert_equal(h.inspect, h.to_s) - assert_deprecated_warning { $, = ":" } + $, = ":" assert_equal(h.inspect, h.to_s) h = @cls[] assert_equal(h.inspect, h.to_s) @@ -928,8 +905,8 @@ class TestHash < Test::Unit::TestCase def test_create assert_equal({1=>2, 3=>4}, @cls[[[1,2],[3,4]]]) - assert_raise(ArgumentError) { @cls[0, 1, 2] } - assert_raise(ArgumentError) { @cls[[[0, 1], 2]] } + assert_raise(ArgumentError) { Hash[0, 1, 2] } + assert_warning(/wrong element type Integer at 1 /) {@cls[[[1, 2], 3]]} bug5406 = '[ruby-core:39945]' assert_raise(ArgumentError, bug5406) { @cls[[[1, 2], [3, 4, 5]]] } assert_equal({1=>2, 3=>4}, @cls[1,2,3,4]) @@ -946,7 +923,7 @@ class TestHash < Test::Unit::TestCase end def test_fetch2 - assert_equal(:bar, assert_warning(/block supersedes default value argument/) {@h.fetch(0, :foo) { :bar }}) + assert_equal(:bar, @h.fetch(0, :foo) { :bar }) end def test_default_proc @@ -1013,8 +990,10 @@ class TestHash < Test::Unit::TestCase h.instance_variable_set(:@foo, :foo) h.default = 42 + h.taint h = h.select {true} assert_instance_of(Hash, h) + assert_not_predicate(h, :tainted?) assert_nil(h.default) assert_not_send([h, :instance_variable_defined?, :@foo]) end @@ -1035,50 +1014,6 @@ class TestHash < Test::Unit::TestCase assert_equal({}, {}.slice) end - def test_except - h = @cls[1=>2,3=>4,5=>6] - assert_equal({5=>6}, h.except(1, 3)) - assert_equal({1=>2,3=>4,5=>6}, h.except(7)) - assert_equal({1=>2,3=>4,5=>6}, h.except) - assert_equal({}, {}.except) - end - - def test_filter - assert_equal({3=>4,5=>6}, @cls[1=>2,3=>4,5=>6].filter {|k, v| k + v >= 7 }) - - base = @cls[ 1 => 'one', '2' => false, true => 'true', 'cat' => 99 ] - h1 = @cls[ '2' => false, 'cat' => 99 ] - h2 = @cls[ 1 => 'one', true => 'true' ] - h3 = @cls[ 1 => 'one', true => 'true', 'cat' => 99 ] - - h = base.dup - assert_equal(h, h.filter { true }) - assert_equal(@cls[], h.filter { false }) - - h = base.dup - assert_equal(h1, h.filter {|k,v| k.instance_of?(String) }) - - assert_equal(h2, h.filter {|k,v| v.instance_of?(String) }) - - assert_equal(h3, h.filter {|k,v| v }) - assert_equal(base, h) - - h.instance_variable_set(:@foo, :foo) - h.default = 42 - h = h.filter {true} - assert_instance_of(Hash, h) - assert_nil(h.default) - assert_not_send([h, :instance_variable_defined?, :@foo]) - end - - def test_filter! - h = @cls[1=>2,3=>4,5=>6] - assert_equal(h, h.filter! {|k, v| k + v >= 7 }) - assert_equal({3=>4,5=>6}, h) - h = @cls[1=>2,3=>4,5=>6] - assert_equal(nil, h.filter!{true}) - end - def test_clear2 assert_equal({}, @cls[1=>2,3=>4,5=>6].clear) h = @cls[1=>2,3=>4,5=>6] @@ -1111,7 +1046,6 @@ class TestHash < Test::Unit::TestCase def o.to_hash; @cls[]; end def o.==(x); true; end assert_equal({}, o) - o.singleton_class.remove_method(:==) def o.==(x); false; end assert_not_equal({}, o) @@ -1128,7 +1062,6 @@ class TestHash < Test::Unit::TestCase def o.to_hash; @cls[]; end def o.eql?(x); true; end assert_send([@cls[], :eql?, o]) - o.singleton_class.remove_method(:eql?) def o.eql?(x); false; end assert_not_send([@cls[], :eql?, o]) end @@ -1149,35 +1082,11 @@ class TestHash < Test::Unit::TestCase assert_equal({1=>6, 3=>4, 5=>7}, h1) end - def test_update3 - h1 = @cls[1=>2, 3=>4] - h1.update() - assert_equal({1=>2, 3=>4}, h1) - h2 = {1=>3, 5=>7} - h3 = {1=>1, 2=>4} - h1.update(h2, h3) - assert_equal({1=>1, 2=>4, 3=>4, 5=>7}, h1) - end - - def test_update4 - h1 = @cls[1=>2, 3=>4] - h1.update(){|k, v1, v2| k + v1 + v2 } - assert_equal({1=>2, 3=>4}, h1) - h2 = {1=>3, 5=>7} - h3 = {1=>1, 2=>4} - h1.update(h2, h3){|k, v1, v2| k + v1 + v2 } - assert_equal({1=>8, 2=>4, 3=>4, 5=>7}, h1) - end - def test_merge h1 = @cls[1=>2, 3=>4] h2 = {1=>3, 5=>7} - h3 = {1=>1, 2=>4} - assert_equal({1=>2, 3=>4}, h1.merge()) assert_equal({1=>3, 3=>4, 5=>7}, h1.merge(h2)) assert_equal({1=>6, 3=>4, 5=>7}, h1.merge(h2) {|k, v1, v2| k + v1 + v2 }) - assert_equal({1=>1, 2=>4, 3=>4, 5=>7}, h1.merge(h2, h3)) - assert_equal({1=>8, 2=>4, 3=>4, 5=>7}, h1.merge(h2, h3) {|k, v1, v2| k + v1 + v2 }) end def test_assoc @@ -1636,8 +1545,6 @@ class TestHash < Test::Unit::TestCase } assert_equal([10, 20, 30], [1, 2, 3].map(&h)) - - assert_equal(true, h.to_proc.lambda?) end def test_transform_keys @@ -1652,9 +1559,6 @@ class TestHash < Test::Unit::TestCase y = x.transform_keys.with_index {|k, i| "#{k}.#{i}" } assert_equal(%w(a.0 b.1 c.2), y.keys) - - assert_equal({A: 1, B: 2, c: 3}, x.transform_keys({a: :A, b: :B, d: :D})) - assert_equal({A: 1, B: 2, "c" => 3}, x.transform_keys({a: :A, b: :B, d: :D}, &:to_s)) end def test_transform_keys_bang @@ -1677,27 +1581,13 @@ class TestHash < Test::Unit::TestCase x = @cls[true => :a, false => :b] x.transform_keys! {|k| !k } assert_equal([false, :a, true, :b], x.flatten) - - x = @cls[a: 1, b: 2, c: 3] - x.transform_keys!({a: :A, b: :B, d: :D}) - assert_equal({A: 1, B: 2, c: 3}, x) - x = @cls[a: 1, b: 2, c: 3] - x.transform_keys!({a: :A, b: :B, d: :D}, &:to_s) - assert_equal({A: 1, B: 2, "c" => 3}, x) end def test_transform_values x = @cls[a: 1, b: 2, c: 3] - x.default = 42 y = x.transform_values {|v| v ** 2 } assert_equal([1, 4, 9], y.values_at(:a, :b, :c)) assert_not_same(x, y) - assert_nil(y.default) - - x.default_proc = proc {|h, k| k} - y = x.transform_values {|v| v ** 2 } - assert_nil(y.default_proc) - assert_nil(y.default) y = x.transform_values.with_index {|v, i| "#{v}.#{i}" } assert_equal(%w(1.0 2.1 3.2), y.values_at(:a, :b, :c)) @@ -1721,44 +1611,6 @@ class TestHash < Test::Unit::TestCase assert_equal(0, 1_000_000.times.count{a=Object.new.hash; b=Object.new.hash; 0 + a + b != 0 + b + a}, bug14218) end - def test_reserved_hash_val - s = Struct.new(:hash) - h = {} - keys = [*0..8] - keys.each {|i| h[s.new(i)]=true} - msg = proc {h.inspect} - assert_equal(keys, h.keys.map(&:hash), msg) - end - - def hrec h, n, &b - if n > 0 - h.each{hrec(h, n-1, &b)} - else - yield - end - end - - def test_huge_iter_level - nrec = 200 - - h = @cls[a: 1] - hrec(h, nrec){} - h[:c] = 3 - assert_equal(3, h[:c]) - - h = @cls[a: 1] - h.freeze # set hidden attribute for a frozen object - hrec(h, nrec){} - assert_equal(1, h.size) - - h = @cls[a: 1] - assert_raise(RuntimeError){ - hrec(h, nrec){ h[:c] = 3 } - } - rescue SystemStackError - # ignore - end - class TestSubHash < TestHash class SubHash < Hash def reject(*) @@ -1770,99 +1622,5 @@ class TestHash < Test::Unit::TestCase @cls = SubHash super end - - def test_reject - assert_warning(/extra states are no longer copied/) do - super - end - end - end - - ruby2_keywords def get_flagged_hash(*args) - args.last - end - - def check_flagged_hash(k: :NG) - k - end - - def test_ruby2_keywords_hash? - flagged_hash = get_flagged_hash(k: 1) - assert_equal(true, Hash.ruby2_keywords_hash?(flagged_hash)) - assert_equal(false, Hash.ruby2_keywords_hash?({})) - assert_raise(TypeError) { Hash.ruby2_keywords_hash?(1) } - end - - def test_ruby2_keywords_hash - hash = {k: 1} - assert_equal(false, Hash.ruby2_keywords_hash?(hash)) - hash = Hash.ruby2_keywords_hash(hash) - assert_equal(true, Hash.ruby2_keywords_hash?(hash)) - assert_equal(1, check_flagged_hash(*[hash])) - assert_raise(TypeError) { Hash.ruby2_keywords_hash(1) } - end - - def test_ar2st - # insert - obj = Object.new - obj.instance_variable_set(:@h, h = {}) - def obj.hash - 10.times{|i| @h[i] = i} - 0 - end - def obj.inspect - 'test' - end - h[obj] = true - assert_equal '{0=>0, 1=>1, 2=>2, 3=>3, 4=>4, 5=>5, 6=>6, 7=>7, 8=>8, 9=>9, test=>true}', h.inspect - - # delete - obj = Object.new - obj.instance_variable_set(:@h, h = {}) - def obj.hash - 10.times{|i| @h[i] = i} - 0 - end - def obj.inspect - 'test' - end - def obj.eql? other - other.class == Object - end - obj2 = Object.new - def obj2.hash - 0 - end - - h[obj2] = true - h.delete obj - assert_equal '{0=>0, 1=>1, 2=>2, 3=>3, 4=>4, 5=>5, 6=>6, 7=>7, 8=>8, 9=>9}', h.inspect - - # lookup - obj = Object.new - obj.instance_variable_set(:@h, h = {}) - def obj.hash - 10.times{|i| @h[i] = i} - 0 - end - def obj.inspect - 'test' - end - def obj.eql? other - other.class == Object - end - obj2 = Object.new - def obj2.hash - 0 - end - - h[obj2] = true - assert_equal true, h[obj] - end - - def test_bug_12706 - assert_raise(ArgumentError) do - {a: 1}.each(&->(k, v) {}) - end end end diff --git a/test/ruby/test_ifunless.rb b/test/ruby/test_ifunless.rb index f68e5154a2..d533e155bc 100644 --- a/test/ruby/test_ifunless.rb +++ b/test/ruby/test_ifunless.rb @@ -1,7 +1,7 @@ # frozen_string_literal: false require 'test/unit' -class TestIfUnless < Test::Unit::TestCase +class TestIfunless < Test::Unit::TestCase def test_if_unless x = 'test'; assert(if x == x then true else false end) diff --git a/test/ruby/test_inlinecache.rb b/test/ruby/test_inlinecache.rb deleted file mode 100644 index 6c2d86aefd..0000000000 --- a/test/ruby/test_inlinecache.rb +++ /dev/null @@ -1,110 +0,0 @@ -# -*- coding: us-ascii -*- -# frozen_string_literal: true - -require 'test/unit' - -class TestMethod < Test::Unit::TestCase - def test_alias - m0 = Module.new do - def foo; :M0 end - end - m1 = Module.new do - include m0 - end - c = Class.new do - include m1 - alias bar foo - end - d = Class.new(c) do - end - - test = -> do - d.new.bar - end - - assert_equal :M0, test[] - - c.class_eval do - def bar - :C - end - end - - assert_equal :C, test[] - end - - def test_zsuper - assert_separately [], <<-EOS - class C - private def foo - :C - end - end - - class D < C - public :foo - end - - class E < D; end - class F < E; end - - test = -> do - F.new().foo - end - - assert_equal :C, test[] - - class E - def foo; :E; end - end - - assert_equal :E, test[] - EOS - end - - def test_module_methods_redefiniton - m0 = Module.new do - def foo - super - end - end - - c1 = Class.new do - def foo - :C1 - end - end - - c2 = Class.new do - def foo - :C2 - end - end - - d1 = Class.new(c1) do - include m0 - end - - d2 = Class.new(c2) do - include m0 - end - - assert_equal :C1, d1.new.foo - - m = Module.new do - def foo - super - end - end - - d1.class_eval do - include m - end - - d2.class_eval do - include m - end - - assert_equal :C2, d2.new.foo - end -end diff --git a/test/ruby/test_integer.rb b/test/ruby/test_integer.rb index 2755987276..1b485760e3 100644 --- a/test/ruby/test_integer.rb +++ b/test/ruby/test_integer.rb @@ -10,46 +10,7 @@ class TestInteger < Test::Unit::TestCase self.class.bdsize(x) end - FIXNUM_MIN = RbConfig::LIMITS['FIXNUM_MIN'] - FIXNUM_MAX = RbConfig::LIMITS['FIXNUM_MAX'] - def test_aref - - [ - *-16..16, - *(FIXNUM_MIN-2)..(FIXNUM_MIN+2), - *(FIXNUM_MAX-2)..(FIXNUM_MAX+2), - ].each do |n| - (-64..64).each do |idx| - assert_equal((n >> idx) & 1, n[idx]) - end - [*-66..-62, *-34..-30, *-5..5, *30..34, *62..66].each do |idx| - (0..100).each do |len| - assert_equal((n >> idx) & ((1 << len) - 1), n[idx, len], "#{ n }[#{ idx }, #{ len }]") - end - (0..100).each do |len| - assert_equal((n >> idx) & ((1 << (len + 1)) - 1), n[idx..idx+len], "#{ n }[#{ idx }..#{ idx+len }]") - assert_equal((n >> idx) & ((1 << len) - 1), n[idx...idx+len], "#{ n }[#{ idx }...#{ idx+len }]") - end - - # endless - assert_equal((n >> idx), n[idx..], "#{ n }[#{ idx }..]") - assert_equal((n >> idx), n[idx...], "#{ n }[#{ idx }...#]") - - # beginless - if idx >= 0 && n & ((1 << (idx + 1)) - 1) != 0 - assert_raise(ArgumentError, "#{ n }[..#{ idx }]") { n[..idx] } - else - assert_equal(0, n[..idx], "#{ n }[..#{ idx }]") - end - if idx >= 0 && n & ((1 << idx) - 1) != 0 - assert_raise(ArgumentError, "#{ n }[...#{ idx }]") { n[...idx] } - else - assert_equal(0, n[...idx], "#{ n }[...#{ idx }]") - end - end - end - # assert_equal(1, (1 << 0x40000000)[0x40000000], "[ruby-dev:31271]") # assert_equal(0, (-1 << 0x40000001)[0x40000000], "[ruby-dev:31271]") big_zero = 0x40000000.coerce(0)[0] @@ -63,32 +24,6 @@ class TestInteger < Test::Unit::TestCase rescue nil end, "[ruby-dev:32084] [ruby-dev:34547]") - - x = EnvUtil.suppress_warning {2 ** -0x4000000000000000} - assert_in_delta(0.0, (x / 2), Float::EPSILON) - - <<~EXPRS.each_line.with_index(__LINE__+1) do |expr, line| - crash01: 111r+11**-11111161111111 - crash02: 1118111111111**-1111111111111111**1+1==11111 - crash03: -1111111**-1111*11 - -1111111** -111111111 - crash04: 1118111111111** -1111111111111111**1+11111111111**1 ===111 - crash05: 11** -111155555555555555 -55 !=5-555 - crash07: 1 + 111111111**-1111811111 - crash08: 18111111111**-1111111111111111**1 + 1111111111**-1111**1 - crash10: -7 - -1111111** -1111**11 - crash12: 1118111111111** -1111111111111111**1 + 1111 - -1111111** -1111*111111111119 - crash13: 1.0i - -1111111** -111111111 - crash14: 11111**111111111**111111 * -11111111111111111111**-111111111111 - crash15: ~1**1111 + -~1**~1**111 - crash17: 11** -1111111**1111 /11i - crash18: 5555i**-5155 - -9111111**-1111**11 - crash19: 111111*-11111111111111111111**-1111111111111111 - crash20: 1111**111-11**-11111**11 - crash21: 11**-10111111119-1i -1r - EXPRS - name, expr = expr.split(':', 2) - assert_ruby_status(%w"-W0", expr, name) - end end def test_lshift @@ -157,17 +92,6 @@ class TestInteger < Test::Unit::TestCase assert_equal(2 ** 50, Integer(2.0 ** 50)) assert_raise(TypeError) { Integer(nil) } - bug14552 = '[ruby-core:85813]' - obj = Object.new - def obj.to_int; "str"; end - assert_raise(TypeError, bug14552) { Integer(obj) } - def obj.to_i; 42; end - assert_equal(42, Integer(obj), bug14552) - - obj = Object.new - def obj.to_i; "str"; end - assert_raise(TypeError) { Integer(obj) } - bug6192 = '[ruby-core:43566]' assert_raise(Encoding::CompatibilityError, bug6192) {Integer("0".encode("utf-16be"))} assert_raise(Encoding::CompatibilityError, bug6192) {Integer("0".encode("utf-16le"))} @@ -192,61 +116,6 @@ class TestInteger < Test::Unit::TestCase end; end - def test_Integer_with_invalid_exception - assert_raise(ArgumentError) { - Integer("0", exception: 1) - } - end - - def test_Integer_with_exception_keyword - assert_nothing_raised(ArgumentError) { - assert_equal(nil, Integer("1z", exception: false)) - } - assert_nothing_raised(ArgumentError) { - assert_equal(nil, Integer(Object.new, exception: false)) - } - assert_nothing_raised(ArgumentError) { - o = Object.new - def o.to_i; 42.5; end - assert_equal(nil, Integer(o, exception: false)) - } - assert_nothing_raised(ArgumentError) { - o = Object.new - def o.to_i; raise; end - assert_equal(nil, Integer(o, exception: false)) - } - assert_nothing_raised(ArgumentError) { - o = Object.new - def o.to_int; raise; end - assert_equal(nil, Integer(o, exception: false)) - } - assert_nothing_raised(FloatDomainError) { - assert_equal(nil, Integer(Float::INFINITY, exception: false)) - } - assert_nothing_raised(FloatDomainError) { - assert_equal(nil, Integer(-Float::INFINITY, exception: false)) - } - assert_nothing_raised(FloatDomainError) { - assert_equal(nil, Integer(Float::NAN, exception: false)) - } - - assert_raise(ArgumentError) { - Integer("1z", exception: true) - } - assert_raise(TypeError) { - Integer(nil, exception: true) - } - assert_nothing_raised(TypeError) { - assert_equal(nil, Integer(nil, exception: false)) - } - - assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") - begin; - class Integer;def method_missing(*);"";end;end - assert_equal(0, Integer("0", 2)) - end; - end - def test_int_p assert_not_predicate(1.0, :integer?) assert_predicate(1, :integer?) @@ -260,7 +129,6 @@ class TestInteger < Test::Unit::TestCase assert_equal("a", "a".ord.chr) assert_raise(RangeError) { (-1).chr } assert_raise(RangeError) { 0x100.chr } - assert_raise_with_message(RangeError, "3000000000 out of char range") { 3_000_000_000.chr } end def test_upto @@ -641,9 +509,6 @@ class TestInteger < Test::Unit::TestCase failures << n unless root*root <= n && (root+1)*(root+1) > n end assert_empty(failures, bug13440) - - x = 0xffff_ffff_ffff_ffff - assert_equal(x, Integer.sqrt(x ** 2), "[ruby-core:95453]") end def test_fdiv diff --git a/test/ruby/test_io.rb b/test/ruby/test_io.rb index 9f9318eaf7..178e3c3d7e 100644 --- a/test/ruby/test_io.rb +++ b/test/ruby/test_io.rb @@ -49,8 +49,8 @@ class TestIO < Test::Unit::TestCase end flunk("timeout") unless wt.join(10) && rt.join(10) ensure - w&.close - r&.close + w.close unless !w || w.closed? + r.close unless !r || r.closed? (wt.kill; wt.join) if wt (rt.kill; rt.join) if rt raise we if we @@ -62,8 +62,8 @@ class TestIO < Test::Unit::TestCase begin yield r, w ensure - r.close - w.close + r.close unless r.closed? + w.close unless w.closed? end end @@ -84,17 +84,12 @@ class TestIO < Test::Unit::TestCase } end - def trapping_usr2 - @usr2_rcvd = 0 - r, w = IO.pipe - trap(:USR2) do - w.write([@usr2_rcvd += 1].pack('L')) - end - yield r + def trapping_usr1 + @usr1_rcvd = 0 + trap(:USR1) { @usr1_rcvd += 1 } + yield ensure - trap(:USR2, "DEFAULT") - w&.close - r&.close + trap(:USR1, "DEFAULT") end def test_pipe @@ -113,65 +108,6 @@ class TestIO < Test::Unit::TestCase ].each{|thr| thr.join} end - def test_binmode_pipe - EnvUtil.with_default_internal(Encoding::UTF_8) do - EnvUtil.with_default_external(Encoding::UTF_8) do - begin - reader0, writer0 = IO.pipe - reader0.binmode - writer0.binmode - - reader1, writer1 = IO.pipe - - reader2, writer2 = IO.pipe(binmode: true) - assert_predicate writer0, :binmode? - assert_predicate writer2, :binmode? - assert_equal writer0.binmode?, writer2.binmode? - assert_equal writer0.external_encoding, writer2.external_encoding - assert_equal writer0.internal_encoding, writer2.internal_encoding - assert_predicate reader0, :binmode? - assert_predicate reader2, :binmode? - assert_equal reader0.binmode?, reader2.binmode? - assert_equal reader0.external_encoding, reader2.external_encoding - assert_equal reader0.internal_encoding, reader2.internal_encoding - - reader3, writer3 = IO.pipe("UTF-8:UTF-8", binmode: true) - assert_predicate writer3, :binmode? - assert_equal writer1.external_encoding, writer3.external_encoding - assert_equal writer1.internal_encoding, writer3.internal_encoding - assert_predicate reader3, :binmode? - assert_equal reader1.external_encoding, reader3.external_encoding - assert_equal reader1.internal_encoding, reader3.internal_encoding - - reader4, writer4 = IO.pipe("UTF-8:UTF-8", binmode: true) - assert_predicate writer4, :binmode? - assert_equal writer1.external_encoding, writer4.external_encoding - assert_equal writer1.internal_encoding, writer4.internal_encoding - assert_predicate reader4, :binmode? - assert_equal reader1.external_encoding, reader4.external_encoding - assert_equal reader1.internal_encoding, reader4.internal_encoding - - reader5, writer5 = IO.pipe("UTF-8", "UTF-8", binmode: true) - assert_predicate writer5, :binmode? - assert_equal writer1.external_encoding, writer5.external_encoding - assert_equal writer1.internal_encoding, writer5.internal_encoding - assert_predicate reader5, :binmode? - assert_equal reader1.external_encoding, reader5.external_encoding - assert_equal reader1.internal_encoding, reader5.internal_encoding - ensure - [ - reader0, writer0, - reader1, writer1, - reader2, writer2, - reader3, writer3, - reader4, writer4, - reader5, writer5, - ].compact.map(&:close) - end - end - end - end - def test_pipe_block x = nil ret = IO.pipe {|r, w| @@ -405,12 +341,25 @@ class TestIO < Test::Unit::TestCase } end + def test_codepoints + make_tempfile {|t| + bug2959 = '[ruby-core:28650]' + a = "" + File.open(t, 'rt') {|f| + assert_warn(/deprecated/) { + f.codepoints {|c| a << c} + } + } + assert_equal("foo\nbar\nbaz\n", a, bug2959) + } + end + def test_rubydev33072 t = make_tempfile path = t.path t.close! assert_raise(Errno::ENOENT, "[ruby-dev:33072]") do - File.read(path, nil, nil, **{}) + File.read(path, nil, nil, {}) end end @@ -607,14 +556,14 @@ class TestIO < Test::Unit::TestCase if have_nonblock? def test_copy_stream_no_busy_wait - skip "MJIT has busy wait on GC. This sometimes fails with --jit." if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? - skip "multiple threads already active" if Thread.list.size > 1 - msg = 'r58534 [ruby-core:80969] [Backport #13533]' IO.pipe do |r,w| r.nonblock = true - assert_cpu_usage_low(msg, stop: ->{w.close}) do - IO.copy_stream(r, IO::NULL) + assert_cpu_usage_low(msg) do + th = Thread.new { IO.copy_stream(r, IO::NULL) } + sleep 0.1 + w.close + th.join end end end @@ -628,6 +577,7 @@ class TestIO < Test::Unit::TestCase w2.nonblock = true rescue Errno::EBADF skip "nonblocking IO for pipe is not implemented" + break end s = w2.syswrite("a" * 100000) t = Thread.new { sleep 0.1; r2.read } @@ -693,7 +643,7 @@ class TestIO < Test::Unit::TestCase assert_equal(bigcontent[30, 40], File.read("bigdst")) assert_equal(0, f.pos) rescue NotImplementedError - #skip "pread(2) is not implemented." + #skip "pread(2) is not implemtented." end } } @@ -925,21 +875,20 @@ class TestIO < Test::Unit::TestCase rescue Errno::EBADF skip "nonblocking IO for pipe is not implemented" end - trapping_usr2 do |rd| + trapping_usr1 do nr = 30 begin pid = fork do s1.close IO.select([s2]) - Process.kill(:USR2, Process.ppid) - buf = String.new(capacity: 16384) - nil while s2.read(16384, buf) + Process.kill(:USR1, Process.ppid) + s2.read end s2.close nr.times do assert_equal megacontent.bytesize, IO.copy_stream("megasrc", s1) end - assert_equal(1, rd.read(4).unpack1('L')) + assert_equal(1, @usr1_rcvd) ensure s1.close _, status = Process.waitpid2(pid) if pid @@ -1243,11 +1192,10 @@ class TestIO < Test::Unit::TestCase def test_copy_stream_to_duplex_io result = IO.pipe {|a,w| - th = Thread.start {w.puts "yes"; w.close} + Thread.start {w.puts "yes"; w.close} IO.popen([EnvUtil.rubybin, '-pe$_="#$.:#$_"'], "r+") {|b| IO.copy_stream(a, b) b.close_write - assert_join_threads([th]) b.read } } @@ -1260,7 +1208,7 @@ class TestIO < Test::Unit::TestCase opts = {} if defined?(Process::RLIMIT_NPROC) lim = Process.getrlimit(Process::RLIMIT_NPROC)[1] - opts[:rlimit_nproc] = [lim, 2048].min + opts[:rlimit_nproc] = [lim, 1024].min end f = IO.popen([ruby] + args, 'r+', opts) pid = f.pid @@ -1348,13 +1296,6 @@ class TestIO < Test::Unit::TestCase assert_empty(err) end - def test_write_no_args - IO.pipe do |r, w| - assert_equal 0, w.write, '[ruby-core:86285] [Bug #14338]' - assert_equal :wait_readable, r.read_nonblock(1, exception: false) - end - end - def test_write_non_writable with_pipe do |r, w| assert_raise(IOError) do @@ -1382,7 +1323,7 @@ class TestIO < Test::Unit::TestCase def test_dup_many opts = {} opts[:rlimit_nofile] = 1024 if defined?(Process::RLIMIT_NOFILE) - assert_separately([], <<-'End', **opts) + assert_separately([], <<-'End', opts) a = [] assert_raise(Errno::EMFILE, Errno::ENFILE, Errno::ENOMEM) do loop {a << IO.pipe} @@ -1555,14 +1496,7 @@ class TestIO < Test::Unit::TestCase } end if have_nonblock? - def test_read_nonblock_invalid_exception - with_pipe {|r, w| - assert_raise(ArgumentError) {r.read_nonblock(4096, exception: 1)} - } - end if have_nonblock? - def test_read_nonblock_no_exceptions - skip '[ruby-core:90895] MJIT worker may leave fd open in a forked child' if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # TODO: consider acquiring GVL from MJIT worker. with_pipe {|r, w| assert_equal :wait_readable, r.read_nonblock(4096, exception: false) w.puts "HI!" @@ -1597,12 +1531,6 @@ class TestIO < Test::Unit::TestCase } end if have_nonblock? - def test_write_nonblock_invalid_exception - with_pipe {|r, w| - assert_raise(ArgumentError) {w.write_nonblock(4096, exception: 1)} - } - end if have_nonblock? - def test_write_nonblock_no_exceptions with_pipe {|r, w| loop { @@ -1763,25 +1691,23 @@ class TestIO < Test::Unit::TestCase f.gets; assert_equal(3, $.) end SRC - } - end - def test_set_lineno_gets - pipe(proc do |w| - w.puts "foo" - w.puts "bar" - w.puts "baz" - w.close - end, proc do |r| - r.gets; assert_equal(1, $.) - r.gets; assert_equal(2, $.) - r.lineno = 1000; assert_equal(2, $.) - r.gets; assert_equal(1001, $.) - r.gets; assert_equal(1001, $.) - end) + pipe(proc do |w| + w.puts "foo" + w.puts "bar" + w.puts "baz" + w.close + end, proc do |r| + r.gets; assert_equal(1, $.) + r.gets; assert_equal(2, $.) + r.lineno = 1000; assert_equal(2, $.) + r.gets; assert_equal(1001, $.) + r.gets; assert_equal(1001, $.) + end) + } end - def test_set_lineno_readline + def test_readline pipe(proc do |w| w.puts "foo" w.puts "bar" @@ -1809,7 +1735,8 @@ class TestIO < Test::Unit::TestCase end) end - def test_each_line + def test_lines + verbose, $VERBOSE = $VERBOSE, nil pipe(proc do |w| w.puts "foo" w.puts "bar" @@ -1817,17 +1744,20 @@ class TestIO < Test::Unit::TestCase w.close end, proc do |r| e = nil - assert_warn('') { - e = r.each_line + assert_warn(/deprecated/) { + e = r.lines } assert_equal("foo\n", e.next) assert_equal("bar\n", e.next) assert_equal("baz\n", e.next) assert_raise(StopIteration) { e.next } end) + ensure + $VERBOSE = verbose end - def test_each_byte2 + def test_bytes + verbose, $VERBOSE = $VERBOSE, nil pipe(proc do |w| w.binmode w.puts "foo" @@ -1836,17 +1766,20 @@ class TestIO < Test::Unit::TestCase w.close end, proc do |r| e = nil - assert_warn('') { - e = r.each_byte + assert_warn(/deprecated/) { + e = r.bytes } (%w(f o o) + ["\n"] + %w(b a r) + ["\n"] + %w(b a z) + ["\n"]).each do |c| assert_equal(c.ord, e.next) end assert_raise(StopIteration) { e.next } end) + ensure + $VERBOSE = verbose end - def test_each_char2 + def test_chars + verbose, $VERBOSE = $VERBOSE, nil pipe(proc do |w| w.puts "foo" w.puts "bar" @@ -1854,14 +1787,16 @@ class TestIO < Test::Unit::TestCase w.close end, proc do |r| e = nil - assert_warn('') { - e = r.each_char + assert_warn(/deprecated/) { + e = r.chars } (%w(f o o) + ["\n"] + %w(b a r) + ["\n"] + %w(b a z) + ["\n"]).each do |c| assert_equal(c, e.next) end assert_raise(StopIteration) { e.next } end) + ensure + $VERBOSE = verbose end def test_readbyte @@ -1926,6 +1861,7 @@ class TestIO < Test::Unit::TestCase def test_pos make_tempfile {|t| + open(t.path, IO::RDWR|IO::CREAT|IO::TRUNC, 0600) do |f| f.write "Hello" assert_equal(5, f.pos) @@ -2208,10 +2144,6 @@ class TestIO < Test::Unit::TestCase end def test_autoclose_true_closed_by_finalizer - # http://ci.rvm.jp/results/trunk-mjit@silicon-docker/1465760 - # http://ci.rvm.jp/results/trunk-mjit@silicon-docker/1469765 - skip 'this randomly fails with MJIT' if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? - feature2250 = '[ruby-core:26222]' pre = 'ft2250' t = Tempfile.new(pre) @@ -2227,7 +2159,7 @@ class TestIO < Test::Unit::TestCase assert_raise(Errno::EBADF, feature2250) {t.close} end ensure - t&.close! + t.close! end def test_autoclose_false_closed_by_finalizer @@ -2257,21 +2189,6 @@ class TestIO < Test::Unit::TestCase assert_equal(o, o2) end - def test_open_redirect_keyword - o = Object.new - def o.to_open(**kw); kw; end - assert_equal({:a=>1}, open(o, a: 1)) - - assert_raise(ArgumentError) { open(o, {a: 1}) } - - class << o - remove_method(:to_open) - end - def o.to_open(kw); kw; end - assert_equal({:a=>1}, open(o, a: 1)) - assert_equal({:a=>1}, open(o, {a: 1})) - end - def test_open_pipe open("|" + EnvUtil.rubybin, "r+") do |f| f.puts "puts 'foo'" @@ -2282,10 +2199,10 @@ class TestIO < Test::Unit::TestCase def test_read_command assert_equal("foo\n", IO.read("|echo foo")) - assert_raise(Errno::ENOENT, Errno::EINVAL) do + assert_warn(/invoke external command/) do File.read("|#{EnvUtil.rubybin} -e puts") end - assert_raise(Errno::ENOENT, Errno::EINVAL) do + assert_warn(/invoke external command/) do File.binread("|#{EnvUtil.rubybin} -e puts") end assert_raise(Errno::ENOENT, Errno::EINVAL) do @@ -2294,9 +2211,6 @@ class TestIO < Test::Unit::TestCase assert_raise(Errno::ENOENT, Errno::EINVAL) do Class.new(IO).binread("|#{EnvUtil.rubybin} -e puts") end - assert_raise(Errno::ESPIPE) do - IO.read("|echo foo", 1, 1) - end end def test_reopen @@ -2340,13 +2254,13 @@ class TestIO < Test::Unit::TestCase def test_reopen_inherit mkcdtmpdir { - system(EnvUtil.rubybin, '-e', <<-"End") + system(EnvUtil.rubybin, '-e', <<"End") f = open("out", "w") STDOUT.reopen(f) STDERR.reopen(f) system(#{EnvUtil.rubybin.dump}, '-e', 'STDOUT.print "out"') system(#{EnvUtil.rubybin.dump}, '-e', 'STDERR.print "err"') - End +End assert_equal("outerr", File.read("out")) } end @@ -2407,7 +2321,7 @@ class TestIO < Test::Unit::TestCase t end ensure - t&.close(true) if block_given? + t.close(true) if t and block_given? end def test_reopen_encoding @@ -2467,17 +2381,6 @@ class TestIO < Test::Unit::TestCase end end - def test_reopen_ivar - assert_ruby_status([], "#{<<~"begin;"}\n#{<<~'end;'}") - begin; - f = File.open(IO::NULL) - f.instance_variable_set(:@foo, 42) - f.reopen(STDIN) - f.instance_variable_defined?(:@foo) - f.instance_variable_get(:@foo) - end; - end - def test_foreach a = [] IO.foreach("|" + EnvUtil.rubybin + " -e 'puts :foo; puts :bar; puts :baz'") {|x| a << x } @@ -2493,15 +2396,15 @@ class TestIO < Test::Unit::TestCase assert_equal(["foo\n", "bar\n", "baz\n"], a) a = [] - IO.foreach(t.path, :mode => "r") {|x| a << x } + IO.foreach(t.path, {:mode => "r" }) {|x| a << x } assert_equal(["foo\n", "bar\n", "baz\n"], a) a = [] - IO.foreach(t.path, :open_args => []) {|x| a << x } + IO.foreach(t.path, {:open_args => [] }) {|x| a << x } assert_equal(["foo\n", "bar\n", "baz\n"], a) a = [] - IO.foreach(t.path, :open_args => ["r"]) {|x| a << x } + IO.foreach(t.path, {:open_args => ["r"] }) {|x| a << x } assert_equal(["foo\n", "bar\n", "baz\n"], a) a = [] @@ -2557,13 +2460,11 @@ class TestIO < Test::Unit::TestCase end def test_print_separators - EnvUtil.suppress_warning { - $, = ':' - $\ = "\n" - } + $, = ':' + $\ = "\n" pipe(proc do |w| w.print('a') - EnvUtil.suppress_warning {w.print('a','b','c')} + w.print('a','b','c') w.close end, proc do |r| assert_equal("a\n", r.gets) @@ -2621,7 +2522,7 @@ class TestIO < Test::Unit::TestCase end capture.clear - assert_deprecated_warning(/[.#]write is outdated/) do + assert_warning(/[.#]write is outdated/) do stdout, $stdout = $stdout, capture puts "hey" ensure @@ -2646,8 +2547,7 @@ class TestIO < Test::Unit::TestCase assert_in_out_err([], "$> = $stderr\nputs 'foo'", [], %w(foo)) - assert_separately(%w[-Eutf-8], "#{<<~"begin;"}\n#{<<~"end;"}") - begin; + assert_separately(%w[-Eutf-8], <<-"end;") # do alias $\u{6a19 6e96 51fa 529b} $stdout x = eval("class X\u{307b 3052}; self; end".encode("euc-jp")) assert_raise_with_message(TypeError, /\\$\u{6a19 6e96 51fa 529b} must.*, X\u{307b 3052} given/) do @@ -2660,6 +2560,7 @@ class TestIO < Test::Unit::TestCase return unless defined?(Fcntl::F_GETFL) make_tempfile {|t| + fd = IO.sysopen(t.path, "w") assert_kind_of(Integer, fd) %w[r r+ w+ a+].each do |mode| @@ -2747,6 +2648,13 @@ class TestIO < Test::Unit::TestCase } end if /freebsd|linux/ =~ RUBY_PLATFORM and defined? File::NOFOLLOW + def test_tainted + make_tempfile {|t| + assert_predicate(File.read(t.path, 4), :tainted?, '[ruby-dev:38826]') + assert_predicate(File.open(t.path) {|f| f.read(4)}, :tainted?, '[ruby-dev:38826]') + } + end + def test_binmode_after_closed make_tempfile {|t| assert_raise(IOError) {t.binmode} @@ -2770,7 +2678,7 @@ __END__ end; 10.times.map do Thread.start do - assert_in_out_err([], src, timeout: 20) {|stdout, stderr| + assert_in_out_err([], src) {|stdout, stderr| assert_no_match(/hi.*hi/, stderr.join, bug3585) } end @@ -2778,6 +2686,7 @@ __END__ end def test_flush_in_finalizer1 + require 'tempfile' bug3910 = '[ruby-dev:42341]' tmp = Tempfile.open("bug3910") {|t| path = t.path @@ -2803,8 +2712,9 @@ __END__ end def test_flush_in_finalizer2 + require 'tempfile' bug3910 = '[ruby-dev:42341]' - Tempfile.create("bug3910") {|t| + Tempfile.open("bug3910") {|t| path = t.path t.close begin @@ -2823,6 +2733,7 @@ __END__ end } end + t.close! } end @@ -2935,7 +2846,7 @@ __END__ end def test_fcntl_lock_linux - pad = 0 + pad=0 Tempfile.create(self.class.name) do |f| r, w = IO.pipe pid = fork do @@ -3116,8 +3027,9 @@ __END__ assert_equal("\00f", File.read(path)) assert_equal(1, File.write(path, "f", 0, encoding: "UTF-8")) assert_equal("ff", File.read(path)) - File.write(path, "foo", Object.new => Object.new) - assert_equal("foo", File.read(path)) + assert_raise(TypeError) { + File.write(path, "foo", Object.new => Object.new) + } end end @@ -3243,7 +3155,7 @@ __END__ f.ioctl(tiocgwinsz, winsize) } ensure - f&.close + f.close if f end end if /^(?:i.?86|x86_64)-linux/ =~ RUBY_PLATFORM @@ -3339,12 +3251,17 @@ __END__ assert_equal 100, buf.bytesize - msg = /can't modify string; temporarily locked/ - assert_raise_with_message(RuntimeError, msg) do + begin buf.replace("") - end + rescue RuntimeError => e + assert_match(/can't modify string; temporarily locked/, e.message) + Thread.pass + end until buf.empty? + + assert_empty(buf, bug6099) assert_predicate(th, :alive?) w.write(data) + Thread.pass while th.alive? th.join end assert_equal(data, buf, bug6099) @@ -3441,17 +3358,10 @@ __END__ tempfiles = [] (0..fd_setsize+1).map {|i| - tempfiles << Tempfile.create("test_io_select_with_many_files") + tempfiles << Tempfile.open("test_io_select_with_many_files") } - begin - IO.select(tempfiles) - ensure - tempfiles.each { |t| - t.close - File.unlink(t.path) - } - end + IO.select(tempfiles) }, bug8080, timeout: 100 end if defined?(Process::RLIMIT_NOFILE) @@ -3625,42 +3535,21 @@ __END__ end def test_open_flag_binary - binary_enc = Encoding.find("BINARY") make_tempfile do |t| open(t.path, File::RDONLY, flags: File::BINARY) do |f| assert_equal true, f.binmode? - assert_equal binary_enc, f.external_encoding end open(t.path, 'r', flags: File::BINARY) do |f| assert_equal true, f.binmode? - assert_equal binary_enc, f.external_encoding end open(t.path, mode: 'r', flags: File::BINARY) do |f| assert_equal true, f.binmode? - assert_equal binary_enc, f.external_encoding - end - open(t.path, File::RDONLY|File::BINARY) do |f| - assert_equal true, f.binmode? - assert_equal binary_enc, f.external_encoding - end - open(t.path, File::RDONLY|File::BINARY, autoclose: true) do |f| - assert_equal true, f.binmode? - assert_equal binary_enc, f.external_encoding end end end if File::BINARY != 0 - def test_exclusive_mode - make_tempfile do |t| - assert_raise(Errno::EEXIST){ open(t.path, 'wx'){} } - assert_raise(ArgumentError){ open(t.path, 'rx'){} } - assert_raise(ArgumentError){ open(t.path, 'ax'){} } - end - end - def test_race_gets_and_close - opt = { signal: :ABRT, timeout: 200 } - assert_separately([], "#{<<-"begin;"}\n#{<<-"end;"}", **opt) + assert_separately([], "#{<<-"begin;"}\n#{<<-"end;"}") bug13076 = '[ruby-core:78845] [Bug #13076]' begin; 10.times do |i| @@ -3682,9 +3571,9 @@ __END__ w.close r.close end - t.each do |th| - assert_same(th, th.join(2), bug13076) - end + assert_nothing_raised(IOError, bug13076) { + t.each(&:join) + } end end; end @@ -3807,7 +3696,6 @@ __END__ end def test_write_no_garbage - skip "multiple threads already active" if Thread.list.size > 1 res = {} ObjectSpace.count_objects(res) # creates strings on first call [ 'foo'.b, '*' * 24 ].each do |buf| @@ -3829,40 +3717,38 @@ __END__ end end end - end - def test_pread - make_tempfile { |t| - open(t.path) do |f| - assert_equal("bar", f.pread(3, 4)) - buf = "asdf" - assert_equal("bar", f.pread(3, 4, buf)) - assert_equal("bar", buf) - assert_raise(EOFError) { f.pread(1, f.size) } - end - } - end if IO.method_defined?(:pread) + def test_pread + make_tempfile { |t| + open(t.path) do |f| + assert_equal("bar", f.pread(3, 4)) + buf = "asdf" + assert_equal("bar", f.pread(3, 4, buf)) + assert_equal("bar", buf) + assert_raise(EOFError) { f.pread(1, f.size) } + end + } + end if IO.method_defined?(:pread) - def test_pwrite - make_tempfile { |t| - open(t.path, IO::RDWR) do |f| - assert_equal(3, f.pwrite("ooo", 4)) - assert_equal("ooo", f.pread(3, 4)) - end - } - end if IO.method_defined?(:pread) and IO.method_defined?(:pwrite) + def test_pwrite + make_tempfile { |t| + open(t.path, IO::RDWR) do |f| + assert_equal(3, f.pwrite("ooo", 4)) + assert_equal("ooo", f.pread(3, 4)) + end + } + end if IO.method_defined?(:pread) and IO.method_defined?(:pwrite) + end def test_select_exceptfds - if Etc.uname[:sysname] == 'SunOS' - str = 'h'.freeze #(???) Only 1 byte with MSG_OOB on Solaris - else - str = 'hello'.freeze + if Etc.uname[:sysname] == 'SunOS' && Etc.uname[:release] == '5.11' + skip "Solaris 11 fails this" end TCPServer.open('localhost', 0) do |svr| con = TCPSocket.new('localhost', svr.addr[1]) acc = svr.accept - assert_equal str.length, con.send(str, Socket::MSG_OOB) + assert_equal 5, con.send('hello', Socket::MSG_OOB) set = IO.select(nil, nil, [acc], 30) assert_equal([[], [], [acc]], set, 'IO#select exceptions array OK') acc.close @@ -3870,100 +3756,20 @@ __END__ end end if Socket.const_defined?(:MSG_OOB) - def test_recycled_fd_close - dot = -'.' - IO.pipe do |sig_rd, sig_wr| - noex = Thread.new do # everything right and never see exceptions :) - until sig_rd.wait_readable(0) - IO.pipe do |r, w| - th = Thread.new { r.read(1) } - w.write(dot) - - assert_same th, th.join(15), '"good" reader timeout' - assert_equal(dot, th.value) - end - end - sig_rd.read(4) - end - 1000.times do |i| # stupid things and make exceptions: - IO.pipe do |r,w| - th = Thread.new do - begin - while r.gets - end - rescue IOError => e - e - end - end - Thread.pass until th.stop? - - r.close - assert_same th, th.join(30), '"bad" reader timeout' - assert_match(/stream closed/, th.value.message) - end - end - sig_wr.write 'done' - assert_same noex, noex.join(20), '"good" writer timeout' - assert_equal 'done', noex.value ,'r63216' - end - end - - def test_select_memory_leak - # avoid malloc arena explosion from glibc and jemalloc: - env = { - 'MALLOC_ARENA_MAX' => '1', - 'MALLOC_ARENA_TEST' => '1', - 'MALLOC_CONF' => 'narenas:1', - } - assert_no_memory_leak([env], "#{<<~"begin;"}\n#{<<~'else;'}", "#{<<~'end;'}", rss: true, timeout: 60) - begin; + def test_select_leak + assert_no_memory_leak([], <<-"end;", <<-"end;", rss: true, timeout: 240) r, w = IO.pipe rset = [r] wset = [w] - exc = StandardError.new(-"select used to leak on exception") - exc.set_backtrace([]) Thread.new { IO.select(rset, wset, nil, 0) }.join - else; - th = Thread.new do - Thread.handle_interrupt(StandardError => :on_blocking) do - begin - IO.select(rset, wset) - rescue - retry - end while true - end - end - 50_000.times do + end; + 20_000.times do + th = Thread.new { IO.select(rset, wset) } Thread.pass until th.stop? - th.raise(exc) + th.kill + th.join + GC.start end - th.kill - th.join end; end - - def test_external_encoding_index - IO.pipe {|r, w| - assert_raise(TypeError) {Marshal.dump(r)} - assert_raise(TypeError) {Marshal.dump(w)} - } - end - - def test_stdout_to_closed_pipe - EnvUtil.invoke_ruby(["-e", "loop {puts :ok}"], "", true, true) do - |in_p, out_p, err_p, pid| - out = out_p.gets - out_p.close - err = err_p.read - ensure - status = Process.wait2(pid)[1] - assert_equal("ok\n", out) - assert_empty(err) - assert_not_predicate(status, :success?) - if Signal.list["PIPE"] - assert_predicate(status, :signaled?) - assert_equal("PIPE", Signal.signame(status.termsig) || status.termsig) - end - end - end end diff --git a/test/ruby/test_io_m17n.rb b/test/ruby/test_io_m17n.rb index 27b16a2a36..9ff5307fc3 100644 --- a/test/ruby/test_io_m17n.rb +++ b/test/ruby/test_io_m17n.rb @@ -23,8 +23,7 @@ class TestIO_M17N < Test::Unit::TestCase def pipe(*args, wp, rp) re, we = nil, nil - kw = args.last.is_a?(Hash) ? args.pop : {} - r, w = IO.pipe(*args, **kw) + r, w = IO.pipe(*args) rt = Thread.new do begin rp.call(r) @@ -776,10 +775,10 @@ EOT assert_equal(eucjp, r.read) end) - assert_raise_with_message(ArgumentError, /invalid encoding name/) do + assert_raise_with_message(ArgumentError, /invalid name encoding/) do with_pipe("UTF-8", "UTF-8".encode("UTF-32BE")) {} end - assert_raise_with_message(ArgumentError, /invalid encoding name/) do + assert_raise_with_message(ArgumentError, /invalid name encoding/) do with_pipe("UTF-8".encode("UTF-32BE")) {} end @@ -2047,19 +2046,19 @@ EOT with_tmpdir { open("raw.txt", "wb", xml: :attr) {|f| f.print '&<>"\''; f.puts "\u4E02\u3042" } content = File.read("raw.txt", :mode=>"rb:ascii-8bit") - assert_equal("\"&<>"'\u4E02\u3042\n\"".force_encoding("ascii-8bit"), content) + assert_equal("\"&<>"'\u4E02\u3042\n\"".force_encoding("ascii-8bit"), content) open("ascii.txt", "wb:us-ascii", xml: :attr) {|f| f.print '&<>"\''; f.puts "\u4E02\u3042" } content = File.read("ascii.txt", :mode=>"rb:ascii-8bit") - assert_equal("\"&<>"'丂あ\n\"".force_encoding("ascii-8bit"), content) + assert_equal("\"&<>"'丂あ\n\"".force_encoding("ascii-8bit"), content) open("iso-2022-jp.txt", "wb:iso-2022-jp", xml: :attr) {|f| f.print '&<>"\''; f.puts "\u4E02\u3042" } content = File.read("iso-2022-jp.txt", :mode=>"rb:ascii-8bit") - assert_equal("\"&<>"'丂\e$B$\"\e(B\n\"".force_encoding("ascii-8bit"), content) + assert_equal("\"&<>"'丂\e$B$\"\e(B\n\"".force_encoding("ascii-8bit"), content) open("utf-16be.txt", "wb:utf-16be", xml: :attr) {|f| f.print '&<>"\''; f.puts "\u4E02\u3042" } content = File.read("utf-16be.txt", :mode=>"rb:ascii-8bit") - assert_equal("\0\"\0&\0a\0m\0p\0;\0&\0l\0t\0;\0&\0g\0t\0;\0&\0q\0u\0o\0t\0;\0&\0a\0p\0o\0s\0;\x4E\x02\x30\x42\0\n\0\"".force_encoding("ascii-8bit"), content) + assert_equal("\0\"\0&\0a\0m\0p\0;\0&\0l\0t\0;\0&\0g\0t\0;\0&\0q\0u\0o\0t\0;\0'\x4E\x02\x30\x42\0\n\0\"".force_encoding("ascii-8bit"), content) open("eucjp.txt", "w:euc-jp:utf-8", xml: :attr) {|f| f.print "\u4E02" # U+4E02 is 0x3021 in JIS X 0212 @@ -2081,56 +2080,29 @@ EOT } 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" + def test_strip_bom + with_tmpdir { + text = "\uFEFF\u0100a" + stripped = "\u0100a" + %w/UTF-8 UTF-16BE UTF-16LE UTF-32BE UTF-32LE/.each do |name| + path = '%s-bom.txt' % name 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 - - 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 - - def test_strip_bom_no_conv - with_tmpdir { - path = 'UTF-8-bom.txt' - generate_file(path, "\uFEFFa") + assert_equal(content[1..-1].force_encoding("ascii-8bit"), + result.force_encoding("ascii-8bit")) + result = File.read(path, mode: 'rb:BOM|UTF-8:UTF-8') + assert_equal(Encoding::UTF_8, result.encoding) + assert_equal(stripped, result) + end bug3407 = '[ruby-core:30641]' - result = File.read(path, encoding: 'BOM|UTF-8') - assert_equal("a", result.b, bug3407) - - File.open(path, "rb", encoding: "iso-8859-1") {|f| - assert_raise(ArgumentError) {f.set_encoding_by_bom} - } - } - end - - def test_strip_bom_invalid - with_tmpdir { path = 'UTF-8-bom.txt' - generate_file(path, "\uFEFFa") + result = File.read(path, encoding: 'BOM|UTF-8') + assert_equal(stripped.b, result.force_encoding("ascii-8bit"), bug3407) bug8323 = '[ruby-core:54563] [Bug #8323]' - expected = "a\xff".force_encoding("utf-8") + expected = (stripped.b + "\xff").force_encoding("utf-8") open(path, 'ab') {|f| f.write("\xff")} result = File.read(path, encoding: 'BOM|UTF-8') assert_not_predicate(result, :valid_encoding?, bug8323) @@ -2138,38 +2110,23 @@ EOT result = File.read(path, encoding: 'BOM|UTF-8:UTF-8') assert_not_predicate(result, :valid_encoding?, bug8323) assert_equal(expected, result, bug8323) - } - end - def test_strip_bom_no_bom - with_tmpdir { - bug8323 = '[ruby-core:54563] [Bug #8323]' path = 'ascii.txt' - stripped = "a" generate_file(path, stripped) result = File.read(path, encoding: 'BOM|UTF-8') assert_equal(stripped, result, bug8323) result = File.read(path, encoding: 'BOM|UTF-8:UTF-8') assert_equal(stripped, result, bug8323) - - File.open(path, "rb") {|f| - assert_nil(f.set_encoding_by_bom) - } - File.open(path, "rb", encoding: "iso-8859-1") {|f| - assert_raise(ArgumentError) {f.set_encoding_by_bom} - } } end def test_bom_too_long_utfname - assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") - begin; + assert_separately([], <<-'end;') # do assert_warn(/Unsupported encoding/) { open(IO::NULL, "r:bom|utf-" + "x" * 10000) {} } end; - assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") - begin; + assert_separately([], <<-'end;') # do assert_warn(/Unsupported encoding/) { open(IO::NULL, encoding: "bom|utf-" + "x" * 10000) {} } diff --git a/test/ruby/test_iseq.rb b/test/ruby/test_iseq.rb index e3ca1ba926..ed88c9b43d 100644 --- a/test/ruby/test_iseq.rb +++ b/test/ruby/test_iseq.rb @@ -91,27 +91,6 @@ class TestISeq < Test::Unit::TestCase asm = compile(src).disasm assert_equal(src.encoding, asm.encoding) assert_predicate(asm, :valid_encoding?) - - obj = Object.new - name = "\u{2603 26a1}" - obj.instance_eval("def #{name}; tap {}; end") - assert_include(RubyVM::InstructionSequence.of(obj.method(name)).disasm, name) - end - - def test_compile_file_encoding - Tempfile.create(%w"test_iseq .rb") do |f| - f.puts "{ '\u00de' => 'Th', '\u00df' => 'ss', '\u00e0' => 'a' }" - f.close - - EnvUtil.with_default_external(Encoding::US_ASCII) do - assert_warn('') { - load f.path - } - assert_nothing_raised(SyntaxError) { - RubyVM::InstructionSequence.compile_file(f.path) - } - end - end end LINE_BEFORE_METHOD = __LINE__ @@ -203,8 +182,8 @@ class TestISeq < Test::Unit::TestCase s1, s2, s3, s4 = compile(code, line, {frozen_string_literal: true}).eval assert_predicate(s1, :frozen?) assert_predicate(s2, :frozen?) - assert_not_predicate(s3, :frozen?) - assert_not_predicate(s4, :frozen?) + assert_predicate(s3, :frozen?) + assert_predicate(s4, :frozen?) end # Safe call chain is not optimized when Coverage is running. @@ -262,12 +241,9 @@ class TestISeq < Test::Unit::TestCase end end assert_equal([m1, e1.message], [m2, e2.message], feature11951) - message = e1.message.each_line - message.with_index(1) do |line, i| - next if /^ / =~ line - assert_send([line, :start_with?, __FILE__], - proc {message.map {|l, j| (i == j ? ">" : " ") + l}.join("")}) - end + e1, e2 = e1.message.lines + assert_send([e1, :start_with?, __FILE__]) + assert_send([e2, :start_with?, __FILE__]) end def test_compile_file_error @@ -275,7 +251,7 @@ class TestISeq < Test::Unit::TestCase f.puts "end" f.close path = f.path - assert_in_out_err(%W[- #{path}], "#{<<-"begin;"}\n#{<<-"end;"}", /unexpected `end'/, [], success: true) + assert_in_out_err(%W[- #{path}], "#{<<-"begin;"}\n#{<<-"end;"}", /keyword_end/, [], success: true) begin; path = ARGV[0] begin @@ -299,18 +275,14 @@ class TestISeq < Test::Unit::TestCase def test_inspect %W[foo \u{30d1 30b9}].each do |name| - assert_match(/@#{name}/, ISeq.compile("", name).inspect, name) + assert_match /@#{name}/, ISeq.compile("", name).inspect, name m = ISeq.compile("class TestISeq::Inspect; def #{name}; end; instance_method(:#{name}); end").eval - assert_match(/:#{name}@/, ISeq.of(m).inspect, name) + assert_match /:#{name}@/, ISeq.of(m).inspect, name end end - def strip_lineno(source) - source.gsub(/^.*?: /, "") - end - def sample_iseq - ISeq.compile(strip_lineno(<<-EOS)) + ISeq.compile <<-EOS.gsub(/^.*?: /, "") 1: class C 2: def foo 3: begin @@ -403,7 +375,7 @@ class TestISeq < Test::Unit::TestCase type = ary[9] name = ary[5] line = ary[13].first - case type + case ary[9] when :method assert_equal "foo", name assert_equal 3, line @@ -419,197 +391,44 @@ class TestISeq < Test::Unit::TestCase } end - def hexdump(bin) - bin.unpack1("H*").gsub(/.{1,32}/) {|s| - "#{'%04x:' % $~.begin(0)}#{s.gsub(/../, " \\&").tap{|_|_[24]&&="-"}}\n" - } - end - - def assert_iseq_to_binary(code, mesg = nil) + def test_to_binary_with_objects + # conceptually backport from r62856. + # ISeq binary dump doesn't consider alignment in 2.5 and older + skip "does not work on other than x86" unless /x(?:86|64)|i\d86/ =~ RUBY_PLATFORM + code = "[]"+100.times.map{|i|"<</#{i}/"}.join iseq = RubyVM::InstructionSequence.compile(code) - bin = assert_nothing_raised(mesg) do + bin = assert_nothing_raised do iseq.to_binary rescue RuntimeError => e skip e.message if /compile with coverage/ =~ e.message raise end - 10.times do - bin2 = iseq.to_binary - assert_equal(bin, bin2, message(mesg) {diff hexdump(bin), hexdump(bin2)}) - end iseq2 = RubyVM::InstructionSequence.load_from_binary(bin) - a1 = iseq.to_a - a2 = iseq2.to_a - assert_equal(a1, a2, message(mesg) {diff iseq.disassemble, iseq2.disassemble}) - iseq2 - end - - def test_to_binary_with_objects - assert_iseq_to_binary("[]"+100.times.map{|i|"<</#{i}/"}.join) - assert_iseq_to_binary("@x ||= (1..2)") - end - - def test_to_binary_pattern_matching - code = "case foo; in []; end" - iseq = compile(code) - assert_include(iseq.disasm, "TypeError") - assert_include(iseq.disasm, "NoMatchingPatternError") - EnvUtil.suppress_warning do - assert_iseq_to_binary(code, "[Feature #14912]") - end - end - - def test_to_binary_dumps_nokey - iseq = assert_iseq_to_binary(<<-RUBY) - o = Object.new - class << o - def foo(**nil); end - end - o - RUBY - assert_equal([[:nokey]], iseq.eval.singleton_method(:foo).parameters) + assert_equal(iseq2.to_a, iseq.to_a) end - def test_to_binary_line_info - assert_iseq_to_binary("#{<<~"begin;"}\n#{<<~'end;'}", '[Bug #14660]').eval - begin; - class P - def p; end - def q; end - E = "" - N = "#{E}" - attr_reader :i - end - end; - - # cleanup - ::Object.class_eval do - remove_const :P + def test_to_binary_tracepoint + # conceptually backport from r62856. + # ISeq binary dump doesn't consider alignment in 2.5 and older + skip "does not work on other than x86" unless /x(?:86|64)|i\d86/ =~ RUBY_PLATFORM + filename = "#{File.basename(__FILE__)}_#{__LINE__}" + iseq = RubyVM::InstructionSequence.compile("x = 1\n y = 2", filename) + # conceptually partial backport from r63103, r65567. + # All ISeq#to_binary should rescue to skip when running with coverage. + # current trunk (2.6-) has assert_iseq_to_binary. + begin + iseq_bin = iseq.to_binary + rescue RuntimeError => e + skip e.message if /compile with coverage/ =~ e.message + raise end - end - - def collect_from_binary_tracepoint_lines(tracepoint_type, filename) - iseq = RubyVM::InstructionSequence.compile(strip_lineno(<<-RUBY), filename) - class A - class B - 2.times { - def self.foo - _a = 'good day' - raise - rescue - 'dear reader' - end - } - end - B.foo - end - RUBY - - iseq_bin = iseq.to_binary - iseq = ISeq.load_from_binary(iseq_bin) - lines = [] - TracePoint.new(tracepoint_type){|tp| + ary = [] + TracePoint.new(:line){|tp| next unless tp.path == filename - lines << tp.lineno + ary << [tp.path, tp.lineno] }.enable{ - EnvUtil.suppress_warning {iseq.eval} + ISeq.load_from_binary(iseq_bin).eval } - - lines - end - - def test_to_binary_line_tracepoint - filename = "#{File.basename(__FILE__)}_#{__LINE__}" - lines = collect_from_binary_tracepoint_lines(:line, filename) - - assert_equal [1, 2, 3, 4, 4, 12, 5, 6, 8], lines, '[Bug #14702]' - end - - def test_to_binary_class_tracepoint - filename = "#{File.basename(__FILE__)}_#{__LINE__}" - lines = collect_from_binary_tracepoint_lines(:class, filename) - - assert_equal [1, 2], lines, '[Bug #14702]' - end - - def test_to_binary_end_tracepoint - filename = "#{File.basename(__FILE__)}_#{__LINE__}" - lines = collect_from_binary_tracepoint_lines(:end, filename) - - assert_equal [11, 13], lines, '[Bug #14702]' - end - - def test_to_binary_return_tracepoint - filename = "#{File.basename(__FILE__)}_#{__LINE__}" - lines = collect_from_binary_tracepoint_lines(:return, filename) - - assert_equal [9], lines, '[Bug #14702]' - end - - def test_to_binary_b_call_tracepoint - filename = "#{File.basename(__FILE__)}_#{__LINE__}" - lines = collect_from_binary_tracepoint_lines(:b_call, filename) - - assert_equal [3, 3], lines, '[Bug #14702]' - end - - def test_to_binary_b_return_tracepoint - filename = "#{File.basename(__FILE__)}_#{__LINE__}" - lines = collect_from_binary_tracepoint_lines(:b_return, filename) - - assert_equal [10, 10], lines, '[Bug #14702]' - end - - def test_iseq_of - [proc{}, - method(:test_iseq_of), - RubyVM::InstructionSequence.compile("p 1", __FILE__)].each{|src| - iseq = RubyVM::InstructionSequence.of(src) - assert_equal __FILE__, iseq.path - } - end - - def test_iseq_of_twice_for_same_code - [proc{}, - method(:test_iseq_of_twice_for_same_code), - RubyVM::InstructionSequence.compile("p 1")].each{|src| - iseq1 = RubyVM::InstructionSequence.of(src) - iseq2 = RubyVM::InstructionSequence.of(src) - - # ISeq objects should be same for same src - assert_equal iseq1.object_id, iseq2.object_id - } - end - - def test_iseq_builtin_to_a - invokebuiltin = eval(EnvUtil.invoke_ruby(['-e', <<~EOS], '', true).first) - insns = RubyVM::InstructionSequence.of([].method(:pack)).to_a.last - p insns.find { |insn| insn.is_a?(Array) && insn[0] == :opt_invokebuiltin_delegate_leave } - EOS - assert_not_nil(invokebuiltin) - assert_equal([:func_ptr, :argc, :index, :name], invokebuiltin[1].keys) - end - - def test_iseq_builtin_load - Tempfile.create(["builtin", ".iseq"]) do |f| - f.binmode - f.write(RubyVM::InstructionSequence.of(1.method(:abs)).to_binary) - f.close - assert_separately(["-", f.path], "#{<<~"begin;"}\n#{<<~'end;'}") - begin; - bin = File.binread(ARGV[0]) - assert_raise(ArgumentError) do - RubyVM::InstructionSequence.load_from_binary(bin) - end - end; - end - end - - def test_iseq_option_debug_level - assert_raise(TypeError) {ISeq.compile("", debug_level: "")} - assert_ruby_status([], "#{<<~"begin;"}\n#{<<~'end;'}") - begin; - RubyVM::InstructionSequence.compile("", debug_level: 5) - end; + assert_equal [[filename, 1], [filename, 2]], ary, '[Bug #14702]' end end diff --git a/test/ruby/test_iterator.rb b/test/ruby/test_iterator.rb index 820d5591c1..9bfa947607 100644 --- a/test/ruby/test_iterator.rb +++ b/test/ruby/test_iterator.rb @@ -12,12 +12,17 @@ class Array end class TestIterator < Test::Unit::TestCase - def test_yield_at_toplevel - assert_separately([],"#{<<~"begin;"}\n#{<<~'end;'}") - begin; - assert(!block_given?) - assert(!defined?(yield)) - end; + def ttt + assert(iterator?) + end + + def test_iterator + assert(!iterator?) + + ttt{} + + # yield at top level !! here's not toplevel + assert(!defined?(yield)) end def test_array @@ -102,16 +107,6 @@ class TestIterator < Test::Unit::TestCase assert_equal([1, 2, 3, 4, 5, 6, 7], x) end - def test_array_for_masgn - a = [Struct.new(:to_ary).new([1,2])] - x = [] - a.each {|i,j|x << [i,j]} - assert_equal([[1,2]], x) - x = [] - for i,j in a; x << [i,j]; end - assert_equal([[1,2]], x) - end - def test_append_method_to_built_in_class x = [[1,2],[3,4],[5,6]] assert_equal(x.iter_test1{|e|e}, x.iter_test2{|e|e}) @@ -339,7 +334,8 @@ class TestIterator < Test::Unit::TestCase marity_test(:marity_test) marity_test(:p) - get_block{|a,n| assert(a,n)}.call(true, "marity") + lambda(&method(:assert)).call(true) + lambda(&get_block{|a,n| assert(a,n)}).call(true, "marity") end def foo diff --git a/test/ruby/test_jit.rb b/test/ruby/test_jit.rb deleted file mode 100644 index 3a38b1a998..0000000000 --- a/test/ruby/test_jit.rb +++ /dev/null @@ -1,1212 +0,0 @@ -# frozen_string_literal: true -require 'test/unit' -require 'tmpdir' -require_relative '../lib/jit_support' - -# Test for --jit option -class TestJIT < Test::Unit::TestCase - include JITSupport - - IGNORABLE_PATTERNS = [ - /\AJIT recompile: .+\n\z/, - /\AJIT inline: .+\n\z/, - /\ASuccessful MJIT finish\n\z/, - ] - MAX_CACHE_PATTERNS = [ - /\AJIT compaction \([^)]+\): .+\n\z/, - /\AToo many JIT code, but skipped unloading units for JIT compaction\n\z/, - /\ANo units can be unloaded -- .+\n\z/, - ] - - # trace_* insns are not compiled for now... - TEST_PENDING_INSNS = RubyVM::INSTRUCTION_NAMES.select { |n| n.start_with?('trace_') }.map(&:to_sym) + [ - # not supported yet - :defineclass, - - # to be tested - :invokebuiltin, - - # never used - :opt_invokebuiltin_delegate, - ].each do |insn| - if !RubyVM::INSTRUCTION_NAMES.include?(insn.to_s) - warn "instruction #{insn.inspect} is not defined but included in TestJIT::TEST_PENDING_INSNS" - end - end - - def self.untested_insns - @untested_insns ||= (RubyVM::INSTRUCTION_NAMES.map(&:to_sym) - TEST_PENDING_INSNS) - end - - def self.setup - return if defined?(@setup_hooked) - @setup_hooked = true - - # ci.rvm.jp caches its build environment. Clean up temporary files left by SEGV. - if ENV['RUBY_DEBUG']&.include?('ci') - Dir.glob("#{ENV.fetch('TMPDIR', '/tmp')}/_ruby_mjit_p*u*.*").each do |file| - puts "test/ruby/test_jit.rb: removing #{file}" - File.unlink(file) - end - end - - # ruby -w -Itest/lib test/ruby/test_jit.rb - if $VERBOSE - at_exit do - unless TestJIT.untested_insns.empty? - warn "you may want to add tests for following insns, when you have a chance: #{TestJIT.untested_insns.join(' ')}" - end - end - end - end - - def setup - unless JITSupport.supported? - skip 'JIT seems not supported on this platform' - end - self.class.setup - end - - def test_compile_insn_nop - assert_compile_once('nil rescue true', result_inspect: 'nil', insns: %i[nop]) - end - - def test_compile_insn_local - assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1', insns: %i[setlocal_WC_0 getlocal_WC_0]) - begin; - foo = 1 - foo - end; - - insns = %i[setlocal getlocal setlocal_WC_0 getlocal_WC_0 setlocal_WC_1 getlocal_WC_1] - assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", success_count: 3, stdout: '168', insns: insns) - begin; - def foo - a = 0 - [1, 2].each do |i| - a += i - [3, 4].each do |j| - a *= j - end - end - a - end - - print foo - end; - end - - def test_compile_insn_blockparam - assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '3', success_count: 2, insns: %i[getblockparam setblockparam]) - begin; - def foo(&b) - a = b - b = 2 - a.call + 2 - end - - print foo { 1 } - end; - end - - def test_compile_insn_getblockparamproxy - assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '4', success_count: 3, insns: %i[getblockparamproxy]) - begin; - def bar(&b) - b.call - end - - def foo(&b) - bar(&b) * bar(&b) - end - - print foo { 2 } - end; - end - - def test_compile_insn_getspecial - assert_compile_once('$1', result_inspect: 'nil', insns: %i[getspecial]) - end - - def test_compile_insn_setspecial - assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: 'true', insns: %i[setspecial]) - begin; - true if nil.nil?..nil.nil? - end; - end - - def test_compile_insn_instancevariable - assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1', insns: %i[getinstancevariable setinstancevariable]) - begin; - @foo = 1 - @foo - end; - - # optimized getinstancevariable call - assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '33', success_count: 1, min_calls: 2) - begin; - class A - def initialize - @a = 1 - @b = 2 - end - - def three - @a + @b - end - end - - a = A.new - print(a.three) # set ic - print(a.three) # inlined ic - end; - end - - def test_compile_insn_classvariable - assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '1', success_count: 1, insns: %i[getclassvariable setclassvariable]) - begin; - class Foo - def self.foo - @@foo = 1 - @@foo - end - end - - print Foo.foo - end; - end - - def test_compile_insn_constant - assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1', insns: %i[getconstant setconstant]) - begin; - FOO = 1 - FOO - end; - end - - def test_compile_insn_global - assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1', insns: %i[getglobal setglobal]) - begin; - $foo = 1 - $foo - end; - end - - def test_compile_insn_putnil - assert_compile_once('nil', result_inspect: 'nil', insns: %i[putnil]) - end - - def test_compile_insn_putself - assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'hello', success_count: 1, insns: %i[putself]) - begin; - proc { print "hello" }.call - end; - end - - def test_compile_insn_putobject - assert_compile_once('0', result_inspect: '0', insns: %i[putobject_INT2FIX_0_]) - assert_compile_once('1', result_inspect: '1', insns: %i[putobject_INT2FIX_1_]) - assert_compile_once('2', result_inspect: '2', insns: %i[putobject]) - end - - def test_compile_insn_definemethod_definesmethod - assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'helloworld', success_count: 3, insns: %i[definemethod definesmethod]) - begin; - print 1.times.map { - def method_definition - 'hello' - end - - def self.smethod_definition - 'world' - end - - method_definition + smethod_definition - }.join - end; - end - - def test_compile_insn_putspecialobject - assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'a', success_count: 2, insns: %i[putspecialobject]) - begin; - print 1.times.map { - def a - 'a' - end - - alias :b :a - - b - }.join - end; - end - - def test_compile_insn_putstring_concatstrings_tostring - assert_compile_once('"a#{}b" + "c"', result_inspect: '"abc"', insns: %i[putstring concatstrings tostring]) - end - - def test_compile_insn_toregexp - assert_compile_once('/#{true}/ =~ "true"', result_inspect: '0', insns: %i[toregexp]) - end - - def test_compile_insn_newarray - assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '[1, 2, 3]', insns: %i[newarray]) - begin; - a, b, c = 1, 2, 3 - [a, b, c] - end; - end - - def test_compile_insn_newarraykwsplat - assert_compile_once('[**{ x: 1 }]', result_inspect: '[{:x=>1}]', insns: %i[newarraykwsplat]) - end - - def test_compile_insn_intern_duparray - assert_compile_once('[:"#{0}"] + [1,2,3]', result_inspect: '[:"0", 1, 2, 3]', insns: %i[intern duparray]) - end - - def test_compile_insn_expandarray - assert_compile_once('y = [ true, false, nil ]; x, = y; x', result_inspect: 'true', insns: %i[expandarray]) - end - - def test_compile_insn_concatarray - assert_compile_once('["t", "r", *x = "u", "e"].join', result_inspect: '"true"', insns: %i[concatarray]) - end - - def test_compile_insn_splatarray - assert_compile_once('[*(1..2)]', result_inspect: '[1, 2]', insns: %i[splatarray]) - end - - def test_compile_insn_newhash - assert_compile_once('a = 1; { a: a }', result_inspect: '{:a=>1}', insns: %i[newhash]) - end - - def test_compile_insn_duphash - assert_compile_once('{ a: 1 }', result_inspect: '{:a=>1}', insns: %i[duphash]) - end - - def test_compile_insn_newrange - assert_compile_once('a = 1; 0..a', result_inspect: '0..1', insns: %i[newrange]) - end - - def test_compile_insn_pop - assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1', insns: %i[pop]) - begin; - a = false - b = 1 - a || b - end; - end - - def test_compile_insn_dup - assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '3', insns: %i[dup]) - begin; - a = 1 - a&.+(2) - end; - end - - def test_compile_insn_dupn - assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: 'true', insns: %i[dupn]) - begin; - klass = Class.new - klass::X ||= true - end; - end - - def test_compile_insn_swap_topn - assert_compile_once('{}["true"] = true', result_inspect: 'true', insns: %i[swap topn]) - end - - def test_compile_insn_reverse - assert_compile_once('q, (w, e), r = 1, [2, 3], 4; [q, w, e, r]', result_inspect: '[1, 2, 3, 4]', insns: %i[reverse]) - end - - def test_compile_insn_reput - skip "write test" - end - - def test_compile_insn_setn - assert_compile_once('[nil][0] = 1', result_inspect: '1', insns: %i[setn]) - end - - def test_compile_insn_adjuststack - assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: 'true', insns: %i[adjuststack]) - begin; - x = [true] - x[0] ||= nil - x[0] - end; - end - - def test_compile_insn_defined - assert_compile_once('defined?(a)', result_inspect: 'nil', insns: %i[defined]) - end - - def test_compile_insn_checkkeyword - assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'true', success_count: 1, insns: %i[checkkeyword]) - begin; - def test(x: rand) - x - end - print test(x: true) - end; - end - - def test_compile_insn_tracecoverage - skip "write test" - end - - def test_compile_insn_defineclass - skip "support this in mjit_compile (low priority)" - end - - def test_compile_insn_send - assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '1', success_count: 3, insns: %i[send]) - begin; - print proc { yield_self { 1 } }.call - end; - end - - def test_compile_insn_opt_str_freeze - assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '"foo"', insns: %i[opt_str_freeze]) - begin; - 'foo'.freeze - end; - end - - def test_compile_insn_opt_nil_p - assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: 'false', insns: %i[opt_nil_p]) - begin; - nil.nil?.nil? - end; - end - - def test_compile_insn_opt_str_uminus - assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '"bar"', insns: %i[opt_str_uminus]) - begin; - -'bar' - end; - end - - def test_compile_insn_opt_newarray_max - assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '2', insns: %i[opt_newarray_max]) - begin; - a = 1 - b = 2 - [a, b].max - end; - end - - def test_compile_insn_opt_newarray_min - assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1', insns: %i[opt_newarray_min]) - begin; - a = 1 - b = 2 - [a, b].min - end; - end - - def test_compile_insn_opt_send_without_block - assert_compile_once('print', result_inspect: 'nil', insns: %i[opt_send_without_block]) - end - - def test_compile_insn_invokesuper - assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '3', success_count: 4, insns: %i[invokesuper]) - begin; - mod = Module.new { - def test - super + 2 - end - } - klass = Class.new { - prepend mod - def test - 1 - end - } - print klass.new.test - end; - end - - def test_compile_insn_invokeblock_leave - assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '2', success_count: 2, insns: %i[invokeblock leave]) - begin; - def foo - yield - end - print foo { 2 } - end; - end - - def test_compile_insn_throw - assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '4', success_count: 2, insns: %i[throw]) - begin; - def test - proc do - if 1+1 == 1 - return 3 - else - return 4 - end - 5 - end.call - end - print test - end; - end - - def test_compile_insn_jump_branchif - assert_compile_once("#{<<~"begin;"}\n#{<<~'end;'}", result_inspect: 'nil', insns: %i[jump branchif]) - begin; - a = false - 1 + 1 while a - end; - end - - def test_compile_insn_branchunless - assert_compile_once("#{<<~"begin;"}\n#{<<~'end;'}", result_inspect: '1', insns: %i[branchunless]) - begin; - a = true - if a - 1 - else - 2 - end - end; - end - - def test_compile_insn_branchnil - assert_compile_once("#{<<~"begin;"}\n#{<<~'end;'}", result_inspect: '3', insns: %i[branchnil]) - begin; - a = 2 - a&.+(1) - end; - end - - def test_compile_insn_checktype - assert_compile_once("#{<<~"begin;"}\n#{<<~'end;'}", result_inspect: '"42"', insns: %i[checktype]) - begin; - a = '2' - "4#{a}" - end; - end - - def test_compile_insn_inlinecache - assert_compile_once('Struct', result_inspect: 'Struct', insns: %i[opt_getinlinecache opt_setinlinecache]) - end - - def test_compile_insn_once - assert_compile_once('/#{true}/o =~ "true" && $~.to_a', result_inspect: '["true"]', insns: %i[once]) - end - - def test_compile_insn_checkmatch_opt_case_dispatch - assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '"world"', insns: %i[checkmatch opt_case_dispatch]) - begin; - case 'hello' - when 'hello' - 'world' - end - end; - end - - def test_compile_insn_opt_calc - assert_compile_once('4 + 2 - ((2 * 3 / 2) % 2)', result_inspect: '5', insns: %i[opt_plus opt_minus opt_mult opt_div opt_mod]) - assert_compile_once('4.0 + 2.0 - ((2.0 * 3.0 / 2.0) % 2.0)', result_inspect: '5.0', insns: %i[opt_plus opt_minus opt_mult opt_div opt_mod]) - assert_compile_once('4 + 2', result_inspect: '6') - end - - def test_compile_insn_opt_cmp - assert_compile_once('(1 == 1) && (1 != 2)', result_inspect: 'true', insns: %i[opt_eq opt_neq]) - end - - def test_compile_insn_opt_rel - assert_compile_once('1 < 2 && 1 <= 1 && 2 > 1 && 1 >= 1', result_inspect: 'true', insns: %i[opt_lt opt_le opt_gt opt_ge]) - end - - def test_compile_insn_opt_ltlt - assert_compile_once('[1] << 2', result_inspect: '[1, 2]', insns: %i[opt_ltlt]) - end - - def test_compile_insn_opt_and - assert_compile_once('1 & 3', result_inspect: '1', insns: %i[opt_and]) - end - - def test_compile_insn_opt_or - assert_compile_once('1 | 3', result_inspect: '3', insns: %i[opt_or]) - end - - def test_compile_insn_opt_aref - # optimized call (optimized JIT) -> send call - assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '21', success_count: 2, min_calls: 1, insns: %i[opt_aref]) - begin; - obj = Object.new - def obj.[](h) - h - end - - block = proc { |h| h[1] } - print block.call({ 1 => 2 }) - print block.call(obj) - end; - - # send call -> optimized call (send JIT) -> optimized call - assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '122', success_count: 2, min_calls: 2) - begin; - obj = Object.new - def obj.[](h) - h - end - - block = proc { |h| h[1] } - print block.call(obj) - print block.call({ 1 => 2 }) - print block.call({ 1 => 2 }) - end; - end - - def test_compile_insn_opt_aref_with - assert_compile_once("{ '1' => 2 }['1']", result_inspect: '2', insns: %i[opt_aref_with]) - end - - def test_compile_insn_opt_aset - assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '5', insns: %i[opt_aset opt_aset_with]) - begin; - hash = { '1' => 2 } - (hash['2'] = 2) + (hash[1.to_s] = 3) - end; - end - - def test_compile_insn_opt_length_size - assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '4', insns: %i[opt_length opt_size]) - begin; - array = [1, 2] - array.length + array.size - end; - end - - def test_compile_insn_opt_empty_p - assert_compile_once('[].empty?', result_inspect: 'true', insns: %i[opt_empty_p]) - end - - def test_compile_insn_opt_succ - assert_compile_once('1.succ', result_inspect: '2', insns: %i[opt_succ]) - end - - def test_compile_insn_opt_not - assert_compile_once('!!true', result_inspect: 'true', insns: %i[opt_not]) - end - - def test_compile_insn_opt_regexpmatch2 - assert_compile_once("/true/ =~ 'true'", result_inspect: '0', insns: %i[opt_regexpmatch2]) - assert_compile_once("'true' =~ /true/", result_inspect: '0', insns: %i[opt_regexpmatch2]) - end - - def test_compile_insn_opt_invokebuiltin_delegate_leave - iseq = eval(EnvUtil.invoke_ruby(['-e', <<~'EOS'], '', true).first) - p RubyVM::InstructionSequence.of("\x00".method(:unpack)).to_a - EOS - insns = collect_insns(iseq) - mark_tested_insn(:opt_invokebuiltin_delegate_leave, used_insns: insns) - assert_eval_with_jit('print "\x00".unpack("c")', stdout: '[0]', success_count: 1) - end - - def test_jit_output - out, err = eval_with_jit('5.times { puts "MJIT" }', verbose: 1, min_calls: 5) - assert_equal("MJIT\n" * 5, out) - assert_match(/^#{JIT_SUCCESS_PREFIX}: block in <main>@-e:1 -> .+_ruby_mjit_p\d+u\d+\.c$/, err) - assert_match(/^Successful MJIT finish$/, err) - end - - def test_nothing_to_unload_with_jit_wait - assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'hello', success_count: 11, max_cache: 10, ignorable_patterns: MAX_CACHE_PATTERNS) - begin; - def a1() a2() end - def a2() a3() end - def a3() a4() end - def a4() a5() end - def a5() a6() end - def a6() a7() end - def a7() a8() end - def a8() a9() end - def a9() a10() end - def a10() a11() end - def a11() print('hello') end - a1 - end; - end - - def test_unload_units_on_fiber - assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'hello', success_count: 12, max_cache: 10, ignorable_patterns: MAX_CACHE_PATTERNS) - begin; - def a1() a2(false); a2(true) end - def a2(a) a3(a) end - def a3(a) a4(a) end - def a4(a) a5(a) end - def a5(a) a6(a) end - def a6(a) a7(a) end - def a7(a) a8(a) end - def a8(a) a9(a) end - def a9(a) a10(a) end - def a10(a) - if a - Fiber.new { a11 }.resume - end - end - def a11() print('hello') end - a1 - end; - end - - def test_unload_units_and_compaction - Dir.mktmpdir("jit_test_unload_units_") do |dir| - # MIN_CACHE_SIZE is 10 - out, err = eval_with_jit({"TMPDIR"=>dir}, "#{<<~"begin;"}\n#{<<~'end;'}", verbose: 1, min_calls: 1, max_cache: 10) - begin; - i = 0 - while i < 11 - eval(<<-EOS) - def mjit#{i} - print #{i} - end - mjit#{i} - EOS - i += 1 - end - - if defined?(fork) - # test the child does not try to delete files which are deleted by parent, - # and test possible deadlock on fork during MJIT unload and JIT compaction on child - Process.waitpid(Process.fork {}) - end - end; - - debug_info = %Q[stdout:\n"""\n#{out}\n"""\n\nstderr:\n"""\n#{err}"""\n] - assert_equal('012345678910', out, debug_info) - compactions, errs = err.lines.partition do |l| - l.match?(/\AJIT compaction \(\d+\.\dms\): Compacted \d+ methods /) - end - 10.times do |i| - assert_match(/\A#{JIT_SUCCESS_PREFIX}: mjit#{i}@\(eval\):/, errs[i], debug_info) - end - - assert_equal("No units can be unloaded -- incremented max-cache-size to 11 for --jit-wait\n", errs[10], debug_info) - assert_match(/\A#{JIT_SUCCESS_PREFIX}: mjit10@\(eval\):/, errs[11], debug_info) - # On --jit-wait, when the number of JIT-ed code reaches --jit-max-cache, - # it should trigger compaction. - unless RUBY_PLATFORM.match?(/mswin|mingw/) # compaction is not supported on Windows yet - assert_equal(1, compactions.size, debug_info) - end - - if RUBY_PLATFORM.match?(/mswin/) - # "Permission Denied" error is preventing to remove so file on AppVeyor/RubyCI. - skip 'Removing so file is randomly failing on AppVeyor/RubyCI mswin due to Permission Denied.' - else - # verify .c files are deleted on unload_units - assert_send([Dir, :empty?, dir], debug_info) - end - end - end - - def test_newarraykwsplat_on_stack - assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "[nil, [{:type=>:development}]]\n", success_count: 1, insns: %i[newarraykwsplat]) - begin; - def arr - [nil, [:type => :development]] - end - p arr - end; - end - - def test_local_stack_on_exception - assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '3', success_count: 2) - begin; - def b - raise - rescue - 2 - end - - def a - # Calling #b should be vm_exec, not direct mjit_exec. - # Otherwise `1` on local variable would be purged. - 1 + b - end - - print a - end; - end - - def test_local_stack_with_sp_motion_by_blockargs - assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '1', success_count: 2) - begin; - def b(base) - 1 - end - - # This method is simple enough to have false in catch_except_p. - # So local_stack_p would be true in JIT compiler. - def a - m = method(:b) - - # ci->flag has VM_CALL_ARGS_BLOCKARG and cfp->sp is moved in vm_caller_setup_arg_block. - # So, for this send insn, JIT-ed code should use cfp->sp instead of local variables for stack. - Module.module_eval(&m) - end - - print a - end; - end - - def test_catching_deep_exception - assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '1', success_count: 4) - begin; - def catch_true(paths, prefixes) # catch_except_p: TRUE - prefixes.each do |prefix| # catch_except_p: TRUE - paths.each do |path| # catch_except_p: FALSE - return path - end - end - end - - def wrapper(paths, prefixes) - catch_true(paths, prefixes) - end - - print wrapper(['1'], ['2']) - end; - end - - def test_inlined_c_method - assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "aaa", success_count: 2, recompile_count: 1, min_calls: 2) - begin; - def test(obj, recursive: nil) - if recursive - test(recursive) - end - obj.to_s - end - - print(test('a')) # set #to_s cc to String#to_s (expecting C method) - print(test('a')) # JIT with #to_s cc: String#to_s - # update #to_s cd->cc to Symbol#to_s, then go through the Symbol#to_s cd->cc - # after checking receiver class using inlined #to_s cc with String#to_s. - print(test('a', recursive: :foo)) - end; - end - - def test_inlined_exivar - assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "aaa", success_count: 3, recompile_count: 1, min_calls: 2) - begin; - class Foo < Hash - def initialize - @a = :a - end - - def bar - @a - end - end - - print(Foo.new.bar) - print(Foo.new.bar) # compile #initialize, #bar -> recompile #bar - print(Foo.new.bar) # compile #bar with exivar - end; - end - - def test_inlined_undefined_ivar - assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "bbb", success_count: 3, min_calls: 3) - begin; - class Foo - def initialize - @a = :a - end - - def bar - if @b.nil? - @b = :b - end - end - end - - print(Foo.new.bar) - print(Foo.new.bar) - print(Foo.new.bar) - end; - end - - def test_inlined_setivar_frozen - assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "FrozenError\n", success_count: 2, min_calls: 3) - begin; - class A - def a - @a = 1 - end - end - - a = A.new - a.a - a.a - a.a - a.freeze - begin - a.a - rescue FrozenError => e - p e.class - end - end; - end - - def test_attr_reader - assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "4nil\nnil\n6", success_count: 2, min_calls: 2) - begin; - class A - attr_reader :a, :b - - def initialize - @a = 2 - end - - def test - a - end - - def undefined - b - end - end - - a = A.new - print(a.test * a.test) - p(a.undefined) - p(a.undefined) - - # redefinition - def a.test - 3 - end - - print(2 * a.test) - end; - - assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "true", success_count: 1, min_calls: 2) - begin; - class Hoge - attr_reader :foo - - def initialize - @foo = [] - @bar = nil - end - end - - class Fuga < Hoge - def initialize - @bar = nil - @foo = [] - end - end - - def test(recv) - recv.foo.empty? - end - - hoge = Hoge.new - fuga = Fuga.new - - test(hoge) # VM: cc set index=1 - test(hoge) # JIT: compile with index=1 - test(fuga) # JIT -> VM: cc set index=2 - print test(hoge) # JIT: should use index=1, not index=2 in cc - end; - end - - def test_heap_promotion_of_ivar_in_the_middle_of_jit - assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "true\ntrue\n", success_count: 2, min_calls: 2) - begin; - class A - def initialize - @iv0 = nil - @iv1 = [] - @iv2 = nil - end - - def test(add) - @iv0.nil? - @iv2.nil? - add_ivar if add - @iv1.empty? - end - - def add_ivar - @iv3 = nil - end - end - - a = A.new - p a.test(false) - p a.test(true) - end; - end - - def test_jump_to_precompiled_branch - assert_eval_with_jit("#{<<~'begin;'}\n#{<<~'end;'}", stdout: ".0", success_count: 1, min_calls: 1) - begin; - def test(foo) - ".#{foo unless foo == 1}" if true - end - print test(0) - end; - end - - def test_clean_so - if RUBY_PLATFORM.match?(/mswin/) - skip 'Removing so file is randomly failing on AppVeyor/RubyCI mswin due to Permission Denied.' - end - Dir.mktmpdir("jit_test_clean_so_") do |dir| - code = "x = 0; 10.times {|i|x+=i}" - eval_with_jit({"TMPDIR"=>dir}, code) - assert_send([Dir, :empty?, dir]) - eval_with_jit({"TMPDIR"=>dir}, code, save_temps: true) - assert_not_send([Dir, :empty?, dir]) - end - end - - def test_clean_objects_on_exec - if /mswin|mingw/ =~ RUBY_PLATFORM - # TODO: check call stack and close handle of code which is not on stack, and remove objects on best-effort basis - skip 'Removing so file being used does not work on Windows' - end - Dir.mktmpdir("jit_test_clean_objects_on_exec_") do |dir| - eval_with_jit({"TMPDIR"=>dir}, "#{<<~"begin;"}\n#{<<~"end;"}", min_calls: 1) - begin; - def a; end; a - exec "true" - end; - error_message = "Undeleted files:\n #{Dir.glob("#{dir}/*").join("\n ")}\n" - assert_send([Dir, :empty?, dir], error_message) - end - end - - def test_lambda_longjmp - assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '5', success_count: 1) - begin; - fib = lambda do |x| - return x if x == 0 || x == 1 - fib.call(x-1) + fib.call(x-2) - end - print fib.call(5) - end; - end - - def test_stack_pointer_with_assignment - assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "nil\nnil\n", success_count: 1) - begin; - 2.times do - a, _ = nil - p a - end - end; - end - - def test_frame_omitted_inlining - assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "true\ntrue\ntrue\n", success_count: 1, min_calls: 2) - begin; - class Integer - remove_method :zero? - def zero? - self == 0 - end - end - - 3.times do - p 0.zero? - end - end; - end - - def test_block_handler_with_possible_frame_omitted_inlining - assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "70.0\n70.0\n70.0\n", success_count: 2, min_calls: 2) - begin; - def multiply(a, b) - a *= b - end - - 3.times do - p multiply(7.0, 10.0) - end - end; - end - - def test_builtin_frame_omitted_inlining - assert_eval_with_jit('0.zero?; 0.zero?; 3.times { p 0.zero? }', stdout: "true\ntrue\ntrue\n", success_count: 1, min_calls: 2) - end - - def test_program_counter_with_regexpmatch - assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "aa", success_count: 1) - begin; - 2.times do - break if /a/ =~ "ab" && !$~[0] - print $~[0] - end - end; - end - - def test_pushed_values_with_opt_aset_with - assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "{}{}", success_count: 1) - begin; - 2.times do - print(Thread.current["a"] = {}) - end - end; - end - - def test_pushed_values_with_opt_aref_with - assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "nil\nnil\n", success_count: 1) - begin; - 2.times do - p(Thread.current["a"]) - end - end; - end - - def test_caller_locations_without_catch_table - out, _ = eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", min_calls: 1) - begin; - def b # 2 - caller_locations.first # 3 - end # 4 - # 5 - def a # 6 - print # <-- don't leave PC here # 7 - b # 8 - end - puts a - puts a - end; - lines = out.lines - assert_equal("-e:8:in `a'\n", lines[0]) - assert_equal("-e:8:in `a'\n", lines[1]) - end - - def test_fork_with_mjit_worker_thread - Dir.mktmpdir("jit_test_fork_with_mjit_worker_thread_") do |dir| - # min_calls: 2 to skip fork block - out, err = eval_with_jit({ "TMPDIR" => dir }, "#{<<~"begin;"}\n#{<<~"end;"}", min_calls: 2, verbose: 1) - begin; - def before_fork; end - def after_fork; end - - before_fork; before_fork # the child should not delete this .o file - pid = Process.fork do # this child should not delete shared .pch file - sleep 2.0 # to prevent mixing outputs on Solaris - after_fork; after_fork # this child does not share JIT-ed after_fork with parent - end - after_fork; after_fork # this parent does not share JIT-ed after_fork with child - - Process.waitpid(pid) - end; - success_count = err.scan(/^#{JIT_SUCCESS_PREFIX}:/).size - debug_info = "stdout:\n```\n#{out}\n```\n\nstderr:\n```\n#{err}```\n" - assert_equal(3, success_count, debug_info) - - # assert no remove error - assert_equal("Successful MJIT finish\n" * 2, err.gsub(/^#{JIT_SUCCESS_PREFIX}:[^\n]+\n/, ''), debug_info) - - # ensure objects are deleted - assert_send([Dir, :empty?, dir], debug_info) - end - end if defined?(fork) - - private - - # The shortest way to test one proc - def assert_compile_once(script, result_inspect:, insns: [], uplevel: 1) - if script.match?(/\A\n.+\n\z/m) - script = script.gsub(/^/, ' ') - else - script = " #{script} " - end - assert_eval_with_jit("p proc {#{script}}.call", stdout: "#{result_inspect}\n", success_count: 1, insns: insns, uplevel: uplevel + 1) - end - - # Shorthand for normal test cases - def assert_eval_with_jit(script, stdout: nil, success_count:, recompile_count: nil, min_calls: 1, max_cache: 1000, insns: [], uplevel: 1, ignorable_patterns: []) - out, err = eval_with_jit(script, verbose: 1, min_calls: min_calls, max_cache: max_cache) - success_actual = err.scan(/^#{JIT_SUCCESS_PREFIX}:/).size - recompile_actual = err.scan(/^#{JIT_RECOMPILE_PREFIX}:/).size - # Add --jit-verbose=2 logs for cl.exe because compiler's error message is suppressed - # for cl.exe with --jit-verbose=1. See `start_process` in mjit_worker.c. - if RUBY_PLATFORM.match?(/mswin/) && success_count != success_actual - out2, err2 = eval_with_jit(script, verbose: 2, min_calls: min_calls, max_cache: max_cache) - end - - # Make sure that the script has insns expected to be tested - used_insns = method_insns(script) - insns.each do |insn| - mark_tested_insn(insn, used_insns: used_insns, uplevel: uplevel + 3) - end - - suffix = "script:\n#{code_block(script)}\nstderr:\n#{code_block(err)}#{( - "\nstdout(verbose=2 retry):\n#{code_block(out2)}\nstderr(verbose=2 retry):\n#{code_block(err2)}" if out2 || err2 - )}" - assert_equal( - success_count, success_actual, - "Expected #{success_count} times of JIT success, but succeeded #{success_actual} times.\n\n#{suffix}", - ) - if recompile_count - assert_equal( - recompile_count, recompile_actual, - "Expected #{success_count} times of JIT recompile, but recompiled #{success_actual} times.\n\n#{suffix}", - ) - end - if stdout - assert_equal(stdout, out, "Expected stdout #{out.inspect} to match #{stdout.inspect} with script:\n#{code_block(script)}") - end - err_lines = err.lines.reject! do |l| - l.chomp.empty? || l.match?(/\A#{JIT_SUCCESS_PREFIX}/) || (IGNORABLE_PATTERNS + ignorable_patterns).any? { |pat| pat.match?(l) } - end - unless err_lines.empty? - warn err_lines.join(''), uplevel: uplevel - end - end - - def mark_tested_insn(insn, used_insns:, uplevel: 1) - unless used_insns.include?(insn) - $stderr.puts - warn "'#{insn}' insn is not included in the script. Actual insns are: #{used_insns.join(' ')}\n", uplevel: uplevel - end - TestJIT.untested_insns.delete(insn) - end - - # Collect block's insns or defined method's insns, which are expected to be JIT-ed. - # Note that this intentionally excludes insns in script's toplevel because they are not JIT-ed. - def method_insns(script) - insns = [] - RubyVM::InstructionSequence.compile(script).to_a.last.each do |(insn, *args)| - case insn - when :send - insns += collect_insns(args.last) - when :definemethod, :definesmethod - insns += collect_insns(args[1]) - when :defineclass - insns += collect_insns(args[1]) - end - end - insns.uniq - end - - # Recursively collect insns in iseq_array - def collect_insns(iseq_array) - return [] if iseq_array.nil? - - insns = iseq_array.last.select { |x| x.is_a?(Array) }.map(&:first) - iseq_array.last.each do |(insn, *args)| - case insn - when :definemethod, :definesmethod, :send - insns += collect_insns(args.last) - end - end - insns - end -end diff --git a/test/ruby/test_jit_debug.rb b/test/ruby/test_jit_debug.rb deleted file mode 100644 index 50e52b4c2e..0000000000 --- a/test/ruby/test_jit_debug.rb +++ /dev/null @@ -1,17 +0,0 @@ -require_relative 'test_jit' - -return unless defined?(TestJIT) -return if ENV.key?('APPVEYOR') -return if ENV.key?('RUBYCI_NICKNAME') -return if ENV['RUBY_DEBUG']&.include?('ci') # ci.rvm.jp -return if /mswin/ =~ RUBY_PLATFORM - -class TestJITDebug < TestJIT - @@test_suites.delete TestJIT if self.respond_to? :on_parallel_worker? - - def setup - super - # let `#eval_with_jit` use --jit-debug - @jit_debug = true - end -end diff --git a/test/ruby/test_key_error.rb b/test/ruby/test_key_error.rb deleted file mode 100644 index fe1d5bb5ab..0000000000 --- a/test/ruby/test_key_error.rb +++ /dev/null @@ -1,42 +0,0 @@ -require 'test/unit' - -class TestKeyError < Test::Unit::TestCase - def test_default - error = KeyError.new - assert_equal("KeyError", error.message) - end - - def test_message - error = KeyError.new("Message") - assert_equal("Message", error.message) - end - - def test_receiver - receiver = Object.new - error = KeyError.new(receiver: receiver) - assert_equal(receiver, error.receiver) - error = KeyError.new - assert_raise(ArgumentError) {error.receiver} - end - - def test_key - error = KeyError.new(key: :key) - assert_equal(:key, error.key) - error = KeyError.new - assert_raise(ArgumentError) {error.key} - end - - def test_receiver_and_key - receiver = Object.new - error = KeyError.new(receiver: receiver, key: :key) - assert_equal([receiver, :key], - [error.receiver, error.key]) - end - - def test_all - receiver = Object.new - error = KeyError.new("Message", receiver: receiver, key: :key) - assert_equal(["Message", receiver, :key], - [error.message, error.receiver, error.key]) - end -end diff --git a/test/ruby/test_keyword.rb b/test/ruby/test_keyword.rb index 8ec0636d5c..8a45016c13 100644 --- a/test/ruby/test_keyword.rb +++ b/test/ruby/test_keyword.rb @@ -1,7 +1,5 @@ # frozen_string_literal: false require 'test/unit' -require '-test-/rb_call_super_kw' -require '-test-/iter' class TestKeywordArguments < Test::Unit::TestCase def f1(str: "foo", num: 424242) @@ -24,7 +22,7 @@ class TestKeywordArguments < Test::Unit::TestCase def test_f2 assert_equal([:xyz, "foo", 424242], f2(:xyz)) - assert_raise(ArgumentError) { f2("bar"=>42) } + assert_equal([{"bar"=>42}, "foo", 424242], f2("bar"=>42)) end @@ -128,47 +126,6 @@ class TestKeywordArguments < Test::Unit::TestCase assert_equal(1, f10(b: 42)) end - def f11(**nil) - local_variables - end - - def test_f11 - h = {} - - assert_equal([], f11) - assert_equal([], f11(**{})) - assert_equal([], f11(**h)) - end - - def f12(**nil, &b) - [b, local_variables] - end - - def test_f12 - h = {} - b = proc{} - - assert_equal([nil, [:b]], f12) - assert_equal([nil, [:b]], f12(**{})) - assert_equal([nil, [:b]], f12(**h)) - assert_equal([b, [:b]], f12(&b)) - assert_equal([b, [:b]], f12(**{}, &b)) - assert_equal([b, [:b]], f12(**h, &b)) - end - - def f13(a, **nil) - a - end - - def test_f13 - assert_equal(1, f13(1)) - assert_equal(1, f13(1, **{})) - assert_raise(ArgumentError) { f13(a: 1) } - assert_raise(ArgumentError) { f13(1, a: 1) } - assert_raise(ArgumentError) { f13(**{a: 1}) } - assert_raise(ArgumentError) { f13(1, **{a: 1}) } - end - def test_method_parameters assert_equal([[:key, :str], [:key, :num]], method(:f1).parameters); assert_equal([[:req, :x], [:key, :str], [:key, :num]], method(:f2).parameters); @@ -190,3185 +147,6 @@ class TestKeywordArguments < Test::Unit::TestCase assert_equal(["bar", 111111], f[str: "bar", num: 111111]) end - def test_keyword_splat_new - kw = {} - h = {a: 1} - - def self.assert_equal_not_same(kw, res) - assert_instance_of(Hash, res) - assert_equal(kw, res) - assert_not_same(kw, res) - end - - def self.y(**kw) kw end - m = method(:y) - assert_equal(false, y(**{}).frozen?) - assert_equal_not_same(kw, y(**kw)) - assert_equal_not_same(h, y(**h)) - assert_equal(false, send(:y, **{}).frozen?) - assert_equal_not_same(kw, send(:y, **kw)) - assert_equal_not_same(h, send(:y, **h)) - assert_equal(false, public_send(:y, **{}).frozen?) - assert_equal_not_same(kw, public_send(:y, **kw)) - assert_equal_not_same(h, public_send(:y, **h)) - assert_equal(false, m.(**{}).frozen?) - assert_equal_not_same(kw, m.(**kw)) - assert_equal_not_same(h, m.(**h)) - assert_equal(false, m.send(:call, **{}).frozen?) - assert_equal_not_same(kw, m.send(:call, **kw)) - assert_equal_not_same(h, m.send(:call, **h)) - - m = method(:send) - assert_equal(false, m.(:y, **{}).frozen?) - assert_equal_not_same(kw, m.(:y, **kw)) - assert_equal_not_same(h, m.(:y, **h)) - assert_equal(false, m.send(:call, :y, **{}).frozen?) - assert_equal_not_same(kw, m.send(:call, :y, **kw)) - assert_equal_not_same(h, m.send(:call, :y, **h)) - - singleton_class.send(:remove_method, :y) - define_singleton_method(:y) { |**kw| kw } - m = method(:y) - assert_equal(false, y(**{}).frozen?) - assert_equal_not_same(kw, y(**kw)) - assert_equal_not_same(h, y(**h)) - assert_equal(false, send(:y, **{}).frozen?) - assert_equal_not_same(kw, send(:y, **kw)) - assert_equal_not_same(h, send(:y, **h)) - assert_equal(false, public_send(:y, **{}).frozen?) - assert_equal_not_same(kw, public_send(:y, **kw)) - assert_equal_not_same(h, public_send(:y, **h)) - assert_equal(false, m.(**{}).frozen?) - assert_equal_not_same(kw, m.(**kw)) - assert_equal_not_same(h, m.(**h)) - assert_equal(false, m.send(:call, **{}).frozen?) - assert_equal_not_same(kw, m.send(:call, **kw)) - assert_equal_not_same(h, m.send(:call, **h)) - - y = lambda { |**kw| kw } - m = y.method(:call) - assert_equal(false, y.(**{}).frozen?) - assert_equal_not_same(kw, y.(**kw)) - assert_equal_not_same(h, y.(**h)) - assert_equal(false, y.send(:call, **{}).frozen?) - assert_equal_not_same(kw, y.send(:call, **kw)) - assert_equal_not_same(h, y.send(:call, **h)) - assert_equal(false, y.public_send(:call, **{}).frozen?) - assert_equal_not_same(kw, y.public_send(:call, **kw)) - assert_equal_not_same(h, y.public_send(:call, **h)) - assert_equal(false, m.(**{}).frozen?) - assert_equal_not_same(kw, m.(**kw)) - assert_equal_not_same(h, m.(**h)) - assert_equal(false, m.send(:call, **{}).frozen?) - assert_equal_not_same(kw, m.send(:call, **kw)) - assert_equal_not_same(h, m.send(:call, **h)) - - y = :y.to_proc - m = y.method(:call) - assert_equal(false, y.(self, **{}).frozen?) - assert_equal_not_same(kw, y.(self, **kw)) - assert_equal_not_same(h, y.(self, **h)) - assert_equal(false, y.send(:call, self, **{}).frozen?) - assert_equal_not_same(kw, y.send(:call, self, **kw)) - assert_equal_not_same(h, y.send(:call, self, **h)) - assert_equal(false, y.public_send(:call, self, **{}).frozen?) - assert_equal_not_same(kw, y.public_send(:call, self, **kw)) - assert_equal_not_same(h, y.public_send(:call, self, **h)) - assert_equal(false, m.(self, **{}).frozen?) - assert_equal_not_same(kw, m.(self, **kw)) - assert_equal_not_same(h, m.(self, **h)) - assert_equal(false, m.send(:call, self, **{}).frozen?) - assert_equal_not_same(kw, m.send(:call, self, **kw)) - assert_equal_not_same(h, m.send(:call, self, **h)) - - c = Class.new do - def y(**kw) kw end - end - o = c.new - def o.y(**kw) super end - m = o.method(:y) - assert_equal(false, o.y(**{}).frozen?) - assert_equal_not_same(kw, o.y(**kw)) - assert_equal_not_same(h, o.y(**h)) - assert_equal(false, o.send(:y, **{}).frozen?) - assert_equal_not_same(kw, o.send(:y, **kw)) - assert_equal_not_same(h, o.send(:y, **h)) - assert_equal(false, o.public_send(:y, **{}).frozen?) - assert_equal_not_same(kw, o.public_send(:y, **kw)) - assert_equal_not_same(h, o.public_send(:y, **h)) - assert_equal(false, m.(**{}).frozen?) - assert_equal_not_same(kw, m.(**kw)) - assert_equal_not_same(h, m.(**h)) - assert_equal(false, m.send(:call, **{}).frozen?) - assert_equal_not_same(kw, m.send(:call, **kw)) - assert_equal_not_same(h, m.send(:call, **h)) - - o.singleton_class.send(:remove_method, :y) - def o.y(**kw) super(**kw) end - assert_equal(false, o.y(**{}).frozen?) - assert_equal_not_same(kw, o.y(**kw)) - assert_equal_not_same(h, o.y(**h)) - assert_equal(false, o.send(:y, **{}).frozen?) - assert_equal_not_same(kw, o.send(:y, **kw)) - assert_equal_not_same(h, o.send(:y, **h)) - assert_equal(false, o.public_send(:y, **{}).frozen?) - assert_equal_not_same(kw, o.public_send(:y, **kw)) - assert_equal_not_same(h, o.public_send(:y, **h)) - assert_equal(false, m.(**{}).frozen?) - assert_equal_not_same(kw, m.(**kw)) - assert_equal_not_same(h, m.(**h)) - assert_equal(false, m.send(:call, **{}).frozen?) - assert_equal_not_same(kw, m.send(:call, **kw)) - assert_equal_not_same(h, m.send(:call, **h)) - - c = Class.new do - def method_missing(_, **kw) kw end - end - o = c.new - def o.y(**kw) super end - m = o.method(:y) - assert_equal(false, o.y(**{}).frozen?) - assert_equal_not_same(kw, o.y(**kw)) - assert_equal_not_same(h, o.y(**h)) - assert_equal(false, o.send(:y, **{}).frozen?) - assert_equal_not_same(kw, o.send(:y, **kw)) - assert_equal_not_same(h, o.send(:y, **h)) - assert_equal(false, o.public_send(:y, **{}).frozen?) - assert_equal_not_same(kw, o.public_send(:y, **kw)) - assert_equal_not_same(h, o.public_send(:y, **h)) - assert_equal(false, m.(**{}).frozen?) - assert_equal_not_same(kw, m.(**kw)) - assert_equal_not_same(h, m.(**h)) - assert_equal(false, m.send(:call, **{}).frozen?) - assert_equal_not_same(kw, m.send(:call, **kw)) - assert_equal_not_same(h, m.send(:call, **h)) - - o.singleton_class.send(:remove_method, :y) - def o.y(**kw) super(**kw) end - assert_equal(false, o.y(**{}).frozen?) - assert_equal_not_same(kw, o.y(**kw)) - assert_equal_not_same(h, o.y(**h)) - assert_equal(false, o.send(:y, **{}).frozen?) - assert_equal_not_same(kw, o.send(:y, **kw)) - assert_equal_not_same(h, o.send(:y, **h)) - assert_equal(false, o.public_send(:y, **{}).frozen?) - assert_equal_not_same(kw, o.public_send(:y, **kw)) - assert_equal_not_same(h, o.public_send(:y, **h)) - assert_equal(false, m.(**{}).frozen?) - assert_equal_not_same(kw, m.(**kw)) - assert_equal_not_same(h, m.(**h)) - assert_equal(false, m.send(:call, **{}).frozen?) - assert_equal_not_same(kw, m.send(:call, **kw)) - assert_equal_not_same(h, m.send(:call, **h)) - - c = Class.new do - attr_reader :kw - def initialize(**kw) @kw = kw end - end - m = c.method(:new) - assert_equal(false, c.new(**{}).kw.frozen?) - assert_equal_not_same(kw, c.new(**kw).kw) - assert_equal_not_same(h, c.new(**h).kw) - assert_equal(false, c.send(:new, **{}).kw.frozen?) - assert_equal_not_same(kw, c.send(:new, **kw).kw) - assert_equal_not_same(h, c.send(:new, **h).kw) - assert_equal(false, c.public_send(:new, **{}).kw.frozen?) - assert_equal_not_same(kw, c.public_send(:new, **kw).kw) - assert_equal_not_same(h, c.public_send(:new, **h).kw) - assert_equal(false, m.(**{}).kw.frozen?) - assert_equal_not_same(kw, m.(**kw).kw) - assert_equal_not_same(h, m.(**h).kw) - assert_equal(false, m.send(:call, **{}).kw.frozen?) - assert_equal_not_same(kw, m.send(:call, **kw).kw) - assert_equal_not_same(h, m.send(:call, **h).kw) - - singleton_class.send(:attr_writer, :y) - m = method(:y=) - assert_equal_not_same(h, send(:y=, **h)) - assert_equal_not_same(h, public_send(:y=, **h)) - assert_equal_not_same(h, m.(**h)) - assert_equal_not_same(h, m.send(:call, **h)) - - singleton_class.send(:remove_method, :y) - def self.method_missing(_, **kw) kw end - assert_equal(false, y(**{}).frozen?) - assert_equal_not_same(kw, y(**kw)) - assert_equal_not_same(h, y(**h)) - assert_equal(false, send(:y, **{}).frozen?) - assert_equal_not_same(kw, send(:y, **kw)) - assert_equal_not_same(h, send(:y, **h)) - assert_equal(false, public_send(:y, **{}).frozen?) - assert_equal_not_same(kw, public_send(:y, **kw)) - assert_equal_not_same(h, public_send(:y, **h)) - end - - def test_regular_kwsplat - kw = {} - h = {:a=>1} - h2 = {'a'=>1} - h3 = {'a'=>1, :a=>1} - - c = Object.new - def c.m(*args) - args - end - assert_equal([], c.m(**{})) - assert_equal([], c.m(**kw)) - assert_equal([h], c.m(**h)) - assert_equal([h], c.m(a: 1)) - assert_equal([h2], c.m(**h2)) - assert_equal([h3], c.m(**h3)) - assert_equal([h3], c.m(a: 1, **h2)) - - c.singleton_class.remove_method(:m) - def c.m; end - assert_nil(c.m(**{})) - assert_nil(c.m(**kw)) - assert_raise(ArgumentError) { c.m(**h) } - assert_raise(ArgumentError) { c.m(a: 1) } - assert_raise(ArgumentError) { c.m(**h2) } - assert_raise(ArgumentError) { c.m(**h3) } - assert_raise(ArgumentError) { c.m(a: 1, **h2) } - - c.singleton_class.remove_method(:m) - def c.m(args) - args - end - assert_raise(ArgumentError) { c.m(**{}) } - assert_raise(ArgumentError) { c.m(**kw) } - assert_equal(kw, c.m(kw, **kw)) - assert_equal(h, c.m(**h)) - assert_equal(h, c.m(a: 1)) - assert_equal(h2, c.m(**h2)) - assert_equal(h3, c.m(**h3)) - assert_equal(h3, c.m(a: 1, **h2)) - - c.singleton_class.remove_method(:m) - def c.m(**args) - args - end - assert_equal(kw, c.m(**{})) - assert_equal(kw, c.m(**kw)) - assert_equal(h, c.m(**h)) - assert_equal(h, c.m(a: 1)) - assert_equal(h2, c.m(**h2)) - assert_equal(h3, c.m(**h3)) - assert_equal(h3, c.m(a: 1, **h2)) - assert_raise(ArgumentError) { c.m(h) } - assert_raise(ArgumentError) { c.m(h2) } - assert_raise(ArgumentError) { c.m(h3) } - - c.singleton_class.remove_method(:m) - def c.m(arg, **args) - [arg, args] - end - assert_raise(ArgumentError) { c.m(**{}) } - assert_raise(ArgumentError) { c.m(**kw) } - assert_raise(ArgumentError) { c.m(**h) } - assert_raise(ArgumentError) { c.m(a: 1) } - assert_raise(ArgumentError) { c.m(**h2) } - assert_raise(ArgumentError) { c.m(**h3) } - assert_raise(ArgumentError) { c.m(a: 1, **h2) } - assert_equal([h, kw], c.m(h)) - assert_equal([h2, kw], c.m(h2)) - assert_equal([h3, kw], c.m(h3)) - - c.singleton_class.remove_method(:m) - def c.m(arg=1, **args) - [arg, args] - end - assert_equal([1, kw], c.m(**{})) - assert_equal([1, kw], c.m(**kw)) - assert_equal([1, h], c.m(**h)) - assert_equal([1, h], c.m(a: 1)) - assert_equal([1, h2], c.m(**h2)) - assert_equal([1, h3], c.m(**h3)) - assert_equal([1, h3], c.m(a: 1, **h2)) - assert_equal([h, kw], c.m(h)) - assert_equal([h2, kw], c.m(h2)) - assert_equal([h3, kw], c.m(h3)) - end - - def test_implicit_super_kwsplat - kw = {} - h = {:a=>1} - h2 = {'a'=>1} - h3 = {'a'=>1, :a=>1} - - sc = Class.new - c = sc.new - def c.m(*args, **kw) - super(*args, **kw) - end - sc.class_eval do - def m(*args) - args - end - end - assert_equal([], c.m(**{})) - assert_equal([], c.m(**kw)) - assert_equal([h], c.m(**h)) - assert_equal([h], c.m(a: 1)) - assert_equal([h2], c.m(**h2)) - assert_equal([h3], c.m(**h3)) - assert_equal([h3], c.m(a: 1, **h2)) - - sc.class_eval do - remove_method(:m) - def m; end - end - assert_nil(c.m(**{})) - assert_nil(c.m(**kw)) - assert_raise(ArgumentError) { c.m(**h) } - assert_raise(ArgumentError) { c.m(a: 1) } - assert_raise(ArgumentError) { c.m(**h2) } - assert_raise(ArgumentError) { c.m(**h3) } - assert_raise(ArgumentError) { c.m(a: 1, **h2) } - - sc.class_eval do - remove_method(:m) - def m(args) - args - end - end - assert_raise(ArgumentError) { c.m(**{}) } - assert_raise(ArgumentError) { c.m(**kw) } - assert_equal(h, c.m(**h)) - assert_equal(h, c.m(a: 1)) - assert_equal(h2, c.m(**h2)) - assert_equal(h3, c.m(**h3)) - assert_equal(h3, c.m(a: 1, **h2)) - - sc.class_eval do - remove_method(:m) - def m(**args) - args - end - end - assert_equal(kw, c.m(**{})) - assert_equal(kw, c.m(**kw)) - assert_equal(h, c.m(**h)) - assert_equal(h, c.m(a: 1)) - assert_equal(h2, c.m(**h2)) - assert_equal(h3, c.m(**h3)) - assert_equal(h3, c.m(a: 1, **h2)) - assert_raise(ArgumentError) { c.m(h) } - assert_raise(ArgumentError) { c.m(h2) } - assert_raise(ArgumentError) { c.m(h3) } - - sc.class_eval do - remove_method(:m) - def m(arg, **args) - [arg, args] - end - end - assert_raise(ArgumentError) { c.m(**{}) } - assert_raise(ArgumentError) { c.m(**kw) } - assert_raise(ArgumentError) { c.m(**h) } - assert_raise(ArgumentError) { c.m(a: 1) } - assert_raise(ArgumentError) { c.m(**h2) } - assert_raise(ArgumentError) { c.m(**h3) } - assert_raise(ArgumentError) { c.m(a: 1, **h2) } - - sc.class_eval do - remove_method(:m) - def m(arg=1, **args) - [arg, args] - end - end - assert_equal([1, kw], c.m(**{})) - assert_equal([1, kw], c.m(**kw)) - assert_equal([1, h], c.m(**h)) - assert_equal([1, h], c.m(a: 1)) - assert_equal([1, h2], c.m(**h2)) - assert_equal([1, h3], c.m(**h3)) - assert_equal([1, h3], c.m(a: 1, **h2)) - end - - def test_explicit_super_kwsplat - kw = {} - h = {:a=>1} - h2 = {'a'=>1} - h3 = {'a'=>1, :a=>1} - - sc = Class.new - c = sc.new - def c.m(*args, **kw) - super(*args, **kw) - end - sc.class_eval do - def m(*args) - args - end - end - assert_equal([], c.m(**{})) - assert_equal([], c.m(**kw)) - assert_equal([h], c.m(**h)) - assert_equal([h], c.m(a: 1)) - assert_equal([h2], c.m(**h2)) - assert_equal([h3], c.m(**h3)) - assert_equal([h3], c.m(a: 1, **h2)) - - sc.class_eval do - remove_method(:m) - def m; end - end - assert_nil(c.m(**{})) - assert_nil(c.m(**kw)) - assert_raise(ArgumentError) { c.m(**h) } - assert_raise(ArgumentError) { c.m(a: 1) } - assert_raise(ArgumentError) { c.m(**h2) } - assert_raise(ArgumentError) { c.m(**h3) } - assert_raise(ArgumentError) { c.m(a: 1, **h2) } - - sc.class_eval do - remove_method(:m) - def m(args) - args - end - end - assert_raise(ArgumentError) { c.m(**{}) } - assert_raise(ArgumentError) { c.m(**kw) } - assert_equal(h, c.m(**h)) - assert_equal(h, c.m(a: 1)) - assert_equal(h2, c.m(**h2)) - assert_equal(h3, c.m(**h3)) - assert_equal(h3, c.m(a: 1, **h2)) - - sc.class_eval do - remove_method(:m) - def m(**args) - args - end - end - assert_equal(kw, c.m(**{})) - assert_equal(kw, c.m(**kw)) - assert_equal(h, c.m(**h)) - assert_equal(h, c.m(a: 1)) - assert_equal(h2, c.m(**h2)) - assert_equal(h3, c.m(**h3)) - assert_equal(h3, c.m(a: 1, **h2)) - assert_raise(ArgumentError) { c.m(h) } - assert_raise(ArgumentError) { c.m(h2) } - assert_raise(ArgumentError) { c.m(h3) } - - sc.class_eval do - remove_method(:m) - def m(arg, **args) - [arg, args] - end - end - assert_raise(ArgumentError) { c.m(**{}) } - assert_raise(ArgumentError) { c.m(**kw) } - assert_raise(ArgumentError) { c.m(**h) } - assert_raise(ArgumentError) { c.m(a: 1) } - assert_raise(ArgumentError) { c.m(**h2) } - assert_raise(ArgumentError) { c.m(**h3) } - assert_raise(ArgumentError) { c.m(a: 1, **h2) } - - sc.class_eval do - remove_method(:m) - def m(arg=1, **args) - [arg, args] - end - end - assert_equal([1, kw], c.m(**{})) - assert_equal([1, kw], c.m(**kw)) - assert_equal([1, h], c.m(**h)) - assert_equal([1, h], c.m(a: 1)) - assert_equal([1, h2], c.m(**h2)) - assert_equal([1, h3], c.m(**h3)) - assert_equal([1, h3], c.m(a: 1, **h2)) - end - - def test_lambda_kwsplat_call - kw = {} - h = {:a=>1} - h2 = {'a'=>1} - h3 = {'a'=>1, :a=>1} - - f = -> { true } - assert_equal(true, f[**{}]) - assert_equal(true, f[**kw]) - assert_raise(ArgumentError) { f[**h] } - assert_raise(ArgumentError) { f[a: 1] } - assert_raise(ArgumentError) { f[**h2] } - assert_raise(ArgumentError) { f[**h3] } - - f = ->(a) { a } - assert_raise(ArgumentError) { f[**{}] } - assert_raise(ArgumentError) { f[**kw] } - assert_equal(h, f[**h]) - assert_equal(h, f[a: 1]) - assert_equal(h2, f[**h2]) - assert_equal(h3, f[**h3]) - assert_equal(h3, f[a: 1, **h2]) - - f = ->(**x) { x } - assert_equal(kw, f[**{}]) - assert_equal(kw, f[**kw]) - assert_equal(h, f[**h]) - assert_equal(h, f[a: 1]) - assert_equal(h2, f[**h2]) - assert_equal(h3, f[**h3]) - assert_equal(h3, f[a: 1, **h2]) - assert_raise(ArgumentError) { f[h] } - assert_raise(ArgumentError) { f[h2] } - assert_raise(ArgumentError) { f[h3] } - - f = ->(a, **x) { [a,x] } - assert_raise(ArgumentError) { f[**{}] } - assert_raise(ArgumentError) { f[**kw] } - assert_raise(ArgumentError) { f[**h] } - assert_raise(ArgumentError) { f[a: 1] } - assert_raise(ArgumentError) { f[**h2] } - assert_raise(ArgumentError) { f[**h3] } - assert_raise(ArgumentError) { f[a: 1, **h2] } - - f = ->(a=1, **x) { [a, x] } - assert_equal([1, kw], f[**{}]) - assert_equal([1, kw], f[**kw]) - assert_equal([1, h], f[**h]) - assert_equal([1, h], f[a: 1]) - assert_equal([1, h2], f[**h2]) - assert_equal([1, h3], f[**h3]) - assert_equal([1, h3], f[a: 1, **h2]) - end - - def test_lambda_method_kwsplat_call - kw = {} - h = {:a=>1} - h2 = {'a'=>1} - h3 = {'a'=>1, :a=>1} - - f = -> { true } - f = f.method(:call) - assert_equal(true, f[**{}]) - assert_equal(true, f[**kw]) - assert_raise(ArgumentError) { f[**h] } - assert_raise(ArgumentError) { f[a: 1] } - assert_raise(ArgumentError) { f[**h2] } - assert_raise(ArgumentError) { f[**h3] } - - f = ->(a) { a } - f = f.method(:call) - assert_raise(ArgumentError) { f[**{}] } - assert_raise(ArgumentError) { f[**kw] } - assert_equal(h, f[**h]) - assert_equal(h, f[a: 1]) - assert_equal(h2, f[**h2]) - assert_equal(h3, f[**h3]) - assert_equal(h3, f[a: 1, **h2]) - - f = ->(**x) { x } - f = f.method(:call) - assert_equal(kw, f[**{}]) - assert_equal(kw, f[**kw]) - assert_equal(h, f[**h]) - assert_equal(h, f[a: 1]) - assert_equal(h2, f[**h2]) - assert_equal(h3, f[**h3]) - assert_equal(h3, f[a: 1, **h2]) - assert_raise(ArgumentError) { f[h] } - assert_raise(ArgumentError) { f[h2] } - assert_raise(ArgumentError) { f[h3] } - - f = ->(a, **x) { [a,x] } - f = f.method(:call) - assert_raise(ArgumentError) { f[**{}] } - assert_raise(ArgumentError) { f[**kw] } - assert_raise(ArgumentError) { f[**h] } - assert_raise(ArgumentError) { f[a: 1] } - assert_raise(ArgumentError) { f[**h2] } - assert_raise(ArgumentError) { f[**h3] } - assert_raise(ArgumentError) { f[a: 1, **h2] } - - f = ->(a=1, **x) { [a, x] } - f = f.method(:call) - assert_equal([1, kw], f[**{}]) - assert_equal([1, kw], f[**kw]) - assert_equal([1, h], f[**h]) - assert_equal([1, h], f[a: 1]) - assert_equal([1, h2], f[**h2]) - assert_equal([1, h3], f[**h3]) - assert_equal([1, h3], f[a: 1, **h2]) - end - - def test_Thread_new_kwsplat - Thread.report_on_exception = false - kw = {} - h = {:a=>1} - h2 = {'a'=>1} - h3 = {'a'=>1, :a=>1} - - t = Thread - f = -> { true } - assert_equal(true, t.new(**{}, &f).value) - assert_equal(true, t.new(**kw, &f).value) - assert_raise(ArgumentError) { t.new(**h, &f).value } - assert_raise(ArgumentError) { t.new(a: 1, &f).value } - assert_raise(ArgumentError) { t.new(**h2, &f).value } - assert_raise(ArgumentError) { t.new(**h3, &f).value } - - f = ->(a) { a } - assert_raise(ArgumentError) { t.new(**{}, &f).value } - assert_raise(ArgumentError) { t.new(**kw, &f).value } - assert_equal(h, t.new(**h, &f).value) - assert_equal(h, t.new(a: 1, &f).value) - assert_equal(h2, t.new(**h2, &f).value) - assert_equal(h3, t.new(**h3, &f).value) - assert_equal(h3, t.new(a: 1, **h2, &f).value) - - f = ->(**x) { x } - assert_equal(kw, t.new(**{}, &f).value) - assert_equal(kw, t.new(**kw, &f).value) - assert_equal(h, t.new(**h, &f).value) - assert_equal(h, t.new(a: 1, &f).value) - assert_equal(h2, t.new(**h2, &f).value) - assert_equal(h3, t.new(**h3, &f).value) - assert_equal(h3, t.new(a: 1, **h2, &f).value) - assert_raise(ArgumentError) { t.new(h, &f).value } - assert_raise(ArgumentError) { t.new(h2, &f).value } - assert_raise(ArgumentError) { t.new(h3, &f).value } - - f = ->(a, **x) { [a,x] } - assert_raise(ArgumentError) { t.new(**{}, &f).value } - assert_raise(ArgumentError) { t.new(**kw, &f).value } - assert_raise(ArgumentError) { t.new(**h, &f).value } - assert_raise(ArgumentError) { t.new(a: 1, &f).value } - assert_raise(ArgumentError) { t.new(**h2, &f).value } - assert_raise(ArgumentError) { t.new(**h3, &f).value } - assert_raise(ArgumentError) { t.new(a: 1, **h2, &f).value } - - f = ->(a=1, **x) { [a, x] } - assert_equal([1, kw], t.new(**{}, &f).value) - assert_equal([1, kw], t.new(**kw, &f).value) - assert_equal([1, h], t.new(**h, &f).value) - assert_equal([1, h], t.new(a: 1, &f).value) - assert_equal([1, h2], t.new(**h2, &f).value) - assert_equal([1, h3], t.new(**h3, &f).value) - assert_equal([1, h3], t.new(a: 1, **h2, &f).value) - ensure - Thread.report_on_exception = true - end - - def test_Fiber_resume_kwsplat - kw = {} - h = {:a=>1} - h2 = {'a'=>1} - h3 = {'a'=>1, :a=>1} - - t = Fiber - f = -> { true } - assert_equal(true, t.new(&f).resume(**{})) - assert_equal(true, t.new(&f).resume(**kw)) - assert_raise(ArgumentError) { t.new(&f).resume(**h) } - assert_raise(ArgumentError) { t.new(&f).resume(a: 1) } - assert_raise(ArgumentError) { t.new(&f).resume(**h2) } - assert_raise(ArgumentError) { t.new(&f).resume(**h3) } - - f = ->(a) { a } - assert_raise(ArgumentError) { t.new(&f).resume(**{}) } - assert_raise(ArgumentError) { t.new(&f).resume(**kw) } - assert_equal(h, t.new(&f).resume(**h)) - assert_equal(h, t.new(&f).resume(a: 1)) - assert_equal(h2, t.new(&f).resume(**h2)) - assert_equal(h3, t.new(&f).resume(**h3)) - assert_equal(h3, t.new(&f).resume(a: 1, **h2)) - - f = ->(**x) { x } - assert_equal(kw, t.new(&f).resume(**{})) - assert_equal(kw, t.new(&f).resume(**kw)) - assert_equal(h, t.new(&f).resume(**h)) - assert_equal(h, t.new(&f).resume(a: 1)) - assert_equal(h2, t.new(&f).resume(**h2)) - assert_equal(h3, t.new(&f).resume(**h3)) - assert_equal(h3, t.new(&f).resume(a: 1, **h2)) - assert_raise(ArgumentError) { t.new(&f).resume(h) } - assert_raise(ArgumentError) { t.new(&f).resume(h2) } - assert_raise(ArgumentError) { t.new(&f).resume(h3) } - - f = ->(a, **x) { [a,x] } - assert_raise(ArgumentError) { t.new(&f).resume(**{}) } - assert_raise(ArgumentError) { t.new(&f).resume(**kw) } - assert_raise(ArgumentError) { t.new(&f).resume(**h) } - assert_raise(ArgumentError) { t.new(&f).resume(a: 1) } - assert_raise(ArgumentError) { t.new(&f).resume(**h2) } - assert_raise(ArgumentError) { t.new(&f).resume(**h3) } - assert_raise(ArgumentError) { t.new(&f).resume(a: 1, **h2) } - - f = ->(a=1, **x) { [a, x] } - assert_equal([1, kw], t.new(&f).resume(**{})) - assert_equal([1, kw], t.new(&f).resume(**kw)) - assert_equal([1, h], t.new(&f).resume(**h)) - assert_equal([1, h], t.new(&f).resume(a: 1)) - assert_equal([1, h2], t.new(&f).resume(**h2)) - assert_equal([1, h3], t.new(&f).resume(**h3)) - assert_equal([1, h3], t.new(&f).resume(a: 1, **h2)) - end - - def test_Enumerator_Generator_each_kwsplat - kw = {} - h = {:a=>1} - h2 = {'a'=>1} - h3 = {'a'=>1, :a=>1} - - g = Enumerator::Generator - f = ->(_) { true } - assert_equal(true, g.new(&f).each(**{})) - assert_equal(true, g.new(&f).each(**kw)) - assert_raise(ArgumentError) { g.new(&f).each(**h) } - assert_raise(ArgumentError) { g.new(&f).each(a: 1) } - assert_raise(ArgumentError) { g.new(&f).each(**h2) } - assert_raise(ArgumentError) { g.new(&f).each(**h3) } - - f = ->(_, a) { a } - assert_raise(ArgumentError) { g.new(&f).each(**{}) } - assert_raise(ArgumentError) { g.new(&f).each(**kw) } - assert_equal(h, g.new(&f).each(**h)) - assert_equal(h, g.new(&f).each(a: 1)) - assert_equal(h2, g.new(&f).each(**h2)) - assert_equal(h3, g.new(&f).each(**h3)) - assert_equal(h3, g.new(&f).each(a: 1, **h2)) - - f = ->(_, **x) { x } - assert_equal(kw, g.new(&f).each(**{})) - assert_equal(kw, g.new(&f).each(**kw)) - assert_equal(h, g.new(&f).each(**h)) - assert_equal(h, g.new(&f).each(a: 1)) - assert_equal(h2, g.new(&f).each(**h2)) - assert_equal(h3, g.new(&f).each(**h3)) - assert_equal(h3, g.new(&f).each(a: 1, **h2)) - assert_raise(ArgumentError) { g.new(&f).each(h) } - assert_raise(ArgumentError) { g.new(&f).each(h2) } - assert_raise(ArgumentError) { g.new(&f).each(h3) } - - f = ->(_, a, **x) { [a,x] } - assert_raise(ArgumentError) { g.new(&f).each(**{}) } - assert_raise(ArgumentError) { g.new(&f).each(**kw) } - assert_raise(ArgumentError) { g.new(&f).each(**h) } - assert_raise(ArgumentError) { g.new(&f).each(a: 1) } - assert_raise(ArgumentError) { g.new(&f).each(**h2) } - assert_raise(ArgumentError) { g.new(&f).each(**h3) } - assert_raise(ArgumentError) { g.new(&f).each(a: 1, **h2) } - - f = ->(_, a=1, **x) { [a, x] } - assert_equal([1, kw], g.new(&f).each(**{})) - assert_equal([1, kw], g.new(&f).each(**kw)) - assert_equal([1, h], g.new(&f).each(**h)) - assert_equal([1, h], g.new(&f).each(a: 1)) - assert_equal([1, h2], g.new(&f).each(**h2)) - assert_equal([1, h3], g.new(&f).each(**h3)) - assert_equal([1, h3], g.new(&f).each(a: 1, **h2)) - end - - def test_Enumerator_Yielder_yield_kwsplat - kw = {} - h = {:a=>1} - h2 = {'a'=>1} - h3 = {'a'=>1, :a=>1} - - g = Enumerator::Generator - f = -> { true } - assert_equal(true, g.new{|y| y.yield(**{})}.each(&f)) - assert_equal(true, g.new{|y| y.yield(**kw)}.each(&f)) - assert_raise(ArgumentError) { g.new{|y| y.yield(**h)}.each(&f) } - assert_raise(ArgumentError) { g.new{|y| y.yield(a: 1)}.each(&f) } - assert_raise(ArgumentError) { g.new{|y| y.yield(**h2)}.each(&f) } - assert_raise(ArgumentError) { g.new{|y| y.yield(**h3)}.each(&f) } - - f = ->(a) { a } - assert_raise(ArgumentError) { g.new{|y| y.yield(**{})}.each(&f) } - assert_raise(ArgumentError) { g.new{|y| y.yield(**kw)}.each(&f) } - assert_equal(h, g.new{|y| y.yield(**h)}.each(&f)) - assert_equal(h, g.new{|y| y.yield(a: 1)}.each(&f)) - assert_equal(h2, g.new{|y| y.yield(**h2)}.each(&f)) - assert_equal(h3, g.new{|y| y.yield(**h3)}.each(&f)) - assert_equal(h3, g.new{|y| y.yield(a: 1, **h2)}.each(&f)) - - f = ->(**x) { x } - assert_equal(kw, g.new{|y| y.yield(**{})}.each(&f)) - assert_equal(kw, g.new{|y| y.yield(**kw)}.each(&f)) - assert_equal(h, g.new{|y| y.yield(**h)}.each(&f)) - assert_equal(h, g.new{|y| y.yield(a: 1)}.each(&f)) - assert_equal(h2, g.new{|y| y.yield(**h2)}.each(&f)) - assert_equal(h3, g.new{|y| y.yield(**h3)}.each(&f)) - assert_equal(h3, g.new{|y| y.yield(a: 1, **h2)}.each(&f)) - assert_raise(ArgumentError) { g.new{|y| y.yield(h)}.each(&f) } - assert_raise(ArgumentError) { g.new{|y| y.yield(h2)}.each(&f) } - assert_raise(ArgumentError) { g.new{|y| y.yield(h3)}.each(&f) } - - f = ->(a, **x) { [a,x] } - assert_raise(ArgumentError) { g.new{|y| y.yield(**{})}.each(&f) } - assert_raise(ArgumentError) { g.new{|y| y.yield(**kw)}.each(&f) } - assert_raise(ArgumentError) { g.new{|y| y.yield(**h)}.each(&f) } - assert_raise(ArgumentError) { g.new{|y| y.yield(a: 1)}.each(&f) } - assert_raise(ArgumentError) { g.new{|y| y.yield(**h2)}.each(&f) } - assert_raise(ArgumentError) { g.new{|y| y.yield(**h3)}.each(&f) } - assert_raise(ArgumentError) { g.new{|y| y.yield(a: 1, **h2)}.each(&f) } - - f = ->(a=1, **x) { [a, x] } - assert_equal([1, kw], g.new{|y| y.yield(**{})}.each(&f)) - assert_equal([1, kw], g.new{|y| y.yield(**kw)}.each(&f)) - assert_equal([1, h], g.new{|y| y.yield(**h)}.each(&f)) - assert_equal([1, h], g.new{|y| y.yield(a: 1)}.each(&f)) - assert_equal([1, h2], g.new{|y| y.yield(**h2)}.each(&f)) - assert_equal([1, h3], g.new{|y| y.yield(**h3)}.each(&f)) - assert_equal([1, h3], g.new{|y| y.yield(a: 1, **h2)}.each(&f)) - end - - def test_Class_new_kwsplat_call - kw = {} - h = {:a=>1} - h2 = {'a'=>1} - h3 = {'a'=>1, :a=>1} - - sc = Class.new do - attr_reader :args - class << self - alias [] new - end - end - - c = Class.new(sc) do - def initialize(*args) - @args = args - end - end - assert_equal([], c[**{}].args) - assert_equal([], c[**kw].args) - assert_equal([h], c[**h].args) - assert_equal([h], c[a: 1].args) - assert_equal([h2], c[**h2].args) - assert_equal([h3], c[**h3].args) - assert_equal([h3], c[a: 1, **h2].args) - - c = Class.new(sc) do - def initialize; end - end - assert_nil(c[**{}].args) - assert_nil(c[**kw].args) - assert_raise(ArgumentError) { c[**h] } - assert_raise(ArgumentError) { c[a: 1] } - assert_raise(ArgumentError) { c[**h2] } - assert_raise(ArgumentError) { c[**h3] } - assert_raise(ArgumentError) { c[a: 1, **h2] } - - c = Class.new(sc) do - def initialize(args) - @args = args - end - end - assert_raise(ArgumentError) { c[**{}] } - assert_raise(ArgumentError) { c[**kw] } - assert_equal(h, c[**h].args) - assert_equal(h, c[a: 1].args) - assert_equal(h2, c[**h2].args) - assert_equal(h3, c[**h3].args) - assert_equal(h3, c[a: 1, **h2].args) - - c = Class.new(sc) do - def initialize(**args) - @args = args - end - end - assert_equal(kw, c[**{}].args) - assert_equal(kw, c[**kw].args) - assert_equal(h, c[**h].args) - assert_equal(h, c[a: 1].args) - assert_equal(h2, c[**h2].args) - assert_equal(h3, c[**h3].args) - assert_equal(h3, c[a: 1, **h2].args) - assert_raise(ArgumentError) { c[h].args } - assert_raise(ArgumentError) { c[h2].args } - assert_raise(ArgumentError) { c[h3].args } - - c = Class.new(sc) do - def initialize(arg, **args) - @args = [arg, args] - end - end - assert_raise(ArgumentError) { c[**{}].args } - assert_raise(ArgumentError) { c[**kw].args } - assert_raise(ArgumentError) { c[**h].args } - assert_raise(ArgumentError) { c[a: 1].args } - assert_raise(ArgumentError) { c[**h2].args } - assert_raise(ArgumentError) { c[**h3].args } - assert_raise(ArgumentError) { c[a: 1, **h2].args } - - c = Class.new(sc) do - def initialize(arg=1, **args) - @args = [arg, args] - end - end - assert_equal([1, kw], c[**{}].args) - assert_equal([1, kw], c[**kw].args) - assert_equal([1, h], c[**h].args) - assert_equal([1, h], c[a: 1].args) - assert_equal([1, h2], c[**h2].args) - assert_equal([1, h3], c[**h3].args) - assert_equal([1, h3], c[a: 1, **h2].args) - end - - def test_Class_new_method_kwsplat_call - kw = {} - h = {:a=>1} - h2 = {'a'=>1} - h3 = {'a'=>1, :a=>1} - - sc = Class.new do - attr_reader :args - end - - c = Class.new(sc) do - def initialize(*args) - @args = args - end - end.method(:new) - assert_equal([], c[**{}].args) - assert_equal([], c[**kw].args) - assert_equal([h], c[**h].args) - assert_equal([h], c[a: 1].args) - assert_equal([h2], c[**h2].args) - assert_equal([h3], c[**h3].args) - assert_equal([h3], c[a: 1, **h2].args) - - c = Class.new(sc) do - def initialize; end - end.method(:new) - assert_nil(c[**{}].args) - assert_nil(c[**kw].args) - assert_raise(ArgumentError) { c[**h] } - assert_raise(ArgumentError) { c[a: 1] } - assert_raise(ArgumentError) { c[**h2] } - assert_raise(ArgumentError) { c[**h3] } - assert_raise(ArgumentError) { c[a: 1, **h2] } - - c = Class.new(sc) do - def initialize(args) - @args = args - end - end.method(:new) - assert_raise(ArgumentError) { c[**{}] } - assert_raise(ArgumentError) { c[**kw] } - assert_equal(h, c[**h].args) - assert_equal(h, c[a: 1].args) - assert_equal(h2, c[**h2].args) - assert_equal(h3, c[**h3].args) - assert_equal(h3, c[a: 1, **h2].args) - - c = Class.new(sc) do - def initialize(**args) - @args = args - end - end.method(:new) - assert_equal(kw, c[**{}].args) - assert_equal(kw, c[**kw].args) - assert_equal(h, c[**h].args) - assert_equal(h, c[a: 1].args) - assert_equal(h2, c[**h2].args) - assert_equal(h3, c[**h3].args) - assert_equal(h3, c[a: 1, **h2].args) - assert_raise(ArgumentError) { c[h].args } - assert_raise(ArgumentError) { c[h2].args } - assert_raise(ArgumentError) { c[h3].args } - - c = Class.new(sc) do - def initialize(arg, **args) - @args = [arg, args] - end - end.method(:new) - assert_raise(ArgumentError) { c[**{}].args } - assert_raise(ArgumentError) { c[**kw].args } - assert_raise(ArgumentError) { c[**h].args } - assert_raise(ArgumentError) { c[a: 1].args } - assert_raise(ArgumentError) { c[**h2].args } - assert_raise(ArgumentError) { c[**h3].args } - assert_raise(ArgumentError) { c[a: 1, **h2].args } - - c = Class.new(sc) do - def initialize(arg=1, **args) - @args = [arg, args] - end - end.method(:new) - assert_equal([1, kw], c[**{}].args) - assert_equal([1, kw], c[**kw].args) - assert_equal([1, h], c[**h].args) - assert_equal([1, h], c[a: 1].args) - assert_equal([1, h2], c[**h2].args) - assert_equal([1, h3], c[**h3].args) - assert_equal([1, h3], c[a: 1, **h2].args) - end - - def test_Method_call_kwsplat_call - kw = {} - h = {:a=>1} - h2 = {'a'=>1} - h3 = {'a'=>1, :a=>1} - - c = Object.new - def c.m(*args) - args - end - assert_equal([], c.method(:m)[**{}]) - assert_equal([], c.method(:m)[**kw]) - assert_equal([h], c.method(:m)[**h]) - assert_equal([h], c.method(:m)[a: 1]) - assert_equal([h2], c.method(:m)[**h2]) - assert_equal([h3], c.method(:m)[**h3]) - assert_equal([h3], c.method(:m)[a: 1, **h2]) - - c.singleton_class.remove_method(:m) - def c.m; end - assert_nil(c.method(:m)[**{}]) - assert_nil(c.method(:m)[**kw]) - assert_raise(ArgumentError) { c.method(:m)[**h] } - assert_raise(ArgumentError) { c.method(:m)[a: 1] } - assert_raise(ArgumentError) { c.method(:m)[**h2] } - assert_raise(ArgumentError) { c.method(:m)[**h3] } - assert_raise(ArgumentError) { c.method(:m)[a: 1, **h2] } - - c.singleton_class.remove_method(:m) - def c.m(args) - args - end - assert_raise(ArgumentError) { c.method(:m)[**{}] } - assert_raise(ArgumentError) { c.method(:m)[**kw] } - assert_equal(h, c.method(:m)[**h]) - assert_equal(h, c.method(:m)[a: 1]) - assert_equal(h2, c.method(:m)[**h2]) - assert_equal(h3, c.method(:m)[**h3]) - assert_equal(h3, c.method(:m)[a: 1, **h2]) - - c.singleton_class.remove_method(:m) - def c.m(**args) - args - end - assert_equal(kw, c.method(:m)[**{}]) - assert_equal(kw, c.method(:m)[**kw]) - assert_equal(h, c.method(:m)[**h]) - assert_equal(h, c.method(:m)[a: 1]) - assert_equal(h2, c.method(:m)[**h2]) - assert_equal(h3, c.method(:m)[**h3]) - assert_equal(h3, c.method(:m)[a: 1, **h2]) - assert_raise(ArgumentError) { c.method(:m)[h] } - assert_raise(ArgumentError) { c.method(:m)[h2] } - assert_raise(ArgumentError) { c.method(:m)[h3] } - - c.singleton_class.remove_method(:m) - def c.m(arg, **args) - [arg, args] - end - assert_raise(ArgumentError) { c.method(:m)[**{}] } - assert_raise(ArgumentError) { c.method(:m)[**kw] } - assert_raise(ArgumentError) { c.method(:m)[**h] } - assert_raise(ArgumentError) { c.method(:m)[a: 1] } - assert_raise(ArgumentError) { c.method(:m)[**h2] } - assert_raise(ArgumentError) { c.method(:m)[**h3] } - assert_raise(ArgumentError) { c.method(:m)[a: 1, **h2] } - - c.singleton_class.remove_method(:m) - def c.m(arg=1, **args) - [arg, args] - end - assert_equal([1, kw], c.method(:m)[**{}]) - assert_equal([1, kw], c.method(:m)[**kw]) - assert_equal([1, h], c.method(:m)[**h]) - assert_equal([1, h], c.method(:m)[a: 1]) - assert_equal([1, h2], c.method(:m)[**h2]) - assert_equal([1, h3], c.method(:m)[**h3]) - assert_equal([1, h3], c.method(:m)[a: 1, **h2]) - end - - def test_UnboundMethod_bindcall_kwsplat_call - kw = {} - h = {:a=>1} - h2 = {'a'=>1} - h3 = {'a'=>1, :a=>1} - - c = Object.new - sc = c.singleton_class - def c.m(*args) - args - end - assert_equal([], sc.instance_method(:m).bind_call(c, **{})) - assert_equal([], sc.instance_method(:m).bind_call(c, **kw)) - assert_equal([h], sc.instance_method(:m).bind_call(c, **h)) - assert_equal([h], sc.instance_method(:m).bind_call(c, a: 1)) - assert_equal([h2], sc.instance_method(:m).bind_call(c, **h2)) - assert_equal([h3], sc.instance_method(:m).bind_call(c, **h3)) - assert_equal([h3], sc.instance_method(:m).bind_call(c, a: 1, **h2)) - - sc.remove_method(:m) - def c.m; end - assert_nil(sc.instance_method(:m).bind_call(c, **{})) - assert_nil(sc.instance_method(:m).bind_call(c, **kw)) - assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, **h) } - assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, a: 1) } - assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, **h2) } - assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, **h3) } - assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, a: 1, **h2) } - - sc.remove_method(:m) - def c.m(args) - args - end - assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, **{}) } - assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, **kw) } - assert_equal(h, sc.instance_method(:m).bind_call(c, **h)) - assert_equal(h, sc.instance_method(:m).bind_call(c, a: 1)) - assert_equal(h2, sc.instance_method(:m).bind_call(c, **h2)) - assert_equal(h3, sc.instance_method(:m).bind_call(c, **h3)) - assert_equal(h3, sc.instance_method(:m).bind_call(c, a: 1, **h2)) - - sc.remove_method(:m) - def c.m(**args) - args - end - assert_equal(kw, sc.instance_method(:m).bind_call(c, **{})) - assert_equal(kw, sc.instance_method(:m).bind_call(c, **kw)) - assert_equal(h, sc.instance_method(:m).bind_call(c, **h)) - assert_equal(h, sc.instance_method(:m).bind_call(c, a: 1)) - assert_equal(h2, sc.instance_method(:m).bind_call(c, **h2)) - assert_equal(h3, sc.instance_method(:m).bind_call(c, **h3)) - assert_equal(h3, sc.instance_method(:m).bind_call(c, a: 1, **h2)) - assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, h) } - assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, h2) } - assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, h3) } - - sc.remove_method(:m) - def c.m(arg, **args) - [arg, args] - end - assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, **{}) } - assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, **kw) } - assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, **h) } - assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, a: 1) } - assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, **h2) } - assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, **h3) } - assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, a: 1, **h2) } - - sc.remove_method(:m) - def c.m(arg=1, **args) - [arg, args] - end - assert_equal([1, kw], sc.instance_method(:m).bind_call(c, **{})) - assert_equal([1, kw], sc.instance_method(:m).bind_call(c, **kw)) - assert_equal([1, h], sc.instance_method(:m).bind_call(c, **h)) - assert_equal([1, h], sc.instance_method(:m).bind_call(c, a: 1)) - assert_equal([1, h2], sc.instance_method(:m).bind_call(c, **h2)) - assert_equal([1, h3], sc.instance_method(:m).bind_call(c, **h3)) - assert_equal([1, h3], sc.instance_method(:m).bind_call(c, a: 1, **h2)) - end - - def test_send_kwsplat - kw = {} - h = {:a=>1} - h2 = {'a'=>1} - h3 = {'a'=>1, :a=>1} - - c = Object.new - def c.m(*args) - args - end - assert_equal([], c.send(:m, **{})) - assert_equal([], c.send(:m, **kw)) - assert_equal([h], c.send(:m, **h)) - assert_equal([h], c.send(:m, a: 1)) - assert_equal([h2], c.send(:m, **h2)) - assert_equal([h3], c.send(:m, **h3)) - assert_equal([h3], c.send(:m, a: 1, **h2)) - - c.singleton_class.remove_method(:m) - def c.m; end - assert_nil(c.send(:m, **{})) - assert_nil(c.send(:m, **kw)) - assert_raise(ArgumentError) { c.send(:m, **h) } - assert_raise(ArgumentError) { c.send(:m, a: 1) } - assert_raise(ArgumentError) { c.send(:m, **h2) } - assert_raise(ArgumentError) { c.send(:m, **h3) } - assert_raise(ArgumentError) { c.send(:m, a: 1, **h2) } - - c.singleton_class.remove_method(:m) - def c.m(args) - args - end - assert_raise(ArgumentError) { c.send(:m, **{}) } - assert_raise(ArgumentError) { c.send(:m, **kw) } - assert_equal(h, c.send(:m, **h)) - assert_equal(h, c.send(:m, a: 1)) - assert_equal(h2, c.send(:m, **h2)) - assert_equal(h3, c.send(:m, **h3)) - assert_equal(h3, c.send(:m, a: 1, **h2)) - - c.singleton_class.remove_method(:m) - def c.m(**args) - args - end - assert_equal(kw, c.send(:m, **{})) - assert_equal(kw, c.send(:m, **kw)) - assert_equal(h, c.send(:m, **h)) - assert_equal(h, c.send(:m, a: 1)) - assert_equal(h2, c.send(:m, **h2)) - assert_equal(h3, c.send(:m, **h3)) - assert_equal(h3, c.send(:m, a: 1, **h2)) - assert_raise(ArgumentError) { c.send(:m, h) } - assert_raise(ArgumentError) { c.send(:m, h2) } - assert_raise(ArgumentError) { c.send(:m, h3) } - - c.singleton_class.remove_method(:m) - def c.m(arg, **args) - [arg, args] - end - assert_raise(ArgumentError) { c.send(:m, **{}) } - assert_raise(ArgumentError) { c.send(:m, **kw) } - assert_raise(ArgumentError) { c.send(:m, **h) } - assert_raise(ArgumentError) { c.send(:m, a: 1) } - assert_raise(ArgumentError) { c.send(:m, **h2) } - assert_raise(ArgumentError) { c.send(:m, **h3) } - assert_raise(ArgumentError) { c.send(:m, a: 1, **h2) } - - c.singleton_class.remove_method(:m) - def c.m(arg=1, **args) - [arg, args] - end - assert_equal([1, kw], c.send(:m, **{})) - assert_equal([1, kw], c.send(:m, **kw)) - assert_equal([1, h], c.send(:m, **h)) - assert_equal([1, h], c.send(:m, a: 1)) - assert_equal([1, h2], c.send(:m, **h2)) - assert_equal([1, h3], c.send(:m, **h3)) - assert_equal([1, h3], c.send(:m, a: 1, **h2)) - end - - def test_public_send_kwsplat - kw = {} - h = {:a=>1} - h2 = {'a'=>1} - h3 = {'a'=>1, :a=>1} - - c = Object.new - def c.m(*args) - args - end - assert_equal([], c.public_send(:m, **{})) - assert_equal([], c.public_send(:m, **kw)) - assert_equal([h], c.public_send(:m, **h)) - assert_equal([h], c.public_send(:m, a: 1)) - assert_equal([h2], c.public_send(:m, **h2)) - assert_equal([h3], c.public_send(:m, **h3)) - assert_equal([h3], c.public_send(:m, a: 1, **h2)) - - c.singleton_class.remove_method(:m) - def c.m; end - assert_nil(c.public_send(:m, **{})) - assert_nil(c.public_send(:m, **kw)) - assert_raise(ArgumentError) { c.public_send(:m, **h) } - assert_raise(ArgumentError) { c.public_send(:m, a: 1) } - assert_raise(ArgumentError) { c.public_send(:m, **h2) } - assert_raise(ArgumentError) { c.public_send(:m, **h3) } - assert_raise(ArgumentError) { c.public_send(:m, a: 1, **h2) } - - c.singleton_class.remove_method(:m) - def c.m(args) - args - end - assert_raise(ArgumentError) { c.public_send(:m, **{}) } - assert_raise(ArgumentError) { c.public_send(:m, **kw) } - assert_equal(h, c.public_send(:m, **h)) - assert_equal(h, c.public_send(:m, a: 1)) - assert_equal(h2, c.public_send(:m, **h2)) - assert_equal(h3, c.public_send(:m, **h3)) - assert_equal(h3, c.public_send(:m, a: 1, **h2)) - - c.singleton_class.remove_method(:m) - def c.m(**args) - args - end - assert_equal(kw, c.public_send(:m, **{})) - assert_equal(kw, c.public_send(:m, **kw)) - assert_equal(h, c.public_send(:m, **h)) - assert_equal(h, c.public_send(:m, a: 1)) - assert_equal(h2, c.public_send(:m, **h2)) - assert_equal(h3, c.public_send(:m, **h3)) - assert_equal(h3, c.public_send(:m, a: 1, **h2)) - assert_raise(ArgumentError) { c.public_send(:m, h) } - assert_raise(ArgumentError) { c.public_send(:m, h2) } - assert_raise(ArgumentError) { c.public_send(:m, h3) } - - c.singleton_class.remove_method(:m) - def c.m(arg, **args) - [arg, args] - end - assert_raise(ArgumentError) { c.public_send(:m, **{}) } - assert_raise(ArgumentError) { c.public_send(:m, **kw) } - assert_raise(ArgumentError) { c.public_send(:m, **h) } - assert_raise(ArgumentError) { c.public_send(:m, a: 1) } - assert_raise(ArgumentError) { c.public_send(:m, **h2) } - assert_raise(ArgumentError) { c.public_send(:m, **h3) } - assert_raise(ArgumentError) { c.public_send(:m, a: 1, **h2) } - - c.singleton_class.remove_method(:m) - def c.m(arg=1, **args) - [arg, args] - end - assert_equal([1, kw], c.public_send(:m, **{})) - assert_equal([1, kw], c.public_send(:m, **kw)) - assert_equal([1, h], c.public_send(:m, **h)) - assert_equal([1, h], c.public_send(:m, a: 1)) - assert_equal([1, h2], c.public_send(:m, **h2)) - assert_equal([1, h3], c.public_send(:m, **h3)) - assert_equal([1, h3], c.public_send(:m, a: 1, **h2)) - end - - def test_send_method_kwsplat - kw = {} - h = {:a=>1} - h2 = {'a'=>1} - h3 = {'a'=>1, :a=>1} - - c = Object.new - def c.m(*args) - args - end - m = c.method(:send) - assert_equal([], m.call(:m, **{})) - assert_equal([], m.call(:m, **kw)) - assert_equal([h], m.call(:m, **h)) - assert_equal([h], m.call(:m, a: 1)) - assert_equal([h2], m.call(:m, **h2)) - assert_equal([h3], m.call(:m, **h3)) - assert_equal([h3], m.call(:m, a: 1, **h2)) - - c.singleton_class.remove_method(:m) - def c.m; end - m = c.method(:send) - assert_nil(m.call(:m, **{})) - assert_nil(m.call(:m, **kw)) - assert_raise(ArgumentError) { m.call(:m, **h) } - assert_raise(ArgumentError) { m.call(:m, a: 1) } - assert_raise(ArgumentError) { m.call(:m, **h2) } - assert_raise(ArgumentError) { m.call(:m, **h3) } - assert_raise(ArgumentError) { m.call(:m, a: 1, **h2) } - - c.singleton_class.remove_method(:m) - def c.m(args) - args - end - m = c.method(:send) - assert_raise(ArgumentError) { m.call(:m, **{}) } - assert_raise(ArgumentError) { m.call(:m, **kw) } - assert_equal(h, m.call(:m, **h)) - assert_equal(h, m.call(:m, a: 1)) - assert_equal(h2, m.call(:m, **h2)) - assert_equal(h3, m.call(:m, **h3)) - assert_equal(h3, m.call(:m, a: 1, **h2)) - - c.singleton_class.remove_method(:m) - def c.m(**args) - args - end - m = c.method(:send) - assert_equal(kw, m.call(:m, **{})) - assert_equal(kw, m.call(:m, **kw)) - assert_equal(h, m.call(:m, **h)) - assert_equal(h, m.call(:m, a: 1)) - assert_equal(h2, m.call(:m, **h2)) - assert_equal(h3, m.call(:m, **h3)) - assert_equal(h3, m.call(:m, a: 1, **h2)) - assert_raise(ArgumentError) { m.call(:m, h) } - assert_raise(ArgumentError) { m.call(:m, h2) } - assert_raise(ArgumentError) { m.call(:m, h3) } - - c.singleton_class.remove_method(:m) - def c.m(arg, **args) - [arg, args] - end - m = c.method(:send) - assert_raise(ArgumentError) { m.call(:m, **{}) } - assert_raise(ArgumentError) { m.call(:m, **kw) } - assert_raise(ArgumentError) { m.call(:m, **h) } - assert_raise(ArgumentError) { m.call(:m, a: 1) } - assert_raise(ArgumentError) { m.call(:m, **h2) } - assert_raise(ArgumentError) { m.call(:m, **h3) } - assert_raise(ArgumentError) { m.call(:m, a: 1, **h2) } - - c.singleton_class.remove_method(:m) - def c.m(arg=1, **args) - [arg, args] - end - m = c.method(:send) - assert_equal([1, kw], m.call(:m, **{})) - assert_equal([1, kw], m.call(:m, **kw)) - assert_equal([1, h], m.call(:m, **h)) - assert_equal([1, h], m.call(:m, a: 1)) - assert_equal([1, h2], m.call(:m, **h2)) - assert_equal([1, h3], m.call(:m, **h3)) - assert_equal([1, h3], m.call(:m, a: 1, **h2)) - end - - def test_sym_proc_kwsplat - kw = {} - h = {:a=>1} - h2 = {'a'=>1} - h3 = {'a'=>1, :a=>1} - - c = Object.new - def c.m(*args) - args - end - assert_equal([], :m.to_proc.call(c, **{})) - assert_equal([], :m.to_proc.call(c, **kw)) - assert_equal([h], :m.to_proc.call(c, **h)) - assert_equal([h], :m.to_proc.call(c, a: 1)) - assert_equal([h2], :m.to_proc.call(c, **h2)) - assert_equal([h3], :m.to_proc.call(c, **h3)) - assert_equal([h3], :m.to_proc.call(c, a: 1, **h2)) - - c.singleton_class.remove_method(:m) - def c.m; end - assert_nil(:m.to_proc.call(c, **{})) - assert_nil(:m.to_proc.call(c, **kw)) - assert_raise(ArgumentError) { :m.to_proc.call(c, **h) } - assert_raise(ArgumentError) { :m.to_proc.call(c, a: 1) } - assert_raise(ArgumentError) { :m.to_proc.call(c, **h2) } - assert_raise(ArgumentError) { :m.to_proc.call(c, **h3) } - assert_raise(ArgumentError) { :m.to_proc.call(c, a: 1, **h2) } - - c.singleton_class.remove_method(:m) - def c.m(args) - args - end - assert_raise(ArgumentError) { :m.to_proc.call(c, **{}) } - assert_raise(ArgumentError) { :m.to_proc.call(c, **kw) } - assert_equal(h, :m.to_proc.call(c, **h)) - assert_equal(h, :m.to_proc.call(c, a: 1)) - assert_equal(h2, :m.to_proc.call(c, **h2)) - assert_equal(h3, :m.to_proc.call(c, **h3)) - assert_equal(h3, :m.to_proc.call(c, a: 1, **h2)) - - c.singleton_class.remove_method(:m) - def c.m(**args) - args - end - assert_equal(kw, :m.to_proc.call(c, **{})) - assert_equal(kw, :m.to_proc.call(c, **kw)) - assert_equal(h, :m.to_proc.call(c, **h)) - assert_equal(h, :m.to_proc.call(c, a: 1)) - assert_equal(h2, :m.to_proc.call(c, **h2)) - assert_equal(h3, :m.to_proc.call(c, **h3)) - assert_equal(h3, :m.to_proc.call(c, a: 1, **h2)) - assert_raise(ArgumentError) { :m.to_proc.call(c, h) } - assert_raise(ArgumentError) { :m.to_proc.call(c, h2) } - assert_raise(ArgumentError) { :m.to_proc.call(c, h3) } - - c.singleton_class.remove_method(:m) - def c.m(arg, **args) - [arg, args] - end - assert_raise(ArgumentError) { :m.to_proc.call(c, **{}) } - assert_raise(ArgumentError) { :m.to_proc.call(c, **kw) } - assert_raise(ArgumentError) { :m.to_proc.call(c, **h) } - assert_raise(ArgumentError) { :m.to_proc.call(c, a: 1) } - assert_raise(ArgumentError) { :m.to_proc.call(c, **h2) } - assert_raise(ArgumentError) { :m.to_proc.call(c, **h3) } - assert_raise(ArgumentError) { :m.to_proc.call(c, a: 1, **h2) } - - c.singleton_class.remove_method(:m) - def c.m(arg=1, **args) - [arg, args] - end - assert_equal([1, kw], :m.to_proc.call(c, **{})) - assert_equal([1, kw], :m.to_proc.call(c, **kw)) - assert_equal([1, h], :m.to_proc.call(c, **h)) - assert_equal([1, h], :m.to_proc.call(c, a: 1)) - assert_equal([1, h2], :m.to_proc.call(c, **h2)) - assert_equal([1, h3], :m.to_proc.call(c, **h3)) - assert_equal([1, h3], :m.to_proc.call(c, a: 1, **h2)) - end - - def test_sym_proc_method_kwsplat - kw = {} - h = {:a=>1} - h2 = {'a'=>1} - h3 = {'a'=>1, :a=>1} - - c = Object.new - def c.m(*args) - args - end - m = :m.to_proc.method(:call) - assert_equal([], m.call(c, **{})) - assert_equal([], m.call(c, **kw)) - assert_equal([h], m.call(c, **h)) - assert_equal([h], m.call(c, a: 1)) - assert_equal([h2], m.call(c, **h2)) - assert_equal([h3], m.call(c, **h3)) - assert_equal([h3], m.call(c, a: 1, **h2)) - - c.singleton_class.remove_method(:m) - def c.m; end - assert_nil(m.call(c, **{})) - assert_nil(m.call(c, **kw)) - assert_raise(ArgumentError) { m.call(c, **h) } - assert_raise(ArgumentError) { m.call(c, a: 1) } - assert_raise(ArgumentError) { m.call(c, **h2) } - assert_raise(ArgumentError) { m.call(c, **h3) } - assert_raise(ArgumentError) { m.call(c, a: 1, **h2) } - - c.singleton_class.remove_method(:m) - def c.m(args) - args - end - assert_raise(ArgumentError) { m.call(c, **{}) } - assert_raise(ArgumentError) { m.call(c, **kw) } - assert_equal(h, m.call(c, **h)) - assert_equal(h, m.call(c, a: 1)) - assert_equal(h2, m.call(c, **h2)) - assert_equal(h3, m.call(c, **h3)) - assert_equal(h3, m.call(c, a: 1, **h2)) - - c.singleton_class.remove_method(:m) - def c.m(**args) - args - end - assert_equal(kw, m.call(c, **{})) - assert_equal(kw, m.call(c, **kw)) - assert_equal(h, m.call(c, **h)) - assert_equal(h, m.call(c, a: 1)) - assert_equal(h2, m.call(c, **h2)) - assert_equal(h3, m.call(c, **h3)) - assert_equal(h3, m.call(c, a: 1, **h2)) - assert_raise(ArgumentError) { m.call(c, h) } - assert_raise(ArgumentError) { m.call(c, h2) } - assert_raise(ArgumentError) { m.call(c, h3) } - - c.singleton_class.remove_method(:m) - def c.m(arg, **args) - [arg, args] - end - assert_raise(ArgumentError) { m.call(c, **{}) } - assert_raise(ArgumentError) { m.call(c, **kw) } - assert_raise(ArgumentError) { m.call(c, **h) } - assert_raise(ArgumentError) { m.call(c, a: 1) } - assert_raise(ArgumentError) { m.call(c, **h2) } - assert_raise(ArgumentError) { m.call(c, **h3) } - assert_raise(ArgumentError) { m.call(c, a: 1, **h2) } - - c.singleton_class.remove_method(:m) - def c.m(arg=1, **args) - [arg, args] - end - assert_equal([1, kw], m.call(c, **{})) - assert_equal([1, kw], m.call(c, **kw)) - assert_equal([1, h], m.call(c, **h)) - assert_equal([1, h], m.call(c, a: 1)) - assert_equal([1, h2], m.call(c, **h2)) - assert_equal([1, h3], m.call(c, **h3)) - assert_equal([1, h3], m.call(c, a: 1, **h2)) - end - - def test_method_missing_kwsplat - kw = {} - h = {:a=>1} - h2 = {'a'=>1} - h3 = {'a'=>1, :a=>1} - - c = Object.new - def c.method_missing(_, *args) - args - end - assert_equal([], c.m(**{})) - assert_equal([], c.m(**kw)) - assert_equal([h], c.m(**h)) - assert_equal([h], c.m(a: 1)) - assert_equal([h2], c.m(**h2)) - assert_equal([h3], c.m(**h3)) - assert_equal([h3], c.m(a: 1, **h2)) - - c.singleton_class.remove_method(:method_missing) - def c.method_missing(_); end - assert_nil(c.m(**{})) - assert_nil(c.m(**kw)) - assert_raise(ArgumentError) { c.m(**h) } - assert_raise(ArgumentError) { c.m(a: 1) } - assert_raise(ArgumentError) { c.m(**h2) } - assert_raise(ArgumentError) { c.m(**h3) } - assert_raise(ArgumentError) { c.m(a: 1, **h2) } - - c.singleton_class.remove_method(:method_missing) - def c.method_missing(_, args) - args - end - assert_raise(ArgumentError) { c.m(**{}) } - assert_raise(ArgumentError) { c.m(**kw) } - assert_equal(h, c.m(**h)) - assert_equal(h, c.m(a: 1)) - assert_equal(h2, c.m(**h2)) - assert_equal(h3, c.m(**h3)) - assert_equal(h3, c.m(a: 1, **h2)) - - c.singleton_class.remove_method(:method_missing) - def c.method_missing(_, **args) - args - end - assert_equal(kw, c.m(**{})) - assert_equal(kw, c.m(**kw)) - assert_equal(h, c.m(**h)) - assert_equal(h, c.m(a: 1)) - assert_equal(h2, c.m(**h2)) - assert_equal(h3, c.m(**h3)) - assert_equal(h3, c.m(a: 1, **h2)) - assert_raise(ArgumentError) { c.m(h) } - assert_raise(ArgumentError) { c.m(h2) } - assert_raise(ArgumentError) { c.m(h3) } - - c.singleton_class.remove_method(:method_missing) - def c.method_missing(_, arg, **args) - [arg, args] - end - assert_raise(ArgumentError) { c.m(**{}) } - assert_raise(ArgumentError) { c.m(**kw) } - assert_raise(ArgumentError) { c.m(**h) } - assert_raise(ArgumentError) { c.m(a: 1) } - assert_raise(ArgumentError) { c.m(**h2) } - assert_raise(ArgumentError) { c.m(**h3) } - assert_raise(ArgumentError) { c.m(a: 1, **h2) } - - c.singleton_class.remove_method(:method_missing) - def c.method_missing(_, arg=1, **args) - [arg, args] - end - assert_equal([1, kw], c.m(**{})) - assert_equal([1, kw], c.m(**kw)) - assert_equal([1, h], c.m(**h)) - assert_equal([1, h], c.m(a: 1)) - assert_equal([1, h2], c.m(**h2)) - assert_equal([1, h3], c.m(**h3)) - assert_equal([1, h3], c.m(a: 1, **h2)) - end - - def test_super_method_missing_kwsplat - kw = {} - h = {:a=>1} - h2 = {'a'=>1} - h3 = {'a'=>1, :a=>1} - - c = Class.new do - def m(*args, **kw) - super - end - end.new - def c.method_missing(_, *args) - args - end - assert_equal([], c.m(**{})) - assert_equal([], c.m(**kw)) - assert_equal([h], c.m(**h)) - assert_equal([h], c.m(a: 1)) - assert_equal([h2], c.m(**h2)) - assert_equal([h3], c.m(**h3)) - assert_equal([h3], c.m(a: 1, **h2)) - - c.singleton_class.remove_method(:method_missing) - def c.method_missing(_); end - assert_nil(c.m(**{})) - assert_nil(c.m(**kw)) - assert_raise(ArgumentError) { c.m(**h) } - assert_raise(ArgumentError) { c.m(a: 1) } - assert_raise(ArgumentError) { c.m(**h2) } - assert_raise(ArgumentError) { c.m(**h3) } - assert_raise(ArgumentError) { c.m(a: 1, **h2) } - - c.singleton_class.remove_method(:method_missing) - def c.method_missing(_, args) - args - end - assert_raise(ArgumentError) { c.m(**{}) } - assert_raise(ArgumentError) { c.m(**kw) } - assert_equal(h, c.m(**h)) - assert_equal(h, c.m(a: 1)) - assert_equal(h2, c.m(**h2)) - assert_equal(h3, c.m(**h3)) - assert_equal(h3, c.m(a: 1, **h2)) - - c.singleton_class.remove_method(:method_missing) - def c.method_missing(_, **args) - args - end - assert_equal(kw, c.m(**{})) - assert_equal(kw, c.m(**kw)) - assert_equal(h, c.m(**h)) - assert_equal(h, c.m(a: 1)) - assert_equal(h2, c.m(**h2)) - assert_equal(h3, c.m(**h3)) - assert_equal(h3, c.m(a: 1, **h2)) - assert_raise(ArgumentError) { c.m(h) } - assert_raise(ArgumentError) { c.m(h2) } - assert_raise(ArgumentError) { c.m(h3) } - - c.singleton_class.remove_method(:method_missing) - def c.method_missing(_, arg, **args) - [arg, args] - end - assert_raise(ArgumentError) { c.m(**{}) } - assert_raise(ArgumentError) { c.m(**kw) } - assert_raise(ArgumentError) { c.m(**h) } - assert_raise(ArgumentError) { c.m(a: 1) } - assert_raise(ArgumentError) { c.m(**h2) } - assert_raise(ArgumentError) { c.m(**h3) } - assert_raise(ArgumentError) { c.m(a: 1, **h2) } - - c.singleton_class.remove_method(:method_missing) - def c.method_missing(_, arg=1, **args) - [arg, args] - end - assert_equal([1, kw], c.m(**{})) - assert_equal([1, kw], c.m(**kw)) - assert_equal([1, h], c.m(**h)) - assert_equal([1, h], c.m(a: 1)) - assert_equal([1, h2], c.m(**h2)) - assert_equal([1, h3], c.m(**h3)) - assert_equal([1, h3], c.m(a: 1, **h2)) - end - - def test_rb_call_super_kw_method_missing_kwsplat - kw = {} - h = {:a=>1} - h2 = {'a'=>1} - h3 = {'a'=>1, :a=>1} - - c = Object.new - c.extend Bug::RbCallSuperKw - def c.method_missing(_, *args) - args - end - assert_equal([], c.m(**{})) - assert_equal([], c.m(**kw)) - assert_equal([h], c.m(**h)) - assert_equal([h], c.m(a: 1)) - assert_equal([h2], c.m(**h2)) - assert_equal([h3], c.m(**h3)) - assert_equal([h3], c.m(a: 1, **h2)) - - c.singleton_class.remove_method(:method_missing) - def c.method_missing(_); end - assert_nil(c.m(**{})) - assert_nil(c.m(**kw)) - assert_raise(ArgumentError) { c.m(**h) } - assert_raise(ArgumentError) { c.m(a: 1) } - assert_raise(ArgumentError) { c.m(**h2) } - assert_raise(ArgumentError) { c.m(**h3) } - assert_raise(ArgumentError) { c.m(a: 1, **h2) } - - c.singleton_class.remove_method(:method_missing) - def c.method_missing(_, args) - args - end - assert_raise(ArgumentError) { c.m(**{}) } - assert_raise(ArgumentError) { c.m(**kw) } - assert_equal(h, c.m(**h)) - assert_equal(h, c.m(a: 1)) - assert_equal(h2, c.m(**h2)) - assert_equal(h3, c.m(**h3)) - assert_equal(h3, c.m(a: 1, **h2)) - - c.singleton_class.remove_method(:method_missing) - def c.method_missing(_, **args) - args - end - assert_equal(kw, c.m(**{})) - assert_equal(kw, c.m(**kw)) - assert_equal(h, c.m(**h)) - assert_equal(h, c.m(a: 1)) - assert_equal(h2, c.m(**h2)) - assert_equal(h3, c.m(**h3)) - assert_equal(h3, c.m(a: 1, **h2)) - assert_raise(ArgumentError) { c.m(h) } - assert_raise(ArgumentError) { c.m(h2) } - assert_raise(ArgumentError) { c.m(h3) } - - c.singleton_class.remove_method(:method_missing) - def c.method_missing(_, arg, **args) - [arg, args] - end - assert_raise(ArgumentError) { c.m(**{}) } - assert_raise(ArgumentError) { c.m(**kw) } - assert_raise(ArgumentError) { c.m(**h) } - assert_raise(ArgumentError) { c.m(a: 1) } - assert_raise(ArgumentError) { c.m(**h2) } - assert_raise(ArgumentError) { c.m(**h3) } - assert_raise(ArgumentError) { c.m(a: 1, **h2) } - - c.singleton_class.remove_method(:method_missing) - def c.method_missing(_, arg=1, **args) - [arg, args] - end - assert_equal([1, kw], c.m(**{})) - assert_equal([1, kw], c.m(**kw)) - assert_equal([1, h], c.m(**h)) - assert_equal([1, h], c.m(a: 1)) - assert_equal([1, h2], c.m(**h2)) - assert_equal([1, h3], c.m(**h3)) - assert_equal([1, h3], c.m(a: 1, **h2)) - end - - def test_define_method_kwsplat - kw = {} - h = {:a=>1} - h2 = {'a'=>1} - h3 = {'a'=>1, :a=>1} - - c = Object.new - class << c - define_method(:m) { } - end - assert_nil(c.m(**{})) - assert_nil(c.m(**kw)) - assert_raise(ArgumentError) { c.m(**h) } - assert_raise(ArgumentError) { c.m(a: 1) } - assert_raise(ArgumentError) { c.m(**h2) } - assert_raise(ArgumentError) { c.m(**h3) } - assert_raise(ArgumentError) { c.m(a: 1, **h2) } - - c = Object.new - class << c - define_method(:m) {|arg| arg } - end - assert_raise(ArgumentError) { c.m(**{}) } - assert_raise(ArgumentError) { c.m(**kw) } - assert_equal(h, c.m(**h)) - assert_equal(h, c.m(a: 1)) - assert_equal(h2, c.m(**h2)) - assert_equal(h3, c.m(**h3)) - assert_equal(h3, c.m(a: 1, **h2)) - - c = Object.new - class << c - define_method(:m) {|*args| args } - end - assert_equal([], c.m(**{})) - assert_equal([], c.m(**kw)) - assert_equal([h], c.m(**h)) - assert_equal([h], c.m(a: 1)) - assert_equal([h2], c.m(**h2)) - assert_equal([h3], c.m(**h3)) - assert_equal([h3], c.m(a: 1, **h2)) - - c = Object.new - class << c - define_method(:m) {|**opt| opt} - end - assert_equal(kw, c.m(**{})) - assert_equal(kw, c.m(**kw)) - assert_equal(h, c.m(**h)) - assert_equal(h, c.m(a: 1)) - assert_equal(h2, c.m(**h2)) - assert_equal(h3, c.m(**h3)) - assert_equal(h3, c.m(a: 1, **h2)) - assert_raise(ArgumentError) { c.m(h) } - assert_raise(ArgumentError) { c.m(h2) } - assert_raise(ArgumentError) { c.m(h3) } - - c = Object.new - class << c - define_method(:m) {|arg, **opt| [arg, opt] } - end - assert_raise(ArgumentError) { c.m(**{}) } - assert_raise(ArgumentError) { c.m(**kw) } - assert_raise(ArgumentError) { c.m(**h) } - assert_raise(ArgumentError) { c.m(a: 1) } - assert_raise(ArgumentError) { c.m(**h2) } - assert_raise(ArgumentError) { c.m(**h3) } - assert_raise(ArgumentError) { c.m(a: 1, **h2) } - - c = Object.new - class << c - define_method(:m) {|arg=1, **opt| [arg, opt] } - end - assert_equal([1, kw], c.m(**{})) - assert_equal([1, kw], c.m(**kw)) - assert_equal([1, h], c.m(**h)) - assert_equal([1, h], c.m(a: 1)) - assert_equal([1, h2], c.m(**h2)) - assert_equal([1, h3], c.m(**h3)) - assert_equal([1, h3], c.m(a: 1, **h2)) - - c = Object.new - class << c - define_method(:m) {|*args, **opt| [args, opt] } - end - assert_equal([[h], kw], c.m(h)) - assert_equal([[h, h], kw], c.m(h, h)) - - c = Object.new - class << c - define_method(:m) {|arg=nil, a: nil| [arg, a] } - end - assert_equal([h3, nil], c.m(h3)) - assert_raise(ArgumentError) { c.m(**h3) } - end - - def test_define_method_method_kwsplat - kw = {} - h = {:a=>1} - h2 = {'a'=>1} - h3 = {'a'=>1, :a=>1} - - c = Object.new - class << c - define_method(:m) { } - end - m = c.method(:m) - assert_nil(m.call(**{})) - assert_nil(m.call(**kw)) - assert_raise(ArgumentError) { m.call(**h) } - assert_raise(ArgumentError) { m.call(a: 1) } - assert_raise(ArgumentError) { m.call(**h2) } - assert_raise(ArgumentError) { m.call(**h3) } - assert_raise(ArgumentError) { m.call(a: 1, **h2) } - - c = Object.new - class << c - define_method(:m) {|arg| arg } - end - m = c.method(:m) - assert_raise(ArgumentError) { m.call(**{}) } - assert_raise(ArgumentError) { m.call(**kw) } - assert_equal(h, m.call(**h)) - assert_equal(h, m.call(a: 1)) - assert_equal(h2, m.call(**h2)) - assert_equal(h3, m.call(**h3)) - assert_equal(h3, m.call(a: 1, **h2)) - - c = Object.new - class << c - define_method(:m) {|*args| args } - end - m = c.method(:m) - assert_equal([], m.call(**{})) - assert_equal([], m.call(**kw)) - assert_equal([h], m.call(**h)) - assert_equal([h], m.call(a: 1)) - assert_equal([h2], m.call(**h2)) - assert_equal([h3], m.call(**h3)) - assert_equal([h3], m.call(a: 1, **h2)) - - c = Object.new - class << c - define_method(:m) {|**opt| opt} - end - m = c.method(:m) - assert_equal(kw, m.call(**{})) - assert_equal(kw, m.call(**kw)) - assert_equal(h, m.call(**h)) - assert_equal(h, m.call(a: 1)) - assert_equal(h2, m.call(**h2)) - assert_equal(h3, m.call(**h3)) - assert_equal(h3, m.call(a: 1, **h2)) - assert_raise(ArgumentError) { m.call(h) } - assert_raise(ArgumentError) { m.call(h2) } - assert_raise(ArgumentError) { m.call(h3) } - - c = Object.new - class << c - define_method(:m) {|arg, **opt| [arg, opt] } - end - m = c.method(:m) - assert_raise(ArgumentError) { m.call(**{}) } - assert_raise(ArgumentError) { m.call(**kw) } - assert_raise(ArgumentError) { m.call(**h) } - assert_raise(ArgumentError) { m.call(a: 1) } - assert_raise(ArgumentError) { m.call(**h2) } - assert_raise(ArgumentError) { m.call(**h3) } - assert_raise(ArgumentError) { m.call(a: 1, **h2) } - - c = Object.new - class << c - define_method(:m) {|arg=1, **opt| [arg, opt] } - end - m = c.method(:m) - assert_equal([1, kw], m.call(**{})) - assert_equal([1, kw], m.call(**kw)) - assert_equal([1, h], m.call(**h)) - assert_equal([1, h], m.call(a: 1)) - assert_equal([1, h2], m.call(**h2)) - assert_equal([1, h3], m.call(**h3)) - assert_equal([1, h3], m.call(a: 1, **h2)) - - c = Object.new - class << c - define_method(:m) {|*args, **opt| [args, opt] } - end - m = c.method(:m) - assert_equal([[h], kw], m.call(h)) - assert_equal([[h, h], kw], m.call(h, h)) - - c = Object.new - class << c - define_method(:m) {|arg=nil, a: nil| [arg, a] } - end - m = c.method(:m) - assert_equal([h3, nil], m.call(h3)) - assert_raise(ArgumentError) { m.call(**h3) } - end - - def test_attr_reader_kwsplat - kw = {} - h = {:a=>1} - h2 = {'a'=>1} - h3 = {'a'=>1, :a=>1} - - c = Object.new - class << c - attr_reader :m - end - assert_nil(c.m(**{})) - assert_nil(c.m(**kw)) - assert_raise(ArgumentError) { c.m(**h) } - assert_raise(ArgumentError) { c.m(a: 1) } - assert_raise(ArgumentError) { c.m(**h2) } - assert_raise(ArgumentError) { c.m(**h3) } - assert_raise(ArgumentError) { c.m(a: 1, **h2) } - end - - def test_attr_reader_method_kwsplat - kw = {} - h = {:a=>1} - h2 = {'a'=>1} - h3 = {'a'=>1, :a=>1} - - c = Object.new - class << c - attr_reader :m - end - m = c.method(:m) - assert_nil(m.call(**{})) - assert_nil(m.call(**kw)) - assert_raise(ArgumentError) { m.call(**h) } - assert_raise(ArgumentError) { m.call(a: 1) } - assert_raise(ArgumentError) { m.call(**h2) } - assert_raise(ArgumentError) { m.call(**h3) } - assert_raise(ArgumentError) { m.call(a: 1, **h2) } - end - - def test_attr_writer_kwsplat - kw = {} - h = {:a=>1} - h2 = {'a'=>1} - h3 = {'a'=>1, :a=>1} - - c = Object.new - class << c - attr_writer :m - end - assert_raise(ArgumentError) { c.send(:m=, **{}) } - assert_raise(ArgumentError) { c.send(:m=, **kw) } - assert_equal(h, c.send(:m=, **h)) - assert_equal(h, c.send(:m=, a: 1)) - assert_equal(h2, c.send(:m=, **h2)) - assert_equal(h3, c.send(:m=, **h3)) - assert_equal(h3, c.send(:m=, a: 1, **h2)) - - assert_equal(42, c.send(:m=, 42, **{})) - assert_equal(42, c.send(:m=, 42, **kw)) - assert_raise(ArgumentError) { c.send(:m=, 42, **h) } - assert_raise(ArgumentError) { c.send(:m=, 42, a: 1) } - assert_raise(ArgumentError) { c.send(:m=, 42, **h2) } - assert_raise(ArgumentError) { c.send(:m=, 42, **h3) } - assert_raise(ArgumentError) { c.send(:m=, 42, a: 1, **h2) } - end - - def test_attr_writer_method_kwsplat - kw = {} - h = {:a=>1} - h2 = {'a'=>1} - h3 = {'a'=>1, :a=>1} - - c = Object.new - class << c - attr_writer :m - end - m = c.method(:m=) - assert_raise(ArgumentError) { m.call(**{}) } - assert_raise(ArgumentError) { m.call(**kw) } - assert_equal(h, m.call(**h)) - assert_equal(h, m.call(a: 1)) - assert_equal(h2, m.call(**h2)) - assert_equal(h3, m.call(**h3)) - assert_equal(h3, m.call(a: 1, **h2)) - - assert_equal(42, m.call(42, **{})) - assert_equal(42, m.call(42, **kw)) - assert_raise(ArgumentError) { m.call(42, **h) } - assert_raise(ArgumentError) { m.call(42, a: 1) } - assert_raise(ArgumentError) { m.call(42, **h2) } - assert_raise(ArgumentError) { m.call(42, **h3) } - assert_raise(ArgumentError) { m.call(42, a: 1, **h2) } - end - - def test_proc_ruby2_keywords - h1 = {:a=>1} - foo = ->(*args, &block){block.call(*args)} - assert_same(foo, foo.ruby2_keywords) - - assert_equal([[1], h1], foo.call(1, :a=>1, &->(*args, **kw){[args, kw]})) - assert_equal([1, h1], foo.call(1, :a=>1, &->(*args){args})) - assert_equal([[1, h1], {}], foo.call(1, {:a=>1}, &->(*args, **kw){[args, kw]})) - assert_equal([1, h1], foo.call(1, {:a=>1}, &->(*args){args})) - assert_raise(ArgumentError) { foo.call(:a=>1, &->(arg, **kw){[arg, kw]}) } - assert_equal(h1, foo.call(:a=>1, &->(arg){arg})) - - [->(){}, ->(arg){}, ->(*args, **kw){}, ->(*args, k: 1){}, ->(*args, k: ){}].each do |pr| - assert_warn(/Skipping set of ruby2_keywords flag for proc \(proc accepts keywords or proc does not accept argument splat\)/) do - pr.ruby2_keywords - end - end - - o = Object.new - def o.foo(*args) - yield(*args) - end - foo = o.method(:foo).to_proc - assert_warn(/Skipping set of ruby2_keywords flag for proc \(proc created from method\)/) do - foo.ruby2_keywords - end - - foo = :foo.to_proc - assert_warn(/Skipping set of ruby2_keywords flag for proc \(proc not defined in Ruby\)/) do - foo.ruby2_keywords - end - - assert_raise(FrozenError) { ->(*args){}.freeze.ruby2_keywords } - end - - def test_ruby2_keywords - assert_raise(ArgumentError) do - Class.new do - ruby2_keywords - end - end - - c = Class.new do - ruby2_keywords def foo(meth, *args) - send(meth, *args) - end - - ruby2_keywords(define_method(:bfoo) do |meth, *args| - send(meth, *args) - end) - - ruby2_keywords def foo_bar(*args) - bar(*args) - end - - ruby2_keywords def foo_baz(*args) - baz(*args) - end - - ruby2_keywords def foo_baz2(*args) - baz(*args) - baz(*args) - end - - ruby2_keywords def foo_foo_bar(meth, *args) - foo_bar(meth, *args) - end - - ruby2_keywords def foo_foo_baz(meth, *args) - foo_baz(meth, *args) - end - - ruby2_keywords def foo_mod(meth, *args) - args << 1 - send(meth, *args) - end - - ruby2_keywords def foo_bar_mod(*args) - args << 1 - bar(*args) - end - - ruby2_keywords def foo_baz_mod(*args) - args << 1 - baz(*args) - end - - def pass_bar(*args) - bar(*args) - end - - def bar(*args, **kw) - [args, kw] - end - - def baz(*args) - args - end - - ruby2_keywords def foo_dbar(*args) - dbar(*args) - end - - ruby2_keywords def foo_dbaz(*args) - dbaz(*args) - end - - define_method(:dbar) do |*args, **kw| - [args, kw] - end - - define_method(:dbaz) do |*args| - args - end - - def pass_cfunc(*args) - self.class.new(*args).init_args - end - - ruby2_keywords def block(*args) - ->(*args, **kw){[args, kw]}.(*args) - end - - ruby2_keywords def cfunc(*args) - self.class.new(*args).init_args - end - - ruby2_keywords def store_foo(meth, *args) - @stored_args = args - use(meth) - end - def use(meth) - send(meth, *@stored_args) - end - - attr_reader :init_args - def initialize(*args, **kw) - @init_args = [args, kw] - end - end - - mmkw = Class.new do - def method_missing(*args, **kw) - [args, kw] - end - end - - mmnokw = Class.new do - def method_missing(*args) - args - end - end - - implicit_super = Class.new(c) do - ruby2_keywords def bar(*args) - super - end - - ruby2_keywords def baz(*args) - super - end - end - - explicit_super = Class.new(c) do - ruby2_keywords def bar(*args) - super(*args) - end - - ruby2_keywords def baz(*args) - super(*args) - end - end - - h1 = {a: 1} - o = c.new - - assert_equal([1, h1], o.foo_baz2(1, :a=>1)) - assert_equal([1], o.foo_baz2(1, **{})) - assert_equal([h1], o.foo_baz2(h1, **{})) - - assert_equal([[1], h1], o.foo(:bar, 1, :a=>1)) - assert_equal([1, h1], o.foo(:baz, 1, :a=>1)) - assert_equal([[1], h1], o.bfoo(:bar, 1, :a=>1)) - assert_equal([1, h1], o.bfoo(:baz, 1, :a=>1)) - assert_equal([[1], h1], o.store_foo(:bar, 1, :a=>1)) - assert_equal([1, h1], o.store_foo(:baz, 1, :a=>1)) - assert_equal([[1], h1], o.foo_bar(1, :a=>1)) - assert_equal([1, h1], o.foo_baz(1, :a=>1)) - assert_equal([[1], h1], o.foo(:foo, :bar, 1, :a=>1)) - assert_equal([1, h1], o.foo(:foo, :baz, 1, :a=>1)) - assert_equal([[1], h1], o.foo(:foo_bar, 1, :a=>1)) - assert_equal([1, h1], o.foo(:foo_baz, 1, :a=>1)) - assert_equal([[1], h1], o.foo_foo_bar(1, :a=>1)) - assert_equal([1, h1], o.foo_foo_baz(1, :a=>1)) - - assert_equal([[1], h1], o.foo(:bar, 1, **h1)) - assert_equal([1, h1], o.foo(:baz, 1, **h1)) - assert_equal([[1], h1], o.bfoo(:bar, 1, **h1)) - assert_equal([1, h1], o.bfoo(:baz, 1, **h1)) - assert_equal([[1], h1], o.store_foo(:bar, 1, **h1)) - assert_equal([1, h1], o.store_foo(:baz, 1, **h1)) - assert_equal([[1], h1], o.foo_bar(1, **h1)) - assert_equal([1, h1], o.foo_baz(1, **h1)) - assert_equal([[1], h1], o.foo(:foo, :bar, 1, **h1)) - assert_equal([1, h1], o.foo(:foo, :baz, 1, **h1)) - assert_equal([[1], h1], o.foo(:foo_bar, 1, **h1)) - assert_equal([1, h1], o.foo(:foo_baz, 1, **h1)) - assert_equal([[1], h1], o.foo_foo_bar(1, **h1)) - assert_equal([1, h1], o.foo_foo_baz(1, **h1)) - - assert_equal([[h1], {}], o.foo(:bar, h1, **{})) - assert_equal([h1], o.foo(:baz, h1, **{})) - assert_equal([[h1], {}], o.bfoo(:bar, h1, **{})) - assert_equal([h1], o.bfoo(:baz, h1, **{})) - assert_equal([[h1], {}], o.store_foo(:bar, h1, **{})) - assert_equal([h1], o.store_foo(:baz, h1, **{})) - assert_equal([[h1], {}], o.foo_bar(h1, **{})) - assert_equal([h1], o.foo_baz(h1, **{})) - assert_equal([[h1], {}], o.foo(:foo, :bar, h1, **{})) - assert_equal([h1], o.foo(:foo, :baz, h1, **{})) - assert_equal([[h1], {}], o.foo(:foo_bar, h1, **{})) - assert_equal([h1], o.foo(:foo_baz, h1, **{})) - assert_equal([[h1], {}], o.foo_foo_bar(h1, **{})) - assert_equal([h1], o.foo_foo_baz(h1, **{})) - - assert_equal([[1, h1], {}], o.foo(:bar, 1, h1)) - assert_equal([1, h1], o.foo(:baz, 1, h1)) - assert_equal([[1, h1], {}], o.bfoo(:bar, 1, h1)) - assert_equal([1, h1], o.bfoo(:baz, 1, h1)) - assert_equal([[1, h1], {}], o.store_foo(:bar, 1, h1)) - assert_equal([1, h1], o.store_foo(:baz, 1, h1)) - assert_equal([[1, h1], {}], o.foo_bar(1, h1)) - assert_equal([1, h1], o.foo_baz(1, h1)) - - assert_equal([[1, h1, 1], {}], o.foo_mod(:bar, 1, :a=>1)) - assert_equal([1, h1, 1], o.foo_mod(:baz, 1, :a=>1)) - assert_equal([[1, h1, 1], {}], o.foo_bar_mod(1, :a=>1)) - assert_equal([1, h1, 1], o.foo_baz_mod(1, :a=>1)) - - assert_equal([[1, h1, 1], {}], o.foo_mod(:bar, 1, **h1)) - assert_equal([1, h1, 1], o.foo_mod(:baz, 1, **h1)) - assert_equal([[1, h1, 1], {}], o.foo_bar_mod(1, **h1)) - assert_equal([1, h1, 1], o.foo_baz_mod(1, **h1)) - - assert_equal([[h1, 1], {}], o.foo_mod(:bar, h1, **{})) - assert_equal([h1, 1], o.foo_mod(:baz, h1, **{})) - assert_equal([[h1, 1], {}], o.foo_bar_mod(h1, **{})) - assert_equal([h1, 1], o.foo_baz_mod(h1, **{})) - - assert_equal([[1, h1, 1], {}], o.foo_mod(:bar, 1, h1)) - assert_equal([1, h1, 1], o.foo_mod(:baz, 1, h1)) - assert_equal([[1, h1, 1], {}], o.foo_bar_mod(1, h1)) - assert_equal([1, h1, 1], o.foo_baz_mod(1, h1)) - - assert_equal([[1], h1], o.foo(:dbar, 1, :a=>1)) - assert_equal([1, h1], o.foo(:dbaz, 1, :a=>1)) - assert_equal([[1], h1], o.bfoo(:dbar, 1, :a=>1)) - assert_equal([1, h1], o.bfoo(:dbaz, 1, :a=>1)) - assert_equal([[1], h1], o.store_foo(:dbar, 1, :a=>1)) - assert_equal([1, h1], o.store_foo(:dbaz, 1, :a=>1)) - assert_equal([[1], h1], o.foo_dbar(1, :a=>1)) - assert_equal([1, h1], o.foo_dbaz(1, :a=>1)) - - assert_equal([[1], h1], o.foo(:dbar, 1, **h1)) - assert_equal([1, h1], o.foo(:dbaz, 1, **h1)) - assert_equal([[1], h1], o.bfoo(:dbar, 1, **h1)) - assert_equal([1, h1], o.bfoo(:dbaz, 1, **h1)) - assert_equal([[1], h1], o.store_foo(:dbar, 1, **h1)) - assert_equal([1, h1], o.store_foo(:dbaz, 1, **h1)) - assert_equal([[1], h1], o.foo_dbar(1, **h1)) - assert_equal([1, h1], o.foo_dbaz(1, **h1)) - - assert_equal([[h1], {}], o.foo(:dbar, h1, **{})) - assert_equal([h1], o.foo(:dbaz, h1, **{})) - assert_equal([[h1], {}], o.bfoo(:dbar, h1, **{})) - assert_equal([h1], o.bfoo(:dbaz, h1, **{})) - assert_equal([[h1], {}], o.store_foo(:dbar, h1, **{})) - assert_equal([h1], o.store_foo(:dbaz, h1, **{})) - assert_equal([[h1], {}], o.foo_dbar(h1, **{})) - assert_equal([h1], o.foo_dbaz(h1, **{})) - - assert_equal([[1, h1], {}], o.foo(:dbar, 1, h1)) - assert_equal([1, h1], o.foo(:dbaz, 1, h1)) - assert_equal([[1, h1], {}], o.bfoo(:dbar, 1, h1)) - assert_equal([1, h1], o.bfoo(:dbaz, 1, h1)) - assert_equal([[1, h1], {}], o.store_foo(:dbar, 1, h1)) - assert_equal([1, h1], o.store_foo(:dbaz, 1, h1)) - assert_equal([[1, h1], {}], o.foo_dbar(1, h1)) - assert_equal([1, h1], o.foo_dbaz(1, h1)) - - assert_equal([[1], h1], o.block(1, :a=>1)) - assert_equal([[1], h1], o.block(1, **h1)) - assert_equal([[1, h1], {}], o.block(1, h1)) - assert_equal([[h1], {}], o.block(h1, **{})) - - assert_equal([[1], h1], o.cfunc(1, :a=>1)) - assert_equal([[1], h1], o.cfunc(1, **h1)) - assert_equal([[1, h1], {}], o.cfunc(1, h1)) - assert_equal([[h1], {}], o.cfunc(h1, **{})) - - o = mmkw.new - assert_equal([[:b, 1], h1], o.b(1, :a=>1)) - assert_equal([[:b, 1], h1], o.b(1, **h1)) - assert_equal([[:b, 1, h1], {}], o.b(1, h1)) - assert_equal([[:b, h1], {}], o.b(h1, **{})) - - o = mmnokw.new - assert_equal([:b, 1, h1], o.b(1, :a=>1)) - assert_equal([:b, 1, h1], o.b(1, **h1)) - assert_equal([:b, 1, h1], o.b(1, h1)) - assert_equal([:b, h1], o.b(h1, **{})) - - o = implicit_super.new - assert_equal([[1], h1], o.bar(1, :a=>1)) - assert_equal([[1], h1], o.bar(1, **h1)) - assert_equal([[1, h1], {}], o.bar(1, h1)) - assert_equal([[h1], {}], o.bar(h1, **{})) - - assert_equal([1, h1], o.baz(1, :a=>1)) - assert_equal([1, h1], o.baz(1, **h1)) - assert_equal([1, h1], o.baz(1, h1)) - assert_equal([h1], o.baz(h1, **{})) - - o = explicit_super.new - assert_equal([[1], h1], o.bar(1, :a=>1)) - assert_equal([[1], h1], o.bar(1, **h1)) - assert_equal([[1, h1], {}], o.bar(1, h1)) - assert_equal([[h1], {}], o.bar(h1, **{})) - - assert_equal([1, h1], o.baz(1, :a=>1)) - assert_equal([1, h1], o.baz(1, **h1)) - assert_equal([1, h1], o.baz(1, h1)) - assert_equal([h1], o.baz(h1, **{})) - - assert_equal([[1, h1], {}], o.foo(:pass_bar, 1, :a=>1)) - assert_equal([[1, h1], {}], o.foo(:pass_cfunc, 1, :a=>1)) - - assert_warn(/Skipping set of ruby2_keywords flag for bar \(method accepts keywords or method does not accept argument splat\)/) do - assert_nil(c.send(:ruby2_keywords, :bar)) - end - - o = Object.new - class << o - alias bar p - end - assert_warn(/Skipping set of ruby2_keywords flag for bar \(method not defined in Ruby\)/) do - assert_nil(o.singleton_class.send(:ruby2_keywords, :bar)) - end - sc = Class.new(c) - assert_warn(/Skipping set of ruby2_keywords flag for bar \(can only set in method defining module\)/) do - sc.send(:ruby2_keywords, :bar) - end - m = Module.new - assert_warn(/Skipping set of ruby2_keywords flag for system \(can only set in method defining module\)/) do - m.send(:ruby2_keywords, :system) - end - - assert_raise(NameError) { c.send(:ruby2_keywords, "a5e36ccec4f5080a1d5e63f8") } - assert_raise(NameError) { c.send(:ruby2_keywords, :quux) } - - c.freeze - assert_raise(FrozenError) { c.send(:ruby2_keywords, :baz) } - end - - def test_top_ruby2_keywords - assert_in_out_err([], <<-INPUT, ["[1, 2, 3]", "{:k=>1}"], []) - def bar(*a, **kw) - p a, kw - end - ruby2_keywords def foo(*a) - bar(*a) - end - foo(1, 2, 3, k:1) - INPUT - end - - def test_dig_kwsplat - kw = {} - h = {:a=>1} - h2 = {'a'=>1} - h3 = {'a'=>1, :a=>1} - - c = Object.new - def c.dig(*args) - args - end - assert_equal(c, [c].dig(0, **{})) - assert_equal(c, [c].dig(0, **kw)) - assert_equal([h], [c].dig(0, **h)) - assert_equal([h], [c].dig(0, a: 1)) - assert_equal([h2], [c].dig(0, **h2)) - assert_equal([h3], [c].dig(0, **h3)) - assert_equal([h3], [c].dig(0, a: 1, **h2)) - - c.singleton_class.remove_method(:dig) - def c.dig; end - assert_equal(c, [c].dig(0, **{})) - assert_equal(c, [c].dig(0, **kw)) - assert_raise(ArgumentError) { [c].dig(0, **h) } - assert_raise(ArgumentError) { [c].dig(0, a: 1) } - assert_raise(ArgumentError) { [c].dig(0, **h2) } - assert_raise(ArgumentError) { [c].dig(0, **h3) } - assert_raise(ArgumentError) { [c].dig(0, a: 1, **h2) } - - c.singleton_class.remove_method(:dig) - def c.dig(args) - args - end - assert_equal(c, [c].dig(0, **{})) - assert_equal(c, [c].dig(0, **kw)) - assert_equal(kw, [c].dig(0, kw, **kw)) - assert_equal(h, [c].dig(0, **h)) - assert_equal(h, [c].dig(0, a: 1)) - assert_equal(h2, [c].dig(0, **h2)) - assert_equal(h3, [c].dig(0, **h3)) - assert_equal(h3, [c].dig(0, a: 1, **h2)) - - c.singleton_class.remove_method(:dig) - def c.dig(**args) - args - end - assert_equal(c, [c].dig(0, **{})) - assert_equal(c, [c].dig(0, **kw)) - assert_raise(ArgumentError) { [c].dig(0, **h) } - assert_raise(ArgumentError) { [c].dig(0, a: 1) } - assert_raise(ArgumentError) { [c].dig(0, **h2) } - assert_raise(ArgumentError) { [c].dig(0, **h3) } - assert_raise(ArgumentError) { [c].dig(0, a: 1, **h2) } - assert_raise(ArgumentError) { [c].dig(0, h) } - assert_raise(ArgumentError) { [c].dig(0, h2) } - assert_raise(ArgumentError) { [c].dig(0, h3) } - - c.singleton_class.remove_method(:dig) - def c.dig(arg, **args) - [arg, args] - end - assert_equal(c, [c].dig(0, **{})) - assert_equal(c, [c].dig(0, **kw)) - assert_equal([h, kw], [c].dig(0, **h)) - assert_equal([h, kw], [c].dig(0, a: 1)) - assert_equal([h2, kw], [c].dig(0, **h2)) - assert_equal([h3, kw], [c].dig(0, **h3)) - assert_equal([h3, kw], [c].dig(0, a: 1, **h2)) - - c.singleton_class.remove_method(:dig) - def c.dig(arg=1, **args) - [arg, args] - end - assert_equal(c, [c].dig(0, **{})) - assert_equal(c, [c].dig(0, **kw)) - assert_equal([h, kw], [c].dig(0, **h)) - assert_equal([h, kw], [c].dig(0, a: 1)) - assert_equal([h2, kw], [c].dig(0, **h2)) - assert_equal([h3, kw], [c].dig(0, **h3)) - assert_equal([h3, kw], [c].dig(0, a: 1, **h2)) - assert_equal([h, {}], [c].dig(0, h)) - assert_equal([h2, kw], [c].dig(0, h2)) - assert_equal([h3, kw], [c].dig(0, h3)) - assert_equal([h, kw], [c].dig(0, h, **{})) - assert_equal([h2, kw], [c].dig(0, h2, **{})) - assert_equal([h3, kw], [c].dig(0, h3, **{})) - end - - def test_dig_method_missing_kwsplat - kw = {} - h = {:a=>1} - h2 = {'a'=>1} - h3 = {'a'=>1, :a=>1} - - c = Object.new - def c.method_missing(_, *args) - args - end - assert_equal(c, [c].dig(0, **{})) - assert_equal(c, [c].dig(0, **kw)) - assert_equal([h], [c].dig(0, **h)) - assert_equal([h], [c].dig(0, a: 1)) - assert_equal([h2], [c].dig(0, **h2)) - assert_equal([h3], [c].dig(0, **h3)) - assert_equal([h3], [c].dig(0, a: 1, **h2)) - - c.singleton_class.remove_method(:method_missing) - def c.method_missing; end - assert_equal(c, [c].dig(0, **{})) - assert_equal(c, [c].dig(0, **kw)) - assert_raise(ArgumentError) { [c].dig(0, **h) } - assert_raise(ArgumentError) { [c].dig(0, a: 1) } - assert_raise(ArgumentError) { [c].dig(0, **h2) } - assert_raise(ArgumentError) { [c].dig(0, **h3) } - assert_raise(ArgumentError) { [c].dig(0, a: 1, **h2) } - - c.singleton_class.remove_method(:method_missing) - def c.method_missing(_, args) - args - end - assert_equal(c, [c].dig(0, **{})) - assert_equal(c, [c].dig(0, **kw)) - assert_equal(kw, [c].dig(0, kw, **kw)) - assert_equal(h, [c].dig(0, **h)) - assert_equal(h, [c].dig(0, a: 1)) - assert_equal(h2, [c].dig(0, **h2)) - assert_equal(h3, [c].dig(0, **h3)) - assert_equal(h3, [c].dig(0, a: 1, **h2)) - - c.singleton_class.remove_method(:method_missing) - def c.method_missing(_, **args) - args - end - assert_equal(c, [c].dig(0, **{})) - assert_equal(c, [c].dig(0, **kw)) - assert_raise(ArgumentError) { [c].dig(0, **h) } - assert_raise(ArgumentError) { [c].dig(0, a: 1) } - assert_raise(ArgumentError) { [c].dig(0, **h2) } - assert_raise(ArgumentError) { [c].dig(0, **h3) } - assert_raise(ArgumentError) { [c].dig(0, a: 1, **h2) } - assert_raise(ArgumentError) { [c].dig(0, h) } - assert_raise(ArgumentError) { [c].dig(0, h2) } - assert_raise(ArgumentError) { [c].dig(0, h3) } - - c.singleton_class.remove_method(:method_missing) - def c.method_missing(_, arg, **args) - [arg, args] - end - assert_equal(c, [c].dig(0, **{})) - assert_equal(c, [c].dig(0, **kw)) - assert_equal([h, kw], [c].dig(0, **h)) - assert_equal([h, kw], [c].dig(0, a: 1)) - assert_equal([h2, kw], [c].dig(0, **h2)) - assert_equal([h3, kw], [c].dig(0, **h3)) - assert_equal([h3, kw], [c].dig(0, a: 1, **h2)) - - c.singleton_class.remove_method(:method_missing) - def c.method_missing(_, arg=1, **args) - [arg, args] - end - assert_equal(c, [c].dig(0, **{})) - assert_equal(c, [c].dig(0, **kw)) - assert_equal([h, kw], [c].dig(0, **h)) - assert_equal([h, kw], [c].dig(0, a: 1)) - assert_equal([h2, kw], [c].dig(0, **h2)) - assert_equal([h3, kw], [c].dig(0, **h3)) - assert_equal([h3, kw], [c].dig(0, a: 1, **h2)) - assert_equal([h, kw], [c].dig(0, h)) - assert_equal([h2, kw], [c].dig(0, h2)) - assert_equal([h3, kw], [c].dig(0, h3)) - assert_equal([h, kw], [c].dig(0, h, **{})) - assert_equal([h2, kw], [c].dig(0, h2, **{})) - assert_equal([h3, kw], [c].dig(0, h3, **{})) - end - - def test_enumerator_size_kwsplat - kw = {} - h = {:a=>1} - h2 = {'a'=>1} - h3 = {'a'=>1, :a=>1} - - c = Object.new - c.to_enum(:each){|*args| args}.size - m = ->(*args){ args } - assert_equal([], c.to_enum(:each, **{}, &m).size) - assert_equal([], c.to_enum(:each, **kw, &m).size) - assert_equal([h], c.to_enum(:each, **h, &m).size) - assert_equal([h], c.to_enum(:each, a: 1, &m).size) - assert_equal([h2], c.to_enum(:each, **h2, &m).size) - assert_equal([h3], c.to_enum(:each, **h3, &m).size) - assert_equal([h3], c.to_enum(:each, a: 1, **h2, &m).size) - - m = ->(){ } - assert_nil(c.to_enum(:each, **{}, &m).size) - assert_nil(c.to_enum(:each, **kw, &m).size) - assert_raise(ArgumentError) { c.to_enum(:each, **h, &m).size } - assert_raise(ArgumentError) { c.to_enum(:each, a: 1, &m).size } - assert_raise(ArgumentError) { c.to_enum(:each, **h2, &m).size } - assert_raise(ArgumentError) { c.to_enum(:each, **h3, &m).size } - assert_raise(ArgumentError) { c.to_enum(:each, a: 1, **h2, &m).size } - - m = ->(args){ args } - assert_raise(ArgumentError) { c.to_enum(:each, **{}, &m).size } - assert_raise(ArgumentError) { c.to_enum(:each, **kw, &m).size } - assert_equal(kw, c.to_enum(:each, kw, **kw, &m).size) - assert_equal(h, c.to_enum(:each, **h, &m).size) - assert_equal(h, c.to_enum(:each, a: 1, &m).size) - assert_equal(h2, c.to_enum(:each, **h2, &m).size) - assert_equal(h3, c.to_enum(:each, **h3, &m).size) - assert_equal(h3, c.to_enum(:each, a: 1, **h2, &m).size) - - m = ->(**args){ args } - assert_equal(kw, c.to_enum(:each, **{}, &m).size) - assert_equal(kw, c.to_enum(:each, **kw, &m).size) - assert_equal(h, c.to_enum(:each, **h, &m).size) - assert_equal(h, c.to_enum(:each, a: 1, &m).size) - assert_equal(h2, c.to_enum(:each, **h2, &m).size) - assert_equal(h3, c.to_enum(:each, **h3, &m).size) - assert_equal(h3, c.to_enum(:each, a: 1, **h2, &m).size) - assert_raise(ArgumentError) { c.to_enum(:each, h, &m).size } - assert_raise(ArgumentError) { c.to_enum(:each, h2, &m).size } - assert_raise(ArgumentError) { c.to_enum(:each, h3, &m).size } - - m = ->(arg, **args){ [arg, args] } - assert_raise(ArgumentError) { c.to_enum(:each, **{}, &m).size } - assert_raise(ArgumentError) { c.to_enum(:each, **kw, &m).size } - assert_raise(ArgumentError) { c.to_enum(:each, **h, &m).size } - assert_raise(ArgumentError) { c.to_enum(:each, a: 1, &m).size } - assert_raise(ArgumentError) { c.to_enum(:each, **h2, &m).size } - assert_raise(ArgumentError) { c.to_enum(:each, **h3, &m).size } - assert_raise(ArgumentError) { c.to_enum(:each, a: 1, **h2, &m).size } - assert_equal([h, kw], c.to_enum(:each, h, &m).size) - assert_equal([h2, kw], c.to_enum(:each, h2, &m).size) - assert_equal([h3, kw], c.to_enum(:each, h3, &m).size) - - m = ->(arg=1, **args){ [arg, args] } - assert_equal([1, kw], c.to_enum(:each, **{}, &m).size) - assert_equal([1, kw], c.to_enum(:each, **kw, &m).size) - assert_equal([1, h], c.to_enum(:each, **h, &m).size) - assert_equal([1, h], c.to_enum(:each, a: 1, &m).size) - assert_equal([1, h2], c.to_enum(:each, **h2, &m).size) - assert_equal([1, h3], c.to_enum(:each, **h3, &m).size) - assert_equal([1, h3], c.to_enum(:each, a: 1, **h2, &m).size) - assert_equal([h, kw], c.to_enum(:each, h, &m).size) - assert_equal([h2, kw], c.to_enum(:each, h2, &m).size) - assert_equal([h3, kw], c.to_enum(:each, h3, &m).size) - end - - def test_instance_exec_kwsplat - kw = {} - h = {:a=>1} - h2 = {'a'=>1} - h3 = {'a'=>1, :a=>1} - - c = Object.new - m = ->(*args) { args } - assert_equal([], c.instance_exec(**{}, &m)) - assert_equal([], c.instance_exec(**kw, &m)) - assert_equal([h], c.instance_exec(**h, &m)) - assert_equal([h], c.instance_exec(a: 1, &m)) - assert_equal([h2], c.instance_exec(**h2, &m)) - assert_equal([h3], c.instance_exec(**h3, &m)) - assert_equal([h3], c.instance_exec(a: 1, **h2, &m)) - - m = ->() { nil } - assert_nil(c.instance_exec(**{}, &m)) - assert_nil(c.instance_exec(**kw, &m)) - assert_raise(ArgumentError) { c.instance_exec(**h, &m) } - assert_raise(ArgumentError) { c.instance_exec(a: 1, &m) } - assert_raise(ArgumentError) { c.instance_exec(**h2, &m) } - assert_raise(ArgumentError) { c.instance_exec(**h3, &m) } - assert_raise(ArgumentError) { c.instance_exec(a: 1, **h2, &m) } - - m = ->(args) { args } - assert_raise(ArgumentError) { c.instance_exec(**{}, &m) } - assert_raise(ArgumentError) { c.instance_exec(**kw, &m) } - assert_equal(kw, c.instance_exec(kw, **kw, &m)) - assert_equal(h, c.instance_exec(**h, &m)) - assert_equal(h, c.instance_exec(a: 1, &m)) - assert_equal(h2, c.instance_exec(**h2, &m)) - assert_equal(h3, c.instance_exec(**h3, &m)) - assert_equal(h3, c.instance_exec(a: 1, **h2, &m)) - - m = ->(**args) { args } - assert_equal(kw, c.instance_exec(**{}, &m)) - assert_equal(kw, c.instance_exec(**kw, &m)) - assert_equal(h, c.instance_exec(**h, &m)) - assert_equal(h, c.instance_exec(a: 1, &m)) - assert_equal(h2, c.instance_exec(**h2, &m)) - assert_equal(h3, c.instance_exec(**h3, &m)) - assert_equal(h3, c.instance_exec(a: 1, **h2, &m)) - assert_raise(ArgumentError) { c.instance_exec(h, &m) } - assert_raise(ArgumentError) { c.instance_exec(h2, &m) } - assert_raise(ArgumentError) { c.instance_exec(h3, &m) } - - m = ->(arg, **args) { [arg, args] } - assert_raise(ArgumentError) { c.instance_exec(**{}, &m) } - assert_raise(ArgumentError) { c.instance_exec(**kw, &m) } - assert_raise(ArgumentError) { c.instance_exec(**h, &m) } - assert_raise(ArgumentError) { c.instance_exec(a: 1, &m) } - assert_raise(ArgumentError) { c.instance_exec(**h2, &m) } - assert_raise(ArgumentError) { c.instance_exec(**h3, &m) } - assert_raise(ArgumentError) { c.instance_exec(a: 1, **h2, &m) } - assert_equal([h, kw], c.instance_exec(h, &m)) - assert_equal([h2, kw], c.instance_exec(h2, &m)) - assert_equal([h3, kw], c.instance_exec(h3, &m)) - - m = ->(arg=1, **args) { [arg, args] } - assert_equal([1, kw], c.instance_exec(**{}, &m)) - assert_equal([1, kw], c.instance_exec(**kw, &m)) - assert_equal([1, h], c.instance_exec(**h, &m)) - assert_equal([1, h], c.instance_exec(a: 1, &m)) - assert_equal([1, h2], c.instance_exec(**h2, &m)) - assert_equal([1, h3], c.instance_exec(**h3, &m)) - assert_equal([1, h3], c.instance_exec(a: 1, **h2, &m)) - assert_equal([h, kw], c.instance_exec(h, &m)) - assert_equal([h2, kw], c.instance_exec(h2, &m)) - assert_equal([h3, kw], c.instance_exec(h3, &m)) - end - - def test_instance_exec_method_kwsplat - kw = {} - h = {:a=>1} - h2 = {'a'=>1} - h3 = {'a'=>1, :a=>1} - - c = Object.new - def c.m(*args) - args - end - m = c.method(:m) - assert_equal([], c.instance_exec(**{}, &m)) - assert_equal([], c.instance_exec(**kw, &m)) - assert_equal([h], c.instance_exec(**h, &m)) - assert_equal([h], c.instance_exec(a: 1, &m)) - assert_equal([h2], c.instance_exec(**h2, &m)) - assert_equal([h3], c.instance_exec(**h3, &m)) - assert_equal([h3], c.instance_exec(a: 1, **h2, &m)) - - c.singleton_class.remove_method(:m) - def c.m - end - m = c.method(:m) - assert_nil(c.instance_exec(**{}, &m)) - assert_nil(c.instance_exec(**kw, &m)) - assert_raise(ArgumentError) { c.instance_exec(**h, &m) } - assert_raise(ArgumentError) { c.instance_exec(a: 1, &m) } - assert_raise(ArgumentError) { c.instance_exec(**h2, &m) } - assert_raise(ArgumentError) { c.instance_exec(**h3, &m) } - assert_raise(ArgumentError) { c.instance_exec(a: 1, **h2, &m) } - - c.singleton_class.remove_method(:m) - def c.m(args) - args - end - m = c.method(:m) - assert_raise(ArgumentError) { c.instance_exec(**{}, &m) } - assert_raise(ArgumentError) { c.instance_exec(**kw, &m) } - assert_equal(kw, c.instance_exec(kw, **kw, &m)) - assert_equal(h, c.instance_exec(**h, &m)) - assert_equal(h, c.instance_exec(a: 1, &m)) - assert_equal(h2, c.instance_exec(**h2, &m)) - assert_equal(h3, c.instance_exec(**h3, &m)) - assert_equal(h3, c.instance_exec(a: 1, **h2, &m)) - - c.singleton_class.remove_method(:m) - def c.m(**args) - args - end - m = c.method(:m) - assert_equal(kw, c.instance_exec(**{}, &m)) - assert_equal(kw, c.instance_exec(**kw, &m)) - assert_equal(h, c.instance_exec(**h, &m)) - assert_equal(h, c.instance_exec(a: 1, &m)) - assert_equal(h2, c.instance_exec(**h2, &m)) - assert_equal(h3, c.instance_exec(**h3, &m)) - assert_equal(h3, c.instance_exec(a: 1, **h2, &m)) - assert_raise(ArgumentError) { c.instance_exec(h, &m) } - assert_raise(ArgumentError) { c.instance_exec(h2, &m) } - assert_raise(ArgumentError) { c.instance_exec(h3, &m) } - - c.singleton_class.remove_method(:m) - def c.m(arg, **args) - [arg, args] - end - m = c.method(:m) - assert_raise(ArgumentError) { c.instance_exec(**{}, &m) } - assert_raise(ArgumentError) { c.instance_exec(**kw, &m) } - assert_raise(ArgumentError) { c.instance_exec(**h, &m) } - assert_raise(ArgumentError) { c.instance_exec(a: 1, &m) } - assert_raise(ArgumentError) { c.instance_exec(**h2, &m) } - assert_raise(ArgumentError) { c.instance_exec(**h3, &m) } - assert_raise(ArgumentError) { c.instance_exec(a: 1, **h2, &m) } - assert_equal([h, kw], c.instance_exec(h, &m)) - assert_equal([h2, kw], c.instance_exec(h2, &m)) - assert_equal([h3, kw], c.instance_exec(h3, &m)) - - c.singleton_class.remove_method(:m) - def c.m(arg=1, **args) - [arg, args] - end - m = c.method(:m) - assert_equal([1, kw], c.instance_exec(**{}, &m)) - assert_equal([1, kw], c.instance_exec(**kw, &m)) - assert_equal([1, h], c.instance_exec(**h, &m)) - assert_equal([1, h], c.instance_exec(a: 1, &m)) - assert_equal([1, h2], c.instance_exec(**h2, &m)) - assert_equal([1, h3], c.instance_exec(**h3, &m)) - assert_equal([1, h3], c.instance_exec(a: 1, **h2, &m)) - assert_equal([h, kw], c.instance_exec(h, &m)) - assert_equal([h2, kw], c.instance_exec(h2, &m)) - assert_equal([h3, kw], c.instance_exec(h3, &m)) - end - - def test_instance_exec_define_method_kwsplat - kw = {} - h = {:a=>1} - h2 = {'a'=>1} - h3 = {'a'=>1, :a=>1} - - c = Object.new - c.define_singleton_method(:m) do |*args| - args - end - m = c.method(:m) - assert_equal([], c.instance_exec(**{}, &m)) - assert_equal([], c.instance_exec(**kw, &m)) - assert_equal([h], c.instance_exec(**h, &m)) - assert_equal([h], c.instance_exec(a: 1, &m)) - assert_equal([h2], c.instance_exec(**h2, &m)) - assert_equal([h3], c.instance_exec(**h3, &m)) - assert_equal([h3], c.instance_exec(a: 1, **h2, &m)) - - c.singleton_class.remove_method(:m) - c.define_singleton_method(:m) do - end - m = c.method(:m) - assert_nil(c.instance_exec(**{}, &m)) - assert_nil(c.instance_exec(**kw, &m)) - assert_raise(ArgumentError) { c.instance_exec(**h, &m) } - assert_raise(ArgumentError) { c.instance_exec(a: 1, &m) } - assert_raise(ArgumentError) { c.instance_exec(**h2, &m) } - assert_raise(ArgumentError) { c.instance_exec(**h3, &m) } - assert_raise(ArgumentError) { c.instance_exec(a: 1, **h2, &m) } - - c.singleton_class.remove_method(:m) - c.define_singleton_method(:m) do |args| - args - end - m = c.method(:m) - assert_raise(ArgumentError) { c.instance_exec(**{}, &m) } - assert_raise(ArgumentError) { c.instance_exec(**kw, &m) } - assert_equal(kw, c.instance_exec(kw, **kw, &m)) - assert_equal(h, c.instance_exec(**h, &m)) - assert_equal(h, c.instance_exec(a: 1, &m)) - assert_equal(h2, c.instance_exec(**h2, &m)) - assert_equal(h3, c.instance_exec(**h3, &m)) - assert_equal(h3, c.instance_exec(a: 1, **h2, &m)) - - c.singleton_class.remove_method(:m) - c.define_singleton_method(:m) do |**args| - args - end - m = c.method(:m) - assert_equal(kw, c.instance_exec(**{}, &m)) - assert_equal(kw, c.instance_exec(**kw, &m)) - assert_equal(h, c.instance_exec(**h, &m)) - assert_equal(h, c.instance_exec(a: 1, &m)) - assert_equal(h2, c.instance_exec(**h2, &m)) - assert_equal(h3, c.instance_exec(**h3, &m)) - assert_equal(h3, c.instance_exec(a: 1, **h2, &m)) - assert_raise(ArgumentError) { c.instance_exec(h, &m) } - assert_raise(ArgumentError) { c.instance_exec(h2, &m) } - assert_raise(ArgumentError) { c.instance_exec(h3, &m) } - - c.singleton_class.remove_method(:m) - c.define_singleton_method(:m) do |arg, **args| - [arg, args] - end - m = c.method(:m) - assert_raise(ArgumentError) { c.instance_exec(**{}, &m) } - assert_raise(ArgumentError) { c.instance_exec(**kw, &m) } - assert_raise(ArgumentError) { c.instance_exec(**h, &m) } - assert_raise(ArgumentError) { c.instance_exec(a: 1, &m) } - assert_raise(ArgumentError) { c.instance_exec(**h2, &m) } - assert_raise(ArgumentError) { c.instance_exec(**h3, &m) } - assert_raise(ArgumentError) { c.instance_exec(a: 1, **h2, &m) } - assert_equal([h, kw], c.instance_exec(h, &m)) - assert_equal([h2, kw], c.instance_exec(h2, &m)) - assert_equal([h3, kw], c.instance_exec(h3, &m)) - - c.singleton_class.remove_method(:m) - c.define_singleton_method(:m) do |arg=1, **args| - [arg, args] - end - m = c.method(:m) - assert_equal([1, kw], c.instance_exec(**{}, &m)) - assert_equal([1, kw], c.instance_exec(**kw, &m)) - assert_equal([1, h], c.instance_exec(**h, &m)) - assert_equal([1, h], c.instance_exec(a: 1, &m)) - assert_equal([1, h2], c.instance_exec(**h2, &m)) - assert_equal([1, h3], c.instance_exec(**h3, &m)) - assert_equal([1, h3], c.instance_exec(a: 1, **h2, &m)) - assert_equal([h, kw], c.instance_exec(h, &m)) - assert_equal([h2, kw], c.instance_exec(h2, &m)) - assert_equal([h3, kw], c.instance_exec(h3, &m)) - end - - def test_instance_exec_sym_proc_kwsplat - kw = {} - h = {:a=>1} - h2 = {'a'=>1} - h3 = {'a'=>1, :a=>1} - - c = Object.new - def c.m(*args) - args - end - assert_equal([], c.instance_exec(c, **{}, &:m)) - assert_equal([], c.instance_exec(c, **kw, &:m)) - assert_equal([h], c.instance_exec(c, **h, &:m)) - assert_equal([h], c.instance_exec(c, a: 1, &:m)) - assert_equal([h2], c.instance_exec(c, **h2, &:m)) - assert_equal([h3], c.instance_exec(c, **h3, &:m)) - assert_equal([h3], c.instance_exec(c, a: 1, **h2, &:m)) - - c.singleton_class.remove_method(:m) - def c.m - end - assert_nil(c.instance_exec(c, **{}, &:m)) - assert_nil(c.instance_exec(c, **kw, &:m)) - assert_raise(ArgumentError) { c.instance_exec(c, **h, &:m) } - assert_raise(ArgumentError) { c.instance_exec(c, a: 1, &:m) } - assert_raise(ArgumentError) { c.instance_exec(c, **h2, &:m) } - assert_raise(ArgumentError) { c.instance_exec(c, **h3, &:m) } - assert_raise(ArgumentError) { c.instance_exec(c, a: 1, **h2, &:m) } - - c.singleton_class.remove_method(:m) - def c.m(args) - args - end - assert_raise(ArgumentError) { c.instance_exec(c, **{}, &:m) } - assert_raise(ArgumentError) { c.instance_exec(c, **kw, &:m) } - assert_equal(kw, c.instance_exec(c, kw, **kw, &:m)) - assert_equal(h, c.instance_exec(c, **h, &:m)) - assert_equal(h, c.instance_exec(c, a: 1, &:m)) - assert_equal(h2, c.instance_exec(c, **h2, &:m)) - assert_equal(h3, c.instance_exec(c, **h3, &:m)) - assert_equal(h3, c.instance_exec(c, a: 1, **h2, &:m)) - - c.singleton_class.remove_method(:m) - def c.m(**args) - args - end - assert_equal(kw, c.instance_exec(c, **{}, &:m)) - assert_equal(kw, c.instance_exec(c, **kw, &:m)) - assert_equal(h, c.instance_exec(c, **h, &:m)) - assert_equal(h, c.instance_exec(c, a: 1, &:m)) - assert_equal(h2, c.instance_exec(c, **h2, &:m)) - assert_equal(h3, c.instance_exec(c, **h3, &:m)) - assert_equal(h3, c.instance_exec(c, a: 1, **h2, &:m)) - assert_raise(ArgumentError) { c.instance_exec(c, h, &:m) } - assert_raise(ArgumentError) { c.instance_exec(c, h2, &:m) } - assert_raise(ArgumentError) { c.instance_exec(c, h3, &:m) } - - c.singleton_class.remove_method(:m) - def c.m(arg, **args) - [arg, args] - end - assert_raise(ArgumentError) { c.instance_exec(c, **{}, &:m) } - assert_raise(ArgumentError) { c.instance_exec(c, **kw, &:m) } - assert_raise(ArgumentError) { c.instance_exec(c, **h, &:m) } - assert_raise(ArgumentError) { c.instance_exec(c, a: 1, &:m) } - assert_raise(ArgumentError) { c.instance_exec(c, **h2, &:m) } - assert_raise(ArgumentError) { c.instance_exec(c, **h3, &:m) } - assert_raise(ArgumentError) { c.instance_exec(c, a: 1, **h2, &:m) } - assert_equal([h, kw], c.instance_exec(c, h, &:m)) - assert_equal([h2, kw], c.instance_exec(c, h2, &:m)) - assert_equal([h3, kw], c.instance_exec(c, h3, &:m)) - - c.singleton_class.remove_method(:m) - def c.m(arg=1, **args) - [arg, args] - end - assert_equal([1, kw], c.instance_exec(c, **{}, &:m)) - assert_equal([1, kw], c.instance_exec(c, **kw, &:m)) - assert_equal([1, h], c.instance_exec(c, **h, &:m)) - assert_equal([1, h], c.instance_exec(c, a: 1, &:m)) - assert_equal([1, h2], c.instance_exec(c, **h2, &:m)) - assert_equal([1, h3], c.instance_exec(c, **h3, &:m)) - assert_equal([1, h3], c.instance_exec(c, a: 1, **h2, &:m)) - assert_equal([h, kw], c.instance_exec(c, h, &:m)) - assert_equal([h2, kw], c.instance_exec(c, h2, &:m)) - assert_equal([h3, kw], c.instance_exec(c, h3, &:m)) - end - - def test_rb_yield_block_kwsplat - kw = {} - h = {:a=>1} - h2 = {'a'=>1} - h3 = {'a'=>1, :a=>1} - - c = Object.new - c.extend Bug::Iter::Yield - class << c - alias m yield_block - end - def c.c(*args) - args - end - assert_equal([], c.m(:c, **{})) - assert_equal([], c.m(:c, **kw)) - assert_equal([h], c.m(:c, **h)) - assert_equal([h], c.m(:c, a: 1)) - assert_equal([h2], c.m(:c, **h2)) - assert_equal([h3], c.m(:c, **h3)) - assert_equal([h3], c.m(:c, a: 1, **h2)) - - c.singleton_class.remove_method(:c) - def c.c; end - assert_nil(c.m(:c, **{})) - assert_nil(c.m(:c, **kw)) - assert_raise(ArgumentError) { c.m(:c, **h) } - assert_raise(ArgumentError) { c.m(:c, a: 1) } - assert_raise(ArgumentError) { c.m(:c, **h2) } - assert_raise(ArgumentError) { c.m(:c, **h3) } - assert_raise(ArgumentError) { c.m(:c, a: 1, **h2) } - - c.singleton_class.remove_method(:c) - def c.c(args) - args - end - assert_raise(ArgumentError) { c.m(:c, **{}) } - assert_raise(ArgumentError) { c.m(:c, **kw) } - assert_equal(kw, c.m(:c, kw, **kw)) - assert_equal(h, c.m(:c, **h)) - assert_equal(h, c.m(:c, a: 1)) - assert_equal(h2, c.m(:c, **h2)) - assert_equal(h3, c.m(:c, **h3)) - assert_equal(h3, c.m(:c, a: 1, **h2)) - - c.singleton_class.remove_method(:c) - def c.c(**args) - [args, yield(**args)] - end - m = ->(**args){ args } - assert_equal([kw, kw], c.m(:c, **{}, &m)) - assert_equal([kw, kw], c.m(:c, **kw, &m)) - assert_equal([h, h], c.m(:c, **h, &m)) - assert_equal([h, h], c.m(:c, a: 1, &m)) - assert_equal([h2, h2], c.m(:c, **h2, &m)) - assert_equal([h3, h3], c.m(:c, **h3, &m)) - assert_equal([h3, h3], c.m(:c, a: 1, **h2, &m)) - assert_raise(ArgumentError) { c.m(:c, h, &m) } - assert_raise(ArgumentError) { c.m(:c, h2, &m) } - assert_raise(ArgumentError) { c.m(:c, h3, &m) } - - c.singleton_class.remove_method(:c) - def c.c(arg, **args) - [arg, args] - end - assert_raise(ArgumentError) { c.m(:c, **{}, &m) } - assert_raise(ArgumentError) { c.m(:c, **kw, &m) } - assert_raise(ArgumentError) { c.m(:c, **h, &m) } - assert_raise(ArgumentError) { c.m(:c, a: 1, &m) } - assert_raise(ArgumentError) { c.m(:c, **h2, &m) } - assert_raise(ArgumentError) { c.m(:c, **h3, &m) } - assert_raise(ArgumentError) { c.m(:c, a: 1, **h2, &m) } - assert_equal([h, kw], c.m(:c, h)) - assert_equal([h2, kw], c.m(:c, h2)) - assert_equal([h3, kw], c.m(:c, h3)) - - c.singleton_class.remove_method(:c) - def c.c(arg=1, **args) - [arg, args] - end - assert_equal([1, kw], c.m(:c, **{})) - assert_equal([1, kw], c.m(:c, **kw)) - assert_equal([1, h], c.m(:c, **h)) - assert_equal([1, h], c.m(:c, a: 1)) - assert_equal([1, h2], c.m(:c, **h2)) - assert_equal([1, h3], c.m(:c, **h3)) - assert_equal([1, h3], c.m(:c, a: 1, **h2)) - assert_equal([h, kw], c.m(:c, h)) - assert_equal([h2, kw], c.m(:c, h2)) - assert_equal([h3, kw], c.m(:c, h3)) - end def p1 Proc.new do |str: "foo", num: 424242| @@ -3476,8 +254,8 @@ class TestKeywordArguments < Test::Unit::TestCase [:keyrest, :kw], [:block, :b]], p6.parameters) end - def m1(*args, **options) - yield(*args, **options) + def m1(*args) + yield(*args) end def test_block @@ -3495,56 +273,15 @@ class TestKeywordArguments < Test::Unit::TestCase def test_rest_keyrest bug7665 = '[ruby-core:51278]' bug8463 = '[ruby-core:55203] [Bug #8463]' - a = [*%w[foo bar], {zzz: 42}] - splat_expect = a + [{}] - nonsplat_expect = [a, {}] - assert_equal(splat_expect, rest_keyrest(*a), bug7665) - assert_equal(nonsplat_expect, rest_keyrest(a), bug7665) - + expect = [*%w[foo bar], {zzz: 42}] + assert_equal(expect, rest_keyrest(*expect), bug7665) pr = proc {|*args, **opt| next *args, opt} - assert_equal(splat_expect, pr.call(*a), bug7665) - assert_equal(nonsplat_expect, pr.call(a), bug8463) - + assert_equal(expect, pr.call(*expect), bug7665) + assert_equal(expect, pr.call(expect), bug8463) pr = proc {|a, *b, **opt| next a, *b, opt} - assert_equal(splat_expect, pr.call(a), bug8463) - + assert_equal(expect, pr.call(expect), bug8463) pr = proc {|a, **opt| next a, opt} - assert_equal(splat_expect.values_at(0, -1), pr.call(splat_expect), bug8463) - end - - def req_plus_keyword(x, **h) - [x, h] - end - - def opt_plus_keyword(x=1, **h) - [x, h] - end - - def splat_plus_keyword(*a, **h) - [a, h] - end - - def test_keyword_no_split - assert_raise(ArgumentError) { req_plus_keyword(:a=>1) } - assert_raise(ArgumentError) { req_plus_keyword("a"=>1) } - assert_raise(ArgumentError) { req_plus_keyword("a"=>1, :a=>1) } - assert_equal([{:a=>1}, {}], req_plus_keyword({:a=>1})) - assert_equal([{"a"=>1}, {}], req_plus_keyword({"a"=>1})) - assert_equal([{"a"=>1, :a=>1}, {}], req_plus_keyword({"a"=>1, :a=>1})) - - assert_equal([1, {:a=>1}], opt_plus_keyword(:a=>1)) - assert_equal([1, {"a"=>1}], opt_plus_keyword("a"=>1)) - assert_equal([1, {"a"=>1, :a=>1}], opt_plus_keyword("a"=>1, :a=>1)) - assert_equal([{:a=>1}, {}], opt_plus_keyword({:a=>1})) - assert_equal([{"a"=>1}, {}], opt_plus_keyword({"a"=>1})) - assert_equal([{"a"=>1, :a=>1}, {}], opt_plus_keyword({"a"=>1, :a=>1})) - - assert_equal([[], {:a=>1}], splat_plus_keyword(:a=>1)) - assert_equal([[], {"a"=>1}], splat_plus_keyword("a"=>1)) - assert_equal([[], {"a"=>1, :a=>1}], splat_plus_keyword("a"=>1, :a=>1)) - assert_equal([[{:a=>1}], {}], splat_plus_keyword({:a=>1})) - assert_equal([[{"a"=>1}], {}], splat_plus_keyword({"a"=>1})) - assert_equal([[{"a"=>1, :a=>1}], {}], splat_plus_keyword({"a"=>1, :a=>1})) + assert_equal(expect.values_at(0, -1), pr.call(expect), bug8463) end def test_bare_kwrest @@ -3723,12 +460,13 @@ class TestKeywordArguments < Test::Unit::TestCase end def test_precedence_of_keyword_arguments_with_post_argument + bug8993 = '[ruby-core:57706] [Bug #8993]' a = Class.new do def foo(a, b, c=1, *d, e, f:2, **g) [a, b, c, d, e, f, g] end end - assert_raise(ArgumentError) { a.new.foo(1, 2, f:5) } + assert_equal([1, 2, 1, [], {:f=>5}, 2, {}], a.new.foo(1, 2, f:5), bug8993) end def test_splat_keyword_nondestructive @@ -3755,49 +493,33 @@ class TestKeywordArguments < Test::Unit::TestCase assert_equal({a: 1, b: 2}, m1(**o, **o2) {|x| break x}, bug9898) end - def test_no_implicit_hash_conversion + def test_implicit_hash_conversion + bug10016 = '[ruby-core:63593] [Bug #10016]' + o = Object.new def o.to_hash() { k: 9 } end assert_equal([1, 42, [], o, :key, {}, nil], f9(1, o)) - assert_equal([1, 0], m1(1, o) {|a, k: 0| break [a, k]}) - assert_raise(ArgumentError) { m1(1, o, &->(a, k: 0) {break [a, k]}) } + assert_equal([1, 9], m1(1, o) {|a, k: 0| break [a, k]}, bug10016) + assert_equal([1, 9], m1(1, o, &->(a, k: 0) {break [a, k]}), bug10016) end def test_splat_hash m = Object.new def m.f() :ok; end - def m.f1(a) a; end def m.f2(a = nil) a; end - def m.f3(**a) a; end - def m.f4(*a) a; end o = {a: 1} - assert_raise_with_message(ArgumentError, /wrong number of arguments \(given 1, expected 0\)/) { + assert_raise_with_message(ArgumentError, /unknown keyword: a/) { m.f(**o) } o = {} assert_equal(:ok, m.f(**o), '[ruby-core:68124] [Bug #10856]') a = [] assert_equal(:ok, m.f(*a, **o), '[ruby-core:83638] [Bug #10856]') - assert_equal(:OK, m.f1(*a, :OK, **o), '[ruby-core:91825] [Bug #10856]') - assert_equal({}, m.f1(*a, o), '[ruby-core:91825] [Bug #10856]') o = {a: 42} - assert_warning('', 'splat to mandatory') do - assert_equal({a: 42}, m.f1(**o)) - end - assert_warning('') do - assert_equal({a: 42}, m.f2(**o), '[ruby-core:82280] [Bug #13791]') - end - assert_warning('', 'splat to kwrest') do - assert_equal({a: 42}, m.f3(**o)) - end - assert_warning('', 'splat to rest') do - assert_equal([{a: 42}], m.f4(**o)) - end + assert_equal({a: 42}, m.f2(**o), '[ruby-core:82280] [Bug #13791]') - assert_warning('') do - assert_equal({a: 42}, m.f2("a".to_sym => 42), '[ruby-core:82291] [Bug #13793]') - end + assert_equal({a: 42}, m.f2("a".to_sym => 42), '[ruby-core:82291] [Bug #13793]') o = {} a = [:ok] @@ -3843,14 +565,14 @@ class TestKeywordArguments < Test::Unit::TestCase bar(k1: 1) end end - assert_raise_with_message(ArgumentError, /unknown keyword: :k1/, bug10413) { + assert_raise_with_message(ArgumentError, /unknown keyword: k1/, bug10413) { o.foo {raise "unreachable"} } end def test_unknown_keyword bug13004 = '[ruby-dev:49893] [Bug #13004]' - assert_raise_with_message(ArgumentError, /unknown keyword: :"invalid-argument"/, bug13004) { + assert_raise_with_message(ArgumentError, /unknown keyword: invalid-argument/, bug13004) { [].sample(random: nil, "invalid-argument": nil) } end @@ -3879,7 +601,7 @@ class TestKeywordArguments < Test::Unit::TestCase def test_nonsymbol_key result = m(["a" => 10]) { |a = nil, **b| [a, b] } - assert_equal([[{"a" => 10}], {}], result) + assert_equal([{"a" => 10}, {}], result) end def method_for_test_to_hash_call_during_setup_complex_parameters k1:, k2:, **rest_kw @@ -3957,346 +679,7 @@ class TestKeywordArguments < Test::Unit::TestCase end end - def many_kwargs(a0: '', a1: '', a2: '', a3: '', a4: '', a5: '', a6: '', a7: '', - b0: '', b1: '', b2: '', b3: '', b4: '', b5: '', b6: '', b7: '', - c0: '', c1: '', c2: '', c3: '', c4: '', c5: '', c6: '', c7: '', - d0: '', d1: '', d2: '', d3: '', d4: '', d5: '', d6: '', d7: '', - e0: '') - [a0, a1, a2, a3, a4, a5, a6, a7, - b0, b1, b2, b3, b4, b5, b6, b7, - c0, c1, c2, c3, c4, c5, c6, c7, - d0, d1, d2, d3, d4, d5, d6, d7, - e0] - end - - def test_many_kwargs - i = 0 - assert_equal(:ok, many_kwargs(a0: :ok)[i], "#{i}: a0"); i+=1 - assert_equal(:ok, many_kwargs(a1: :ok)[i], "#{i}: a1"); i+=1 - assert_equal(:ok, many_kwargs(a2: :ok)[i], "#{i}: a2"); i+=1 - assert_equal(:ok, many_kwargs(a3: :ok)[i], "#{i}: a3"); i+=1 - assert_equal(:ok, many_kwargs(a4: :ok)[i], "#{i}: a4"); i+=1 - assert_equal(:ok, many_kwargs(a5: :ok)[i], "#{i}: a5"); i+=1 - assert_equal(:ok, many_kwargs(a6: :ok)[i], "#{i}: a6"); i+=1 - assert_equal(:ok, many_kwargs(a7: :ok)[i], "#{i}: a7"); i+=1 - - assert_equal(:ok, many_kwargs(b0: :ok)[i], "#{i}: b0"); i+=1 - assert_equal(:ok, many_kwargs(b1: :ok)[i], "#{i}: b1"); i+=1 - assert_equal(:ok, many_kwargs(b2: :ok)[i], "#{i}: b2"); i+=1 - assert_equal(:ok, many_kwargs(b3: :ok)[i], "#{i}: b3"); i+=1 - assert_equal(:ok, many_kwargs(b4: :ok)[i], "#{i}: b4"); i+=1 - assert_equal(:ok, many_kwargs(b5: :ok)[i], "#{i}: b5"); i+=1 - assert_equal(:ok, many_kwargs(b6: :ok)[i], "#{i}: b6"); i+=1 - assert_equal(:ok, many_kwargs(b7: :ok)[i], "#{i}: b7"); i+=1 - - assert_equal(:ok, many_kwargs(c0: :ok)[i], "#{i}: c0"); i+=1 - assert_equal(:ok, many_kwargs(c1: :ok)[i], "#{i}: c1"); i+=1 - assert_equal(:ok, many_kwargs(c2: :ok)[i], "#{i}: c2"); i+=1 - assert_equal(:ok, many_kwargs(c3: :ok)[i], "#{i}: c3"); i+=1 - assert_equal(:ok, many_kwargs(c4: :ok)[i], "#{i}: c4"); i+=1 - assert_equal(:ok, many_kwargs(c5: :ok)[i], "#{i}: c5"); i+=1 - assert_equal(:ok, many_kwargs(c6: :ok)[i], "#{i}: c6"); i+=1 - assert_equal(:ok, many_kwargs(c7: :ok)[i], "#{i}: c7"); i+=1 - - assert_equal(:ok, many_kwargs(d0: :ok)[i], "#{i}: d0"); i+=1 - assert_equal(:ok, many_kwargs(d1: :ok)[i], "#{i}: d1"); i+=1 - assert_equal(:ok, many_kwargs(d2: :ok)[i], "#{i}: d2"); i+=1 - assert_equal(:ok, many_kwargs(d3: :ok)[i], "#{i}: d3"); i+=1 - assert_equal(:ok, many_kwargs(d4: :ok)[i], "#{i}: d4"); i+=1 - assert_equal(:ok, many_kwargs(d5: :ok)[i], "#{i}: d5"); i+=1 - assert_equal(:ok, many_kwargs(d6: :ok)[i], "#{i}: d6"); i+=1 - assert_equal(:ok, many_kwargs(d7: :ok)[i], "#{i}: d7"); i+=1 - - assert_equal(:ok, many_kwargs(e0: :ok)[i], "#{i}: e0"); i+=1 - end - def test_splat_empty_hash_with_block_passing assert_valid_syntax("bug15087(**{}, &nil)") end - - def test_do_not_use_newarraykwsplat - assert_equal([42, "foo", 424242], f2(*[], 42, **{})) - a = [1, 2, 3] - assert_equal([[1,2,3,4,5,6], "foo", 424242, {:k=>:k}], f7(*a, 4,5,6, k: :k)) - end -end - -class TestKeywordArgumentsSymProcRefinements < Test::Unit::TestCase - class C - def call(*args, **kw) - yield(self, *args, **kw) - end - end - using(Module.new do - refine C do - def m(*args, **kw) - super - end - end - end) - - def test_sym_proc_refine_kwsplat - kw = {} - h = {:a=>1} - h2 = {'a'=>1} - h3 = {'a'=>1, :a=>1} - - c = C.new - def c.m(*args) - args - end - assert_equal([], c.call(**{}, &:m)) - assert_equal([], c.call(**kw, &:m)) - assert_equal([h], c.call(**h, &:m)) - assert_equal([h], c.call(h, **{}, &:m)) - assert_equal([h], c.call(a: 1, &:m)) - assert_equal([h2], c.call(**h2, &:m)) - assert_equal([h3], c.call(**h3, &:m)) - assert_equal([h3], c.call(a: 1, **h2, &:m)) - - c.singleton_class.remove_method(:m) - def c.m; end - assert_nil(c.call(**{}, &:m)) - assert_nil(c.call(**kw, &:m)) - assert_raise(ArgumentError) { c.call(**h, &:m) } - assert_raise(ArgumentError) { c.call(a: 1, &:m) } - assert_raise(ArgumentError) { c.call(**h2, &:m) } - assert_raise(ArgumentError) { c.call(**h3, &:m) } - assert_raise(ArgumentError) { c.call(a: 1, **h2, &:m) } - - c.singleton_class.remove_method(:m) - def c.m(args) - args - end - assert_raise(ArgumentError) { c.call(**{}, &:m) } - assert_raise(ArgumentError) { c.call(**kw, &:m) } - assert_equal(h, c.call(**h, &:m)) - assert_equal(h, c.call(a: 1, &:m)) - assert_equal(h2, c.call(**h2, &:m)) - assert_equal(h3, c.call(**h3, &:m)) - assert_equal(h3, c.call(a: 1, **h2, &:m)) - - c.singleton_class.remove_method(:m) - def c.m(**args) - args - end - assert_equal(kw, c.call(**{}, &:m)) - assert_equal(kw, c.call(**kw, &:m)) - assert_equal(h, c.call(**h, &:m)) - assert_equal(h, c.call(a: 1, &:m)) - assert_equal(h2, c.call(**h2, &:m)) - assert_equal(h3, c.call(**h3, &:m)) - assert_equal(h3, c.call(a: 1, **h2, &:m)) - assert_raise(ArgumentError) { c.call(h, &:m) } - assert_raise(ArgumentError) { c.call(h2, &:m) } - assert_raise(ArgumentError) { c.call(h3, &:m) } - - c.singleton_class.remove_method(:m) - def c.m(arg, **args) - [arg, args] - end - assert_raise(ArgumentError) { c.call(**{}, &:m) } - assert_raise(ArgumentError) { c.call(**kw, &:m) } - assert_raise(ArgumentError) { c.call(**h, &:m) } - assert_raise(ArgumentError) { c.call(a: 1, &:m) } - assert_raise(ArgumentError) { c.call(**h2, &:m) } - assert_raise(ArgumentError) { c.call(**h3, &:m) } - assert_raise(ArgumentError) { c.call(a: 1, **h2, &:m) } - - c.singleton_class.remove_method(:m) - def c.m(arg=1, **args) - [arg, args] - end - assert_equal([1, kw], c.call(**{}, &:m)) - assert_equal([1, kw], c.call(**kw, &:m)) - assert_equal([1, h], c.call(**h, &:m)) - assert_equal([1, h], c.call(a: 1, &:m)) - assert_equal([1, h2], c.call(**h2, &:m)) - assert_equal([1, h3], c.call(**h3, &:m)) - assert_equal([1, h3], c.call(a: 1, **h2, &:m)) - end - - def test_sym_proc_refine_super_method_missing_kwsplat - kw = {} - h = {:a=>1} - h2 = {'a'=>1} - h3 = {'a'=>1, :a=>1} - - c = C.new - def c.method_missing(_, *args) - args - end - assert_equal([], c.call(**{}, &:m)) - assert_equal([], c.call(**kw, &:m)) - assert_equal([h], c.call(**h, &:m)) - assert_equal([h], c.call(h, **{}, &:m)) - assert_equal([h], c.call(a: 1, &:m)) - assert_equal([h2], c.call(**h2, &:m)) - assert_equal([h3], c.call(**h3, &:m)) - assert_equal([h3], c.call(a: 1, **h2, &:m)) - - c.singleton_class.remove_method(:method_missing) - def c.method_missing(_) end - assert_nil(c.call(**{}, &:m)) - assert_nil(c.call(**kw, &:m)) - assert_raise(ArgumentError) { c.call(**h, &:m) } - assert_raise(ArgumentError) { c.call(a: 1, &:m) } - assert_raise(ArgumentError) { c.call(**h2, &:m) } - assert_raise(ArgumentError) { c.call(**h3, &:m) } - assert_raise(ArgumentError) { c.call(a: 1, **h2, &:m) } - - c.singleton_class.remove_method(:method_missing) - def c.method_missing(_, args) - args - end - assert_raise(ArgumentError) { c.call(**{}, &:m) } - assert_raise(ArgumentError) { c.call(**kw, &:m) } - assert_equal(h, c.call(**h, &:m)) - assert_equal(h, c.call(a: 1, &:m)) - assert_equal(h2, c.call(**h2, &:m)) - assert_equal(h3, c.call(**h3, &:m)) - assert_equal(h3, c.call(a: 1, **h2, &:m)) - - c.singleton_class.remove_method(:method_missing) - def c.method_missing(_, **args) - args - end - assert_equal(kw, c.call(**{}, &:m)) - assert_equal(kw, c.call(**kw, &:m)) - assert_equal(h, c.call(**h, &:m)) - assert_equal(h, c.call(a: 1, &:m)) - assert_equal(h2, c.call(**h2, &:m)) - assert_equal(h3, c.call(**h3, &:m)) - assert_equal(h3, c.call(a: 1, **h2, &:m)) - assert_raise(ArgumentError) { c.call(h, &:m2) } - assert_raise(ArgumentError) { c.call(h2, &:m2) } - assert_raise(ArgumentError) { c.call(h3, &:m2) } - - c.singleton_class.remove_method(:method_missing) - def c.method_missing(_, arg, **args) - [arg, args] - end - assert_raise(ArgumentError) { c.call(**{}, &:m2) } - assert_raise(ArgumentError) { c.call(**kw, &:m2) } - assert_raise(ArgumentError) { c.call(**h, &:m2) } - assert_raise(ArgumentError) { c.call(a: 1, &:m2) } - assert_raise(ArgumentError) { c.call(**h2, &:m2) } - assert_raise(ArgumentError) { c.call(**h3, &:m2) } - assert_raise(ArgumentError) { c.call(a: 1, **h2, &:m2) } - - c.singleton_class.remove_method(:method_missing) - def c.method_missing(_, arg=1, **args) - [arg, args] - end - assert_equal([1, kw], c.call(**{}, &:m)) - assert_equal([1, kw], c.call(**kw, &:m)) - assert_equal([1, h], c.call(**h, &:m)) - assert_equal([1, h], c.call(a: 1, &:m)) - assert_equal([1, h2], c.call(**h2, &:m)) - assert_equal([1, h3], c.call(**h3, &:m)) - assert_equal([1, h3], c.call(a: 1, **h2, &:m)) - end - - def test_sym_proc_refine_method_missing_kwsplat - kw = {} - h = {:a=>1} - h2 = {'a'=>1} - h3 = {'a'=>1, :a=>1} - - c = C.new - def c.method_missing(_, *args) - args - end - assert_equal([], c.call(**{}, &:m2)) - assert_equal([], c.call(**kw, &:m2)) - assert_equal([h], c.call(**h, &:m2)) - assert_equal([h], c.call(h, **{}, &:m2)) - assert_equal([h], c.call(a: 1, &:m2)) - assert_equal([h2], c.call(**h2, &:m2)) - assert_equal([h3], c.call(**h3, &:m2)) - assert_equal([h3], c.call(a: 1, **h2, &:m2)) - - c.singleton_class.remove_method(:method_missing) - def c.method_missing(_) end - assert_nil(c.call(**{}, &:m2)) - assert_nil(c.call(**kw, &:m2)) - assert_raise(ArgumentError) { c.call(**h, &:m2) } - assert_raise(ArgumentError) { c.call(a: 1, &:m2) } - assert_raise(ArgumentError) { c.call(**h2, &:m2) } - assert_raise(ArgumentError) { c.call(**h3, &:m2) } - assert_raise(ArgumentError) { c.call(a: 1, **h2, &:m2) } - - c.singleton_class.remove_method(:method_missing) - def c.method_missing(_, args) - args - end - assert_raise(ArgumentError) { c.call(**{}, &:m2) } - assert_raise(ArgumentError) { c.call(**kw, &:m2) } - assert_equal(h, c.call(**h, &:m2)) - assert_equal(h, c.call(a: 1, &:m2)) - assert_equal(h2, c.call(**h2, &:m2)) - assert_equal(h3, c.call(**h3, &:m2)) - assert_equal(h3, c.call(a: 1, **h2, &:m2)) - - c.singleton_class.remove_method(:method_missing) - def c.method_missing(_, **args) - args - end - assert_equal(kw, c.call(**{}, &:m2)) - assert_equal(kw, c.call(**kw, &:m2)) - assert_equal(h, c.call(**h, &:m2)) - assert_equal(h, c.call(a: 1, &:m2)) - assert_equal(h2, c.call(**h2, &:m2)) - assert_equal(h3, c.call(**h3, &:m2)) - assert_equal(h3, c.call(a: 1, **h2, &:m2)) - assert_raise(ArgumentError) { c.call(h, &:m2) } - assert_raise(ArgumentError) { c.call(h2, &:m2) } - assert_raise(ArgumentError) { c.call(h3, &:m2) } - - c.singleton_class.remove_method(:method_missing) - def c.method_missing(_, arg, **args) - [arg, args] - end - assert_raise(ArgumentError) { c.call(**{}, &:m2) } - assert_raise(ArgumentError) { c.call(**kw, &:m2) } - assert_raise(ArgumentError) { c.call(**h, &:m2) } - assert_raise(ArgumentError) { c.call(a: 1, &:m2) } - assert_raise(ArgumentError) { c.call(**h2, &:m2) } - assert_raise(ArgumentError) { c.call(**h3, &:m2) } - assert_raise(ArgumentError) { c.call(a: 1, **h2, &:m2) } - - c.singleton_class.remove_method(:method_missing) - def c.method_missing(_, arg=1, **args) - [arg, args] - end - assert_equal([1, kw], c.call(**{}, &:m2)) - assert_equal([1, kw], c.call(**kw, &:m2)) - assert_equal([1, h], c.call(**h, &:m2)) - assert_equal([1, h], c.call(a: 1, &:m2)) - assert_equal([1, h2], c.call(**h2, &:m2)) - assert_equal([1, h3], c.call(**h3, &:m2)) - assert_equal([1, h3], c.call(a: 1, **h2, &:m2)) - end - - def test_protected_kwarg - mock = Class.new do - def foo - bar('x', y: 'z') - end - protected - def bar(x, y) - nil - end - end - - assert_nothing_raised do - mock.new.foo - end - end - - def test_splat_fixnum - bug16603 = '[ruby-core:97047] [Bug #16603]' - assert_raise(TypeError, bug16603) { p(**42) } - assert_raise(TypeError, bug16603) { p(k:1, **42) } - end end diff --git a/test/ruby/test_lambda.rb b/test/ruby/test_lambda.rb index 8e460475c0..3ac2e4cb98 100644 --- a/test/ruby/test_lambda.rb +++ b/test/ruby/test_lambda.rb @@ -74,32 +74,6 @@ class TestLambdaParameters < Test::Unit::TestCase assert_raise(ArgumentError, bug9605) {proc(&plus).call [1,2]} end - def pass_along(&block) - lambda(&block) - end - - def pass_along2(&block) - pass_along(&block) - end - - def test_create_non_lambda_for_proc_one_level - prev_warning, Warning[:deprecated] = Warning[:deprecated], false - f = pass_along {} - refute_predicate(f, :lambda?, '[Bug #15620]') - assert_nothing_raised(ArgumentError) { f.call(:extra_arg) } - ensure - Warning[:deprecated] = prev_warning - end - - def test_create_non_lambda_for_proc_two_levels - prev_warning, Warning[:deprecated] = Warning[:deprecated], false - f = pass_along2 {} - refute_predicate(f, :lambda?, '[Bug #15620]') - assert_nothing_raised(ArgumentError) { f.call(:extra_arg) } - ensure - Warning[:deprecated] = prev_warning - end - def test_instance_exec bug12568 = '[ruby-core:76300] [Bug #12568]' assert_nothing_raised(ArgumentError, bug12568) do @@ -183,21 +157,6 @@ class TestLambdaParameters < Test::Unit::TestCase assert_equal(42, return_in_callee(42), feature8693) end - def break_in_current(val) - 1.tap(&->(*) {break 0}) - val - end - - def break_in_callee(val) - yield_block(&->(*) {break 0}) - val - end - - def test_break - assert_equal(42, break_in_current(42)) - assert_equal(42, break_in_callee(42)) - end - def test_do_lambda_source_location exp_lineno = __LINE__ + 3 lmd = ->(x, @@ -221,31 +180,4 @@ class TestLambdaParameters < Test::Unit::TestCase assert_match(/^#{ Regexp.quote(__FILE__) }$/, file) assert_equal(exp_lineno, lineno, "must be at the beginning of the block") end - - def test_not_orphan_return - assert_equal(42, Module.new { extend self - def m1(&b) b.call end; def m2(); m1(&-> { return 42 }) end }.m2) - assert_equal(42, Module.new { extend self - def m1(&b) b end; def m2(); m1(&-> { return 42 }).call end }.m2) - assert_equal(42, Module.new { extend self - def m1(&b) b end; def m2(); m1(&-> { return 42 }) end }.m2.call) - end - - def test_not_orphan_break - assert_equal(42, Module.new { extend self - def m1(&b) b.call end; def m2(); m1(&-> { break 42 }) end }.m2) - assert_equal(42, Module.new { extend self - def m1(&b) b end; def m2(); m1(&-> { break 42 }).call end }.m2) - assert_equal(42, Module.new { extend self - def m1(&b) b end; def m2(); m1(&-> { break 42 }) end }.m2.call) - end - - def test_not_orphan_next - assert_equal(42, Module.new { extend self - def m1(&b) b.call end; def m2(); m1(&-> { next 42 }) end }.m2) - assert_equal(42, Module.new { extend self - def m1(&b) b end; def m2(); m1(&-> { next 42 }).call end }.m2) - assert_equal(42, Module.new { extend self - def m1(&b) b end; def m2(); m1(&-> { next 42 }) end }.m2.call) - end end diff --git a/test/ruby/test_lazy_enumerator.rb b/test/ruby/test_lazy_enumerator.rb index 3f5a05555b..03371c912a 100644 --- a/test/ruby/test_lazy_enumerator.rb +++ b/test/ruby/test_lazy_enumerator.rb @@ -17,9 +17,9 @@ class TestLazyEnumerator < Test::Unit::TestCase @enum.each do |v| @current = v if v.is_a? Enumerable - yield(*v) + yield *v else - yield(v) + yield v end end end @@ -160,10 +160,6 @@ class TestLazyEnumerator < Test::Unit::TestCase assert_equal([{?a=>97}, {?b=>98}, {?c=>99}], [?a, ?b, ?c].lazy.flat_map {|x| {x=>x.ord}}.force) end - def test_flat_map_take - assert_equal([1,2]*3, [[1,2]].cycle.lazy.take(3).flat_map {|x| x}.to_a) - end - def test_reject a = Step.new(1..6) assert_equal(4, a.reject {|x| x < 4}.first) @@ -456,14 +452,6 @@ class TestLazyEnumerator < Test::Unit::TestCase EOS end - def test_lazy_eager - lazy = [1, 2, 3].lazy.map { |x| x * 2 } - enum = lazy.eager - assert_equal Enumerator, enum.class - assert_equal 3, enum.size - assert_equal [1, 2, 3], enum.map { |x| x / 2 } - end - def test_lazy_to_enum lazy = [1, 2, 3].lazy def lazy.foo(*args) @@ -478,54 +466,6 @@ EOS assert_equal [1, 2, 3], lazy.to_enum.to_a end - def test_lazy_to_enum_lazy_methods - a = [1, 2, 3].to_enum - pr = proc{|x| [x, x * 2]} - selector = proc{|x| x*2 if x % 2 == 0} - - [ - [:with_index, nil], - [:with_index, 10, nil], - [:with_index, 10, pr], - [:map, nil], - [:map, pr], - [:collect, nil], - [:flat_map, nil], - [:flat_map, pr], - [:collect_concat, nil], - [:select, nil], - [:select, selector], - [:find_all, nil], - [:filter, nil], - [:filter_map, selector], - [:filter_map, nil], - [:reject, selector], - [:grep, selector, nil], - [:grep, selector, pr], - [:grep_v, selector, nil], - [:grep_v, selector, pr], - [:zip, a, nil], - [:take, 3, nil], - [:take_while, nil], - [:take_while, selector], - [:drop, 1, nil], - [:drop_while, nil], - [:drop_while, selector], - [:uniq, nil], - [:uniq, proc{|x| x.odd?}], - ].each do |args| - block = args.pop - assert_equal [1, 2, 3].to_enum.to_enum(*args).first(2).to_a, [1, 2, 3].to_enum.lazy.to_enum(*args).first(2).to_a - assert_equal (0..50).to_enum.to_enum(*args).first(2).to_a, (0..50000).to_enum.lazy.to_enum(*args).first(2).to_a - if block - assert_equal [1, 2, 3, 4].to_enum.to_enum(*args).map(&block).first(2).to_a, [1, 2, 3, 4].to_enum.lazy.to_enum(*args).map(&block).first(2).to_a - unless args.first == :take_while || args.first == :drop_while - assert_equal (0..50).to_enum.to_enum(*args).map(&block).first(2).to_a, (0..50000).to_enum.lazy.to_enum(*args).map(&block).first(2).to_a - end - end - end - end - def test_size lazy = [1, 2, 3].lazy assert_equal 3, lazy.size @@ -638,48 +578,4 @@ EOS assert_equal([1, 2, 3, 4, 5, 10], u.first(6)) assert_equal([1, 2, 3, 4, 5, 10], u.first(6)) end - - def test_filter_map - e = (1..Float::INFINITY).lazy.filter_map do |x| - raise "too big" if x > 10000 - (x**2) % 10 if x.even? - end - assert_equal([4, 6, 6, 4, 0, 4], e.first(6)) - assert_equal([4, 6, 6, 4, 0, 4], e.first(6)) - end - - def test_with_index - feature7877 = '[ruby-dev:47025] [Feature #7877]' - leibniz = ->(n) { - (0..Float::INFINITY).lazy.with_index.map {|i, j| - raise IndexError, "limit exceeded (#{n})" unless j < n - ((-1) ** j) / (2*i+1).to_f - }.take(n).reduce(:+) - } - assert_nothing_raised(IndexError, feature7877) { - assert_in_epsilon(Math::PI/4, leibniz[1000]) - } - - a = [] - ary = (0..Float::INFINITY).lazy.with_index(2) {|i, j| a << [i-1, j] }.take(2).to_a - assert_equal([[-1, 2], [0, 3]], a) - assert_equal([0, 1], ary) - - a = [] - ary = (0..Float::INFINITY).lazy.with_index(2, &->(i,j) { a << [i-1, j] }).take(2).to_a - assert_equal([[-1, 2], [0, 3]], a) - assert_equal([0, 1], ary) - - ary = (0..Float::INFINITY).lazy.with_index(2).map {|i, j| [i-1, j] }.take(2).to_a - assert_equal([[-1, 2], [0, 3]], ary) - - ary = (0..Float::INFINITY).lazy.with_index(2).map(&->(i, j) { [i-1, j] }).take(2).to_a - assert_equal([[-1, 2], [0, 3]], ary) - - ary = (0..Float::INFINITY).lazy.with_index(2).take(2).to_a - assert_equal([[0, 2], [1, 3]], ary) - - ary = (0..Float::INFINITY).lazy.with_index.take(2).to_a - assert_equal([[0, 0], [1, 1]], ary) - end end diff --git a/test/ruby/test_literal.rb b/test/ruby/test_literal.rb index 679af20bb9..cf1a2babd7 100644 --- a/test/ruby/test_literal.rb +++ b/test/ruby/test_literal.rb @@ -45,7 +45,6 @@ class TestRubyLiteral < Test::Unit::TestCase assert_equal "A", ?A assert_instance_of String, ?\n assert_equal "\n", ?\n - assert_equal " ", ?\s assert_equal " ", ?\ # space assert_equal '', '' assert_equal 'string', 'string' @@ -178,34 +177,17 @@ class TestRubyLiteral < Test::Unit::TestCase end end - def test_frozen_string_in_array_literal - list = eval("# frozen-string-literal: true\n""['foo', 'bar']") - assert_equal 2, list.length - list.each { |str| assert_predicate str, :frozen? } - end - if defined?(RubyVM::InstructionSequence.compile_option) and RubyVM::InstructionSequence.compile_option.key?(:debug_frozen_string_literal) def test_debug_frozen_string - src = '_="foo-1"'; f = "test.rb"; n = 1 + src = 'n = 1; "foo#{n ? "-#{n}" : ""}"'; f = "test.rb"; n = 1 opt = {frozen_string_literal: true, debug_frozen_string_literal: true} - str = RubyVM::InstructionSequence.compile(src, f, f, n, **opt).eval + str = RubyVM::InstructionSequence.compile(src, f, f, n, opt).eval assert_equal("foo-1", str) assert_predicate(str, :frozen?) assert_raise_with_message(FrozenError, /created at #{Regexp.quote(f)}:#{n}/) { str << "x" - } unless ENV['RUBY_ISEQ_DUMP_DEBUG'] - end - - def test_debug_frozen_string_in_array_literal - src = '["foo"]'; f = "test.rb"; n = 1 - opt = {frozen_string_literal: true, debug_frozen_string_literal: true} - ary = RubyVM::InstructionSequence.compile(src, f, f, n, **opt).eval - assert_equal("foo", ary.first) - assert_predicate(ary.first, :frozen?) - assert_raise_with_message(FrozenError, /created at #{Regexp.quote(f)}:#{n}/) { - ary.first << "x" - } unless ENV['RUBY_ISEQ_DUMP_DEBUG'] + } end end @@ -284,24 +266,6 @@ class TestRubyLiteral < Test::Unit::TestCase assert_equal "literal", h["string"] end - def test_hash_literal_frozen - assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") - begin; - def frozen_hash_literal_arg - {0=>1,1=>4,2=>17} - end - - ObjectSpace.each_object(Hash) do |a| - if a.class == Hash and !a.default_proc and a.size == 3 && - a[0] == 1 && a[1] == 4 && a[2] == 17 - # should not be found. - raise - end - end - assert_not_include frozen_hash_literal_arg, 3 - end; - end - def test_big_array_and_hash_literal assert_normal_exit %q{GC.disable=true; x = nil; raise if eval("[#{(1..1_000_000).map{'x'}.join(", ")}]").size != 1_000_000}, "", timeout: 300, child_env: %[--disable-gems] assert_normal_exit %q{GC.disable=true; x = nil; raise if eval("[#{(1..1_000_000).to_a.join(", ")}]").size != 1_000_000}, "", timeout: 300, child_env: %[--disable-gems] @@ -552,12 +516,15 @@ class TestRubyLiteral < Test::Unit::TestCase } } bug2407 = '[ruby-dev:39798]' - head.grep_v(/^0/) do |s| - head.grep(/^0/) do |h| - h = "#{s}#{h}_" - assert_syntax_error(h, /numeric literal without digits\Z/, "#{bug2407}: #{h.inspect}") + head.each {|h| + if /^0/ =~ h + begin + eval("#{h}_") + rescue SyntaxError => e + assert_match(/numeric literal without digits\Z/, e.message, bug2407) + end end - end + } end def test_float diff --git a/test/ruby/test_m17n.rb b/test/ruby/test_m17n.rb index 3f28d55ac1..9c7df4cb03 100644 --- a/test/ruby/test_m17n.rb +++ b/test/ruby/test_m17n.rb @@ -310,7 +310,6 @@ class TestM17N < Test::Unit::TestCase def o.inspect "abc".encode(Encoding.default_external) end - assert_equal '[abc]', [o].inspect Encoding.default_external = Encoding::US_ASCII @@ -366,10 +365,7 @@ class TestM17N < Test::Unit::TestCase "\u3042".encode("UTF-16LE"), "\u3042".encode("UTF-16BE"), ].each do |str| - dump = str.dump - assert_equal(str, eval(dump), "[ruby-dev:33142]") - assert_equal(str, dump.undump) - assert_equal(str, eval("# frozen-string-literal: true\n#{dump}"), '[Bug #14687]') + assert_equal(str, eval(str.dump), "[ruby-dev:33142]") end end @@ -616,8 +612,6 @@ class TestM17N < Test::Unit::TestCase r1 = Regexp.new('\xa1'.force_encoding("ascii-8bit")) r2 = eval('/\xa1#{r1}/'.force_encoding('ascii-8bit')) assert_equal(Encoding::ASCII_8BIT, r2.encoding) - - [r1, r2] end def test_regexp_named_class @@ -1325,14 +1319,10 @@ class TestM17N < Test::Unit::TestCase end def test_env - if RUBY_PLATFORM =~ /bccwin|mswin|mingw/ - env_encoding = Encoding::UTF_8 - else - env_encoding = Encoding.find("locale") - end + locale_encoding = Encoding.find("locale") ENV.each {|k, v| - assert_equal(env_encoding, k.encoding, k) - assert_equal(env_encoding, v.encoding, v) + assert_equal(locale_encoding, k.encoding, k) + assert_equal(locale_encoding, v.encoding, v) } end @@ -1538,17 +1528,6 @@ class TestM17N < Test::Unit::TestCase } end - def test_setbyte_range - s = u("\xE3\x81\x82\xE3\x81\x84") - assert_nothing_raised { s.setbyte(0, -1) } - assert_nothing_raised { s.setbyte(0, 0x00) } - assert_nothing_raised { s.setbyte(0, 0x7F) } - assert_nothing_raised { s.setbyte(0, 0x80) } - assert_nothing_raised { s.setbyte(0, 0xff) } - assert_nothing_raised { s.setbyte(0, 0x100) } - assert_nothing_raised { s.setbyte(0, 0x4f7574206f6620636861722072616e6765) } - end - def test_compatible assert_nil Encoding.compatible?("",0) assert_equal(Encoding::UTF_8, Encoding.compatible?(u(""), ua("abc"))) @@ -1587,6 +1566,8 @@ class TestM17N < Test::Unit::TestCase s = "\u3042" assert_equal(a("\xE3\x81\x82"), s.b) assert_equal(Encoding::ASCII_8BIT, s.b.encoding) + s.taint + assert_predicate(s.b, :tainted?) s = "abc".b assert_predicate(s.b, :ascii_only?) end @@ -1595,31 +1576,23 @@ class TestM17N < Test::Unit::TestCase str = "foo" assert_equal(str, str.scrub) assert_not_same(str, str.scrub) + assert_predicate(str.dup.taint.scrub, :tainted?) str = "\u3042\u3044" assert_equal(str, str.scrub) assert_not_same(str, str.scrub) + assert_predicate(str.dup.taint.scrub, :tainted?) str.force_encoding(Encoding::ISO_2022_JP) # dummy encoding assert_equal(str, str.scrub) assert_not_same(str, str.scrub) assert_nothing_raised(ArgumentError) {str.scrub(nil)} - end - - def test_scrub_modification_inside_block - str = ("abc\u3042".b << "\xE3\x80".b).force_encoding('UTF-8') - assert_raise(RuntimeError) {str.scrub{|_| str << "1234567890"; "?" }} - - str = "\x00\xD8\x42\x30".force_encoding(Encoding::UTF_16LE) - assert_raise(RuntimeError) do - str.scrub do |_| - str << "1\x002\x00".force_encoding('UTF-16LE') - "?\x00".force_encoding('UTF-16LE') - end - end + assert_predicate(str.dup.taint.scrub, :tainted?) end def test_scrub_replace_default assert_equal("\uFFFD\uFFFD\uFFFD", u("\x80\x80\x80").scrub) assert_equal("\uFFFDA", u("\xF4\x80\x80A").scrub) + assert_predicate(u("\x80\x80\x80").taint.scrub, :tainted?) + assert_predicate(u("\xF4\x80\x80A").taint.scrub, :tainted?) # examples in Unicode 6.1.0 D93b assert_equal("\x41\uFFFD\uFFFD\x41\uFFFD\x41", @@ -1634,8 +1607,14 @@ class TestM17N < Test::Unit::TestCase def test_scrub_replace_argument assert_equal("foo", u("foo").scrub("\u3013")) + assert_predicate(u("foo").taint.scrub("\u3013"), :tainted?) + assert_not_predicate(u("foo").scrub("\u3013".taint), :tainted?) assert_equal("\u3042\u3044", u("\xE3\x81\x82\xE3\x81\x84").scrub("\u3013")) + assert_predicate(u("\xE3\x81\x82\xE3\x81\x84").taint.scrub("\u3013"), :tainted?) + assert_not_predicate(u("\xE3\x81\x82\xE3\x81\x84").scrub("\u3013".taint), :tainted?) assert_equal("\u3042\u3013", u("\xE3\x81\x82\xE3\x81").scrub("\u3013")) + assert_predicate(u("\xE3\x81\x82\xE3\x81").taint.scrub("\u3013"), :tainted?) + assert_predicate(u("\xE3\x81\x82\xE3\x81").scrub("\u3013".taint), :tainted?) assert_raise(Encoding::CompatibilityError){ u("\xE3\x81\x82\xE3\x81").scrub(e("\xA4\xA2")) } assert_raise(TypeError){ u("\xE3\x81\x82\xE3\x81").scrub(1) } assert_raise(ArgumentError){ u("\xE3\x81\x82\xE3\x81\x82\xE3\x81").scrub(u("\x81")) } @@ -1644,6 +1623,8 @@ class TestM17N < Test::Unit::TestCase def test_scrub_replace_block assert_equal("\u3042<e381>", u("\xE3\x81\x82\xE3\x81").scrub{|x|'<'+x.unpack('H*')[0]+'>'}) + assert_predicate(u("\xE3\x81\x82\xE3\x81").taint.scrub{|x|'<'+x.unpack('H*')[0]+'>'}, :tainted?) + assert_predicate(u("\xE3\x81\x82\xE3\x81").scrub{|x|('<'+x.unpack('H*')[0]+'>').taint}, :tainted?) assert_raise(Encoding::CompatibilityError){ u("\xE3\x81\x82\xE3\x81").scrub{e("\xA4\xA2")} } assert_raise(TypeError){ u("\xE3\x81\x82\xE3\x81").scrub{1} } assert_raise(ArgumentError){ u("\xE3\x81\x82\xE3\x81\x82\xE3\x81").scrub{u("\x81")} } diff --git a/test/ruby/test_m17n_comb.rb b/test/ruby/test_m17n_comb.rb index 49141790f0..99c162a92f 100644 --- a/test/ruby/test_m17n_comb.rb +++ b/test/ruby/test_m17n_comb.rb @@ -744,21 +744,11 @@ class TestM17NComb < Test::Unit::TestCase } end - def crypt_supports_des_crypt? - /openbsd/ !~ RUBY_PLATFORM - end - # glibc 2.16 or later denies salt contained other than [0-9A-Za-z./] #7312 # we use this check to test strict and non-strict behavior separately #11045 strict_crypt = if defined? Etc::CS_GNU_LIBC_VERSION - begin - confstr = Etc.confstr(Etc::CS_GNU_LIBC_VERSION) - rescue Errno::EINVAL - false - else - glibcver = confstr.scan(/\d+/).map(&:to_i) - (glibcver <=> [2, 16]) >= 0 - end + glibcver = Etc.confstr(Etc::CS_GNU_LIBC_VERSION).scan(/\d+/).map(&:to_i) + (glibcver <=> [2, 16]) >= 0 end def test_str_crypt @@ -770,7 +760,7 @@ class TestM17NComb < Test::Unit::TestCase } end - if !strict_crypt && /openbsd/ !~ RUBY_PLATFORM + if !strict_crypt def test_str_crypt_nonstrict combination(STRINGS, STRINGS) {|str, salt| # only test input other than [0-9A-Za-z./] to confirm non-strict behavior @@ -782,14 +772,9 @@ class TestM17NComb < Test::Unit::TestCase end private def confirm_crypt_result(str, salt) - if crypt_supports_des_crypt? - if b(salt).length < 2 - assert_raise(ArgumentError) { str.crypt(salt) } - return - end - else - return if b(salt).length < 2 - salt = "$2a$04$0WVaz0pV3jzfZ5G5tpmH#{salt}" + if b(salt).length < 2 + assert_raise(ArgumentError) { str.crypt(salt) } + return end t = str.crypt(salt) assert_equal(b(str).crypt(b(salt)), t, "#{encdump(str)}.crypt(#{encdump(salt)})") diff --git a/test/ruby/test_marshal.rb b/test/ruby/test_marshal.rb index ef8b261321..0565a1c04f 100644 --- a/test/ruby/test_marshal.rb +++ b/test/ruby/test_marshal.rb @@ -8,6 +8,7 @@ class TestMarshal < Test::Unit::TestCase def setup @verbose = $VERBOSE + $VERBOSE = nil end def teardown @@ -156,29 +157,20 @@ class TestMarshal < Test::Unit::TestCase end def test_change_class_name - 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) assert_raise(TypeError) { Marshal.load(m) } - self.class.__send__(:remove_const, :C3) eval("C3 = nil") assert_raise(TypeError) { Marshal.load(m) } - ensure - self.class.__send__(:remove_const, :C3) if self.class.const_defined?(:C3) end def test_change_struct - 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")) - self.class.__send__(:remove_const, :C3) eval("C3 = Struct.new(:foo)") assert_raise(TypeError) { Marshal.load(m) } - self.class.__send__(:remove_const, :C3) 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) end class C4 @@ -197,6 +189,57 @@ class TestMarshal < Test::Unit::TestCase end end + def test_taint + x = Object.new + x.taint + s = Marshal.dump(x) + assert_equal(true, s.tainted?) + y = Marshal.load(s) + assert_equal(true, y.tainted?) + end + + def test_taint_each_object + x = Object.new + obj = [[x]] + + # clean object causes crean stream + assert_equal(false, obj.tainted?) + assert_equal(false, obj.first.tainted?) + assert_equal(false, obj.first.first.tainted?) + s = Marshal.dump(obj) + assert_equal(false, s.tainted?) + + # tainted object causes tainted stream + x.taint + assert_equal(false, obj.tainted?) + assert_equal(false, obj.first.tainted?) + assert_equal(true, obj.first.first.tainted?) + t = Marshal.dump(obj) + assert_equal(true, t.tainted?) + + # clean stream causes clean objects + assert_equal(false, s.tainted?) + y = Marshal.load(s) + assert_equal(false, y.tainted?) + assert_equal(false, y.first.tainted?) + assert_equal(false, y.first.first.tainted?) + + # tainted stream causes tainted objects + assert_equal(true, t.tainted?) + y = Marshal.load(t) + assert_equal(true, y.tainted?) + assert_equal(true, y.first.tainted?) + assert_equal(true, y.first.first.tainted?) + + # same tests by different senario + s.taint + assert_equal(true, s.tainted?) + y = Marshal.load(s) + assert_equal(true, y.tainted?) + assert_equal(true, y.first.tainted?) + assert_equal(true, y.first.first.tainted?) + end + def test_symbol2 [:ruby, :"\u{7d05}\u{7389}"].each do |sym| assert_equal(sym, Marshal.load(Marshal.dump(sym)), '[ruby-core:24788]') @@ -456,6 +499,16 @@ class TestMarshal < Test::Unit::TestCase module TestModule end + def test_marshal_load_should_not_taint_classes + bug7325 = '[ruby-core:49198]' + for c in [TestClass, TestModule] + assert_not_predicate(c, :tainted?) + c2 = Marshal.load(Marshal.dump(c).taint) + assert_same(c, c2) + assert_not_predicate(c, :tainted?, bug7325) + end + end + class Bug7627 < Struct.new(:bar) attr_accessor :foo @@ -550,7 +603,7 @@ class TestMarshal < Test::Unit::TestCase end class TestForRespondToFalse - def respond_to?(a, priv = false) + def respond_to?(a) false end end @@ -567,6 +620,15 @@ class TestMarshal < Test::Unit::TestCase assert_equal(Marshal.dump(bare), Marshal.dump(packed)) end + def test_untainted_numeric + bug8945 = '[ruby-core:57346] [Bug #8945] Numerics never be tainted' + b = RbConfig::LIMITS['FIXNUM_MAX'] + 1 + tainted = [0, 1.0, 1.72723e-77, b].select do |x| + Marshal.load(Marshal.dump(x).taint).tainted? + end + assert_empty(tainted.map {|x| [x, x.class]}, bug8945) + end + class Bug9523 attr_reader :cc def marshal_dump @@ -578,7 +640,7 @@ class TestMarshal < Test::Unit::TestCase end def test_continuation - EnvUtil.suppress_warning {require "continuation"} + require "continuation" c = Bug9523.new assert_raise_with_message(RuntimeError, /Marshal\.dump reentered at marshal_dump/) do Marshal.dump(c) @@ -604,8 +666,7 @@ class TestMarshal < Test::Unit::TestCase end def test_unloadable_data - name = "Unloadable\u{23F0 23F3}" - c = eval("class #{name} < Time;;self;end") + c = eval("class Unloadable\u{23F0 23F3}<Time;;self;end") c.class_eval { alias _dump_data _dump undef _dump @@ -614,16 +675,10 @@ class TestMarshal < Test::Unit::TestCase assert_raise_with_message(TypeError, /Unloadable\u{23F0 23F3}/) { Marshal.load(d) } - - # cleanup - self.class.class_eval do - remove_const name - end end def test_unloadable_userdef - name = "Userdef\u{23F0 23F3}" - c = eval("class #{name} < Time;self;end") + c = eval("class Userdef\u{23F0 23F3}<Time;self;end") class << c undef _load end @@ -631,11 +686,6 @@ class TestMarshal < Test::Unit::TestCase assert_raise_with_message(TypeError, /Userdef\u{23F0 23F3}/) { Marshal.load(d) } - - # cleanup - self.class.class_eval do - remove_const name - end end def test_unloadable_usrmarshal @@ -651,16 +701,15 @@ class TestMarshal < Test::Unit::TestCase def test_no_internal_ids opt = %w[--disable=gems] - args = [opt, 'Marshal.dump("",STDOUT)', true, true] - kw = {encoding: Encoding::ASCII_8BIT} - out, err, status = EnvUtil.invoke_ruby(*args, **kw) + args = [opt, 'Marshal.dump("",STDOUT)', true, true, encoding: Encoding::ASCII_8BIT] + out, err, status = EnvUtil.invoke_ruby(*args) assert_empty(err) assert_predicate(status, :success?) expected = out opt << "--enable=frozen-string-literal" opt << "--debug=frozen-string-literal" - out, err, status = EnvUtil.invoke_ruby(*args, **kw) + out, err, status = EnvUtil.invoke_ruby(*args) assert_empty(err) assert_predicate(status, :success?) assert_equal(expected, out) @@ -746,11 +795,7 @@ class TestMarshal < Test::Unit::TestCase end def marshal_dump - if self.foo.baz - self.foo.remove_instance_variable(:@baz) - else - self.foo.baz = :problem - end + self.foo.baz = :problem {foo: self.foo} end @@ -766,57 +811,4 @@ class TestMarshal < Test::Unit::TestCase Marshal.dump(obj) end end - - def test_marshal_dump_removing_instance_variable - obj = Bug15968.new - obj.baz = :Bug15968 - assert_raise_with_message(RuntimeError, /instance variable removed/) do - Marshal.dump(obj) - end - end - - ruby2_keywords def ruby2_keywords_hash(*a) - a.last - end - - def ruby2_keywords_test(key: 1) - key - end - - def test_marshal_with_ruby2_keywords_hash - flagged_hash = ruby2_keywords_hash(key: 42) - hash = Marshal.load(Marshal.dump(flagged_hash)) - assert_equal(42, ruby2_keywords_test(*[hash])) - end - - def exception_test - raise - end - - def test_marshal_exception - begin - exception_test - rescue => e - e2 = Marshal.load(Marshal.dump(e)) - assert_equal(e.message, e2.message) - assert_equal(e.backtrace, e2.backtrace) - assert_nil(e2.backtrace_locations) # temporal - end - end - - def nameerror_test - unknown_method - end - - def test_marshal_nameerror - begin - nameerror_test - rescue NameError => e - e2 = Marshal.load(Marshal.dump(e)) - assert_equal(e.message, e2.message) - assert_equal(e.name, e2.name) - assert_equal(e.backtrace, e2.backtrace) - assert_nil(e2.backtrace_locations) # temporal - end - end end diff --git a/test/ruby/test_math.rb b/test/ruby/test_math.rb index 5cc12bcfeb..f226287442 100644 --- a/test/ruby/test_math.rb +++ b/test/ruby/test_math.rb @@ -202,7 +202,6 @@ class TestMath < Test::Unit::TestCase check(3, Math.cbrt(27)) check(-0.1, Math.cbrt(-0.001)) assert_nothing_raised { assert_infinity(Math.cbrt(1.0/0)) } - assert_operator(Math.cbrt(1.0 - Float::EPSILON), :<=, 1.0) end def test_frexp diff --git a/test/ruby/test_memory_view.rb b/test/ruby/test_memory_view.rb deleted file mode 100644 index 5a39084d18..0000000000 --- a/test/ruby/test_memory_view.rb +++ /dev/null @@ -1,341 +0,0 @@ -require "-test-/memory_view" -require "rbconfig/sizeof" - -class TestMemoryView < Test::Unit::TestCase - NATIVE_ENDIAN = MemoryViewTestUtils::NATIVE_ENDIAN - LITTLE_ENDIAN = :little_endian - BIG_ENDIAN = :big_endian - - %I(SHORT INT INT16 INT32 INT64 INTPTR LONG LONG_LONG FLOAT DOUBLE).each do |type| - name = :"#{type}_ALIGNMENT" - const_set(name, MemoryViewTestUtils.const_get(name)) - end - - def test_rb_memory_view_register_duplicated - assert_warning(/Duplicated registration of memory view to/) do - MemoryViewTestUtils.register(MemoryViewTestUtils::ExportableString) - end - end - - def test_rb_memory_view_register_nonclass - assert_raise(TypeError) do - MemoryViewTestUtils.register(Object.new) - end - end - - def sizeof(type) - RbConfig::SIZEOF[type.to_s] - end - - def test_rb_memory_view_item_size_from_format - [ - [nil, 1], ['c', 1], ['C', 1], - ['n', 2], ['v', 2], - ['l', 4], ['L', 4], ['N', 4], ['V', 4], ['f', 4], ['e', 4], ['g', 4], - ['q', 8], ['Q', 8], ['d', 8], ['E', 8], ['G', 8], - ['s', sizeof(:short)], ['S', sizeof(:short)], ['s!', sizeof(:short)], ['S!', sizeof(:short)], - ['i', sizeof(:int)], ['I', sizeof(:int)], ['i!', sizeof(:int)], ['I!', sizeof(:int)], - ['l!', sizeof(:long)], ['L!', sizeof(:long)], - ['q!', sizeof('long long')], ['Q!', sizeof('long long')], - ['j', sizeof(:intptr_t)], ['J', sizeof(:intptr_t)], - ].each do |format, expected| - actual, err = MemoryViewTestUtils.item_size_from_format(format) - assert_nil(err) - assert_equal(expected, actual, "rb_memory_view_item_size_from_format(#{format || 'NULL'}) == #{expected}") - end - end - - def test_rb_memory_view_item_size_from_format_composed - actual, = MemoryViewTestUtils.item_size_from_format("ccc") - assert_equal(3, actual) - - actual, = MemoryViewTestUtils.item_size_from_format("c3") - assert_equal(3, actual) - - actual, = MemoryViewTestUtils.item_size_from_format("fd") - assert_equal(12, actual) - - actual, = MemoryViewTestUtils.item_size_from_format("fx2d") - assert_equal(14, actual) - end - - def test_rb_memory_view_item_size_from_format_with_spaces - # spaces should be ignored - actual, = MemoryViewTestUtils.item_size_from_format("f x2 d") - assert_equal(14, actual) - end - - def test_rb_memory_view_item_size_from_format_error - assert_equal([-1, "a"], MemoryViewTestUtils.item_size_from_format("ccca")) - assert_equal([-1, "a"], MemoryViewTestUtils.item_size_from_format("ccc4a")) - end - - def test_rb_memory_view_parse_item_format - total_size, members, err = MemoryViewTestUtils.parse_item_format("ccc2f3x2d4q!<") - assert_equal(58, total_size) - assert_nil(err) - assert_equal([ - {format: 'c', native_size_p: false, endianness: NATIVE_ENDIAN, offset: 0, size: 1, repeat: 1}, - {format: 'c', native_size_p: false, endianness: NATIVE_ENDIAN, offset: 1, size: 1, repeat: 1}, - {format: 'c', native_size_p: false, endianness: NATIVE_ENDIAN, offset: 2, size: 1, repeat: 2}, - {format: 'f', native_size_p: false, endianness: NATIVE_ENDIAN, offset: 4, size: 4, repeat: 3}, - {format: 'd', native_size_p: false, endianness: NATIVE_ENDIAN, offset: 18, size: 8, repeat: 4}, - {format: 'q', native_size_p: true, endianness: :little_endian, offset: 50, size: sizeof('long long'), repeat: 1} - ], - members) - end - - def test_rb_memory_view_parse_item_format_with_alignment_signle - [ - ["c", false, NATIVE_ENDIAN, 1, 1, 1], - ["C", false, NATIVE_ENDIAN, 1, 1, 1], - ["s", false, NATIVE_ENDIAN, SHORT_ALIGNMENT, sizeof(:short), 1], - ["S", false, NATIVE_ENDIAN, SHORT_ALIGNMENT, sizeof(:short), 1], - ["s!", true, NATIVE_ENDIAN, SHORT_ALIGNMENT, sizeof(:short), 1], - ["S!", true, NATIVE_ENDIAN, SHORT_ALIGNMENT, sizeof(:short), 1], - ["n", false, :big_endian, INT16_ALIGNMENT, sizeof(:int16_t), 1], - ["v", false, :little_endian, INT16_ALIGNMENT, sizeof(:int16_t), 1], - ["i", false, NATIVE_ENDIAN, INT_ALIGNMENT, sizeof(:int), 1], - ["I", false, NATIVE_ENDIAN, INT_ALIGNMENT, sizeof(:int), 1], - ["i!", true, NATIVE_ENDIAN, INT_ALIGNMENT, sizeof(:int), 1], - ["I!", true, NATIVE_ENDIAN, INT_ALIGNMENT, sizeof(:int), 1], - ["l", false, NATIVE_ENDIAN, INT32_ALIGNMENT, sizeof(:int32_t), 1], - ["L", false, NATIVE_ENDIAN, INT32_ALIGNMENT, sizeof(:int32_t), 1], - ["l!", true, NATIVE_ENDIAN, LONG_ALIGNMENT, sizeof(:long), 1], - ["L!", true, NATIVE_ENDIAN, LONG_ALIGNMENT, sizeof(:long), 1], - ["N", false, :big_endian, INT32_ALIGNMENT, sizeof(:int32_t), 1], - ["V", false, :little_endian, INT32_ALIGNMENT, sizeof(:int32_t), 1], - ["f", false, NATIVE_ENDIAN, FLOAT_ALIGNMENT, sizeof(:float), 1], - ["e", false, :little_endian, FLOAT_ALIGNMENT, sizeof(:float), 1], - ["g", false, :big_endian, FLOAT_ALIGNMENT, sizeof(:float), 1], - ["q", false, NATIVE_ENDIAN, INT64_ALIGNMENT, sizeof(:int64_t), 1], - ["Q", false, NATIVE_ENDIAN, INT64_ALIGNMENT, sizeof(:int64_t), 1], - ["q!", true, NATIVE_ENDIAN, LONG_LONG_ALIGNMENT, sizeof("long long"), 1], - ["Q!", true, NATIVE_ENDIAN, LONG_LONG_ALIGNMENT, sizeof("long long"), 1], - ["d", false, NATIVE_ENDIAN, DOUBLE_ALIGNMENT, sizeof(:double), 1], - ["E", false, :little_endian, DOUBLE_ALIGNMENT, sizeof(:double), 1], - ["G", false, :big_endian, DOUBLE_ALIGNMENT, sizeof(:double), 1], - ["j", false, NATIVE_ENDIAN, INTPTR_ALIGNMENT, sizeof(:intptr_t), 1], - ["J", false, NATIVE_ENDIAN, INTPTR_ALIGNMENT, sizeof(:intptr_t), 1], - ].each do |type, native_size_p, endianness, alignment, size, repeat, total_size| - total_size, members, err = MemoryViewTestUtils.parse_item_format("|c#{type}") - assert_nil(err) - - padding_size = alignment - 1 - expected_total_size = 1 + padding_size + size - assert_equal(expected_total_size, total_size) - - expected_result = [ - {format: 'c', native_size_p: false, endianness: NATIVE_ENDIAN, offset: 0, size: 1, repeat: 1}, - {format: type[0], native_size_p: native_size_p, endianness: endianness, offset: alignment, size: size, repeat: repeat}, - ] - assert_equal(expected_result, members) - end - end - - def alignment_padding(total_size, alignment) - res = total_size % alignment - if res > 0 - alignment - res - else - 0 - end - end - - def test_rb_memory_view_parse_item_format_with_alignment_total_size_with_tail_padding - total_size, _members, err = MemoryViewTestUtils.parse_item_format("|lqc") - assert_nil(err) - - expected_total_size = sizeof(:int32_t) - expected_total_size += alignment_padding(expected_total_size, INT32_ALIGNMENT) - expected_total_size += sizeof(:int64_t) - expected_total_size += alignment_padding(expected_total_size, INT64_ALIGNMENT) - expected_total_size += 1 - expected_total_size += alignment_padding(expected_total_size, INT64_ALIGNMENT) - assert_equal(expected_total_size, total_size) - end - - def test_rb_memory_view_parse_item_format_with_alignment_compound - total_size, members, err = MemoryViewTestUtils.parse_item_format("|ccc2f3x2d4cq!<") - assert_nil(err) - - expected_total_size = 1 + 1 + 1*2 - expected_total_size += alignment_padding(expected_total_size, FLOAT_ALIGNMENT) - expected_total_size += sizeof(:float)*3 + 1*2 - expected_total_size += alignment_padding(expected_total_size, DOUBLE_ALIGNMENT) - expected_total_size += sizeof(:double)*4 + 1 - expected_total_size += alignment_padding(expected_total_size, LONG_LONG_ALIGNMENT) - expected_total_size += sizeof("long long") - assert_equal(expected_total_size, total_size) - - expected_result = [ - {format: 'c', native_size_p: false, endianness: NATIVE_ENDIAN, offset: 0, size: 1, repeat: 1}, - {format: 'c', native_size_p: false, endianness: NATIVE_ENDIAN, offset: 1, size: 1, repeat: 1}, - {format: 'c', native_size_p: false, endianness: NATIVE_ENDIAN, offset: 2, size: 1, repeat: 2}, - ] - offset = 4 - - res = offset % FLOAT_ALIGNMENT - offset += FLOAT_ALIGNMENT - res if res > 0 - expected_result << {format: 'f', native_size_p: false, endianness: NATIVE_ENDIAN, offset: offset, size: 4, repeat: 3} - offset += 12 - - offset += 2 # 2x - - res = offset % DOUBLE_ALIGNMENT - offset += DOUBLE_ALIGNMENT - res if res > 0 - expected_result << {format: 'd', native_size_p: false, endianness: NATIVE_ENDIAN, offset: offset, size: 8, repeat: 4} - offset += 32 - - expected_result << {format: 'c', native_size_p: false, endianness: NATIVE_ENDIAN, offset: offset, size: 1, repeat: 1} - offset += 1 - - res = offset % LONG_LONG_ALIGNMENT - offset += LONG_LONG_ALIGNMENT - res if res > 0 - expected_result << {format: 'q', native_size_p: true, endianness: :little_endian, offset: offset, size: 8, repeat: 1} - - assert_equal(expected_result, members) - end - - def test_rb_memory_view_extract_item_members - m = MemoryViewTestUtils - assert_equal(1, m.extract_item_members([1].pack("c"), "c")) - assert_equal([1, 2], m.extract_item_members([1, 2].pack("ii"), "ii")) - assert_equal([1, 2, 3], m.extract_item_members([1, 2, 3].pack("cls"), "cls")) - end - - def test_rb_memory_view_extract_item_members_endianness - m = MemoryViewTestUtils - assert_equal([0x0102, 0x0304], m.extract_item_members([1, 2, 3, 4].pack("c*"), "S>2")) - assert_equal([0x0102, 0x0304], m.extract_item_members([1, 2, 3, 4].pack("c*"), "n2")) - assert_equal([0x0201, 0x0403], m.extract_item_members([1, 2, 3, 4].pack("c*"), "S<2")) - assert_equal([0x0201, 0x0403], m.extract_item_members([1, 2, 3, 4].pack("c*"), "v2")) - assert_equal(0x01020304, m.extract_item_members([1, 2, 3, 4].pack("c*"), "L>")) - assert_equal(0x01020304, m.extract_item_members([1, 2, 3, 4].pack("c*"), "N")) - assert_equal(0x04030201, m.extract_item_members([1, 2, 3, 4].pack("c*"), "L<")) - assert_equal(0x04030201, m.extract_item_members([1, 2, 3, 4].pack("c*"), "V")) - assert_equal(0x0102030405060708, m.extract_item_members([1, 2, 3, 4, 5, 6, 7, 8].pack("c*"), "Q>")) - assert_equal(0x0807060504030201, m.extract_item_members([1, 2, 3, 4, 5, 6, 7, 8].pack("c*"), "Q<")) - end - - def test_rb_memory_view_extract_item_members_float - m = MemoryViewTestUtils - packed = [1.23].pack("f") - assert_equal(packed.unpack("f")[0], m.extract_item_members(packed, "f")) - end - - def test_rb_memory_view_extract_item_members_float_endianness - m = MemoryViewTestUtils - hi, lo = [1.23].pack("f").unpack("L")[0].divmod(0x10000) - packed = [lo, hi].pack("S*") - assert_equal(packed.unpack("e")[0], m.extract_item_members(packed, "e")) - packed = [hi, lo].pack("S*") - assert_equal(packed.unpack("g")[0], m.extract_item_members(packed, "g")) - end - - def test_rb_memory_view_extract_item_members_doble - m = MemoryViewTestUtils - packed = [1.23].pack("d") - assert_equal(1.23, m.extract_item_members(packed, "d")) - end - - def test_rb_memory_view_extract_item_members_doble_endianness - m = MemoryViewTestUtils - hi, lo = [1.23].pack("d").unpack("Q")[0].divmod(0x10000) - packed = [lo, hi].pack("L*") - assert_equal(packed.unpack("E")[0], m.extract_item_members(packed, "E")) - packed = [hi, lo].pack("L*") - assert_equal(packed.unpack("G")[0], m.extract_item_members(packed, "G")) - end - - def test_rb_memory_view_available_p - es = MemoryViewTestUtils::ExportableString.new("ruby") - assert_equal(true, MemoryViewTestUtils.available?(es)) - es = MemoryViewTestUtils::ExportableString.new(nil) - assert_equal(false, MemoryViewTestUtils.available?(es)) - end - - def test_ref_count_with_exported_object - es = MemoryViewTestUtils::ExportableString.new("ruby") - assert_equal(1, MemoryViewTestUtils.ref_count_while_exporting(es, 1)) - assert_equal(2, MemoryViewTestUtils.ref_count_while_exporting(es, 2)) - assert_equal(10, MemoryViewTestUtils.ref_count_while_exporting(es, 10)) - assert_nil(MemoryViewTestUtils.ref_count_while_exporting(es, 0)) - end - - def test_rb_memory_view_init_as_byte_array - # ExportableString's memory view is initialized by rb_memory_view_init_as_byte_array - es = MemoryViewTestUtils::ExportableString.new("ruby") - memory_view_info = MemoryViewTestUtils.get_memory_view_info(es) - assert_equal({ - obj: es, - byte_size: 4, - readonly: true, - format: nil, - item_size: 1, - ndim: 1, - shape: nil, - strides: nil, - sub_offsets: nil - }, - memory_view_info) - end - - def test_rb_memory_view_get_with_memory_view_unavailable_object - es = MemoryViewTestUtils::ExportableString.new(nil) - memory_view_info = MemoryViewTestUtils.get_memory_view_info(es) - assert_nil(memory_view_info) - end - - def test_rb_memory_view_fill_contiguous_strides - row_major_strides = MemoryViewTestUtils.fill_contiguous_strides(3, 8, [2, 3, 4], true) - assert_equal([96, 32, 8], - row_major_strides) - - column_major_strides = MemoryViewTestUtils.fill_contiguous_strides(3, 8, [2, 3, 4], false) - assert_equal([8, 16, 48], - column_major_strides) - end - - def test_rb_memory_view_get_item_pointer_single_member - buf = [ 1, 2, 3, 4, - 5, 6, 7, 8, - 9, 10, 11, 12 ].pack("l!*") - shape = [3, 4] - mv = MemoryViewTestUtils::MultiDimensionalView.new(buf, "l!", shape, nil) - assert_equal(1, mv[[0, 0]]) - assert_equal(4, mv[[0, 3]]) - assert_equal(6, mv[[1, 1]]) - assert_equal(10, mv[[2, 1]]) - end - - def test_rb_memory_view_get_item_pointer_multiple_members - buf = [ 1, 2, 3, 4, 5, 6, 7, 8, - -1, -2, -3, -4, -5, -6, -7, -8].pack("s*") - shape = [2, 4] - strides = [4*sizeof(:short)*2, sizeof(:short)*2] - mv = MemoryViewTestUtils::MultiDimensionalView.new(buf, "ss", shape, strides) - assert_equal([1, 2], mv[[0, 0]]) - assert_equal([5, 6], mv[[0, 2]]) - assert_equal([-1, -2], mv[[1, 0]]) - assert_equal([-7, -8], mv[[1, 3]]) - end - - def test_ractor - assert_in_out_err([], <<-"end;", ["[5, 6]", "[-7, -8]"], []) - require "-test-/memory_view" - require "rbconfig/sizeof" - $VERBOSE = nil - r = Ractor.new RbConfig::SIZEOF["short"] do |sizeof_short| - buf = [ 1, 2, 3, 4, 5, 6, 7, 8, - -1, -2, -3, -4, -5, -6, -7, -8].pack("s*") - shape = [2, 4] - strides = [4*sizeof_short*2, sizeof_short*2] - mv = MemoryViewTestUtils::MultiDimensionalView.new(buf, "ss", shape, strides) - p mv[[0, 2]] - mv[[1, 3]] - end - p r.take - end; - end -end diff --git a/test/ruby/test_method.rb b/test/ruby/test_method.rb index 3dfab84e93..77273dade5 100644 --- a/test/ruby/test_method.rb +++ b/test/ruby/test_method.rb @@ -5,6 +5,7 @@ require 'test/unit' class TestMethod < Test::Unit::TestCase def setup @verbose = $VERBOSE + $VERBOSE = nil end def teardown @@ -21,7 +22,6 @@ class TestMethod < Test::Unit::TestCase def mo5(a, *b, c) end def mo6(a, *b, c, &d) end def mo7(a, b = nil, *c, d, &e) end - def mo8(a, b = nil, *, d, &e) end def ma1((a), &b) nil && a end def mk1(**) end def mk2(**o) nil && o end @@ -30,9 +30,6 @@ class TestMethod < Test::Unit::TestCase def mk5(a, b = nil, **o) nil && o end def mk6(a, b = nil, c, **o) nil && o end def mk7(a, b = nil, *c, d, **o) nil && o end - def mk8(a, b = nil, *c, d, e:, f: nil, **o) nil && o end - def mnk(**nil) end - def mf(...) end class Base def foo() :base end @@ -103,12 +100,6 @@ class TestMethod < Test::Unit::TestCase assert_raise(TypeError) do um.bind(Base.new) end - - # cleanup - Derived.class_eval do - remove_method :foo - def foo() :derived; end - end end def test_callee @@ -441,51 +432,32 @@ class TestMethod < Test::Unit::TestCase def test_inspect o = Object.new - def o.foo; end; line_no = __LINE__ + def o.foo; end m = o.method(:foo) - assert_equal("#<Method: #{ o.inspect }.foo() #{__FILE__}:#{line_no}>", m.inspect) + assert_equal("#<Method: #{ o.inspect }.foo>", m.inspect) m = o.method(:foo) - assert_match("#<UnboundMethod: #{ class << o; self; end.inspect }#foo() #{__FILE__}:#{line_no}", m.unbind.inspect) + assert_equal("#<UnboundMethod: #{ class << o; self; end.inspect }#foo>", m.unbind.inspect) c = Class.new - c.class_eval { def foo; end; }; line_no = __LINE__ + c.class_eval { def foo; end; } m = c.new.method(:foo) - assert_equal("#<Method: #{ c.inspect }#foo() #{__FILE__}:#{line_no}>", m.inspect) + assert_equal("#<Method: #{ c.inspect }#foo>", m.inspect) m = c.instance_method(:foo) - assert_equal("#<UnboundMethod: #{ c.inspect }#foo() #{__FILE__}:#{line_no}>", m.inspect) + assert_equal("#<UnboundMethod: #{ c.inspect }#foo>", m.inspect) c2 = Class.new(c) c2.class_eval { private :foo } m2 = c2.new.method(:foo) - assert_equal("#<Method: #{ c2.inspect }(#{ c.inspect })#foo() #{__FILE__}:#{line_no}>", m2.inspect) + assert_equal("#<Method: #{ c2.inspect }(#{ c.inspect })#foo>", m2.inspect) bug7806 = '[ruby-core:52048] [Bug #7806]' c3 = Class.new(c) c3.class_eval { alias bar foo } m3 = c3.new.method(:bar) - assert_equal("#<Method: #{c3.inspect}(#{c.inspect})#bar(foo)() #{__FILE__}:#{line_no}>", m3.inspect, bug7806) - - bug15608 = '[ruby-core:91570] [Bug #15608]' - c4 = Class.new(c) - c4.class_eval { alias bar foo } - o = c4.new - o.singleton_class - m4 = o.method(:bar) - assert_equal("#<Method: #{c4.inspect}(#{c.inspect})#bar(foo)() #{__FILE__}:#{line_no}>", m4.inspect, bug15608) - - bug17428 = '[ruby-core:101635] [Bug #17428]' - c4 = Class.new(c) - c4.class_eval { alias bar foo } - o = c4.new - o.singleton_class - m4 = o.method(:bar) - assert_equal("#<Method: #<Class:String>(Module)#prepend(*)>", String.method(:prepend).inspect, bug17428) - - c5 = Class.new(String) - m = Module.new{def prepend; end; alias prep prepend}; line_no = __LINE__ - c5.extend(m) - c6 = Class.new(c5) - assert_equal("#<Method: #<Class:#{c6.inspect}>(#{m.inspect})#prep(prepend)() #{__FILE__}:#{line_no}>", c6.method(:prep).inspect, bug17428) + assert_equal("#<Method: #{c3.inspect}(#{c.inspect})#bar(foo)>", m3.inspect, bug7806) + + m.taint + assert_predicate(m.inspect, :tainted?, "inspect result should be infected") end def test_callee_top_level @@ -523,22 +495,6 @@ class TestMethod < Test::Unit::TestCase assert_include mmethods, :meth, 'normal methods are public by default' end - def test_respond_to_missing_argument - obj = Struct.new(:mid).new - def obj.respond_to_missing?(id, *) - self.mid = id - true - end - assert_kind_of(Method, obj.method("bug15640")) - assert_kind_of(Symbol, obj.mid) - assert_equal("bug15640", obj.mid.to_s) - - arg = Struct.new(:to_str).new("bug15640_2") - assert_kind_of(Method, obj.method(arg)) - assert_kind_of(Symbol, obj.mid) - assert_equal("bug15640_2", obj.mid.to_s) - end - define_method(:pm0) {||} define_method(:pm1) {|a|} define_method(:pm2) {|a, b|} @@ -557,8 +513,6 @@ class TestMethod < Test::Unit::TestCase define_method(:pmk5) {|a, b = nil, **o|} define_method(:pmk6) {|a, b = nil, c, **o|} define_method(:pmk7) {|a, b = nil, *c, d, **o|} - define_method(:pmk8) {|a, b = nil, *c, d, e:, f: nil, **o|} - define_method(:pmnk) {|**nil|} def test_bound_parameters assert_equal([], method(:m0).parameters) @@ -571,7 +525,6 @@ class TestMethod < Test::Unit::TestCase assert_equal([[:req, :a], [:rest, :b], [:req, :c]], method(:mo5).parameters) assert_equal([[:req, :a], [:rest, :b], [:req, :c], [:block, :d]], method(:mo6).parameters) assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:block, :e]], method(:mo7).parameters) - assert_equal([[:req, :a], [:opt, :b], [:rest], [:req, :d], [:block, :e]], method(:mo8).parameters) assert_equal([[:req], [:block, :b]], method(:ma1).parameters) assert_equal([[:keyrest]], method(:mk1).parameters) assert_equal([[:keyrest, :o]], method(:mk2).parameters) @@ -580,10 +533,6 @@ class TestMethod < Test::Unit::TestCase assert_equal([[:req, :a], [:opt, :b], [:keyrest, :o]], method(:mk5).parameters) assert_equal([[:req, :a], [:opt, :b], [:req, :c], [:keyrest, :o]], method(:mk6).parameters) assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:keyrest, :o]], method(:mk7).parameters) - assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:keyreq, :e], [:key, :f], [:keyrest, :o]], method(:mk8).parameters) - assert_equal([[:nokey]], method(:mnk).parameters) - # pending - assert_equal([[:rest, :*], [:block, :&]], method(:mf).parameters) end def test_unbound_parameters @@ -597,7 +546,6 @@ class TestMethod < Test::Unit::TestCase assert_equal([[:req, :a], [:rest, :b], [:req, :c]], self.class.instance_method(:mo5).parameters) assert_equal([[:req, :a], [:rest, :b], [:req, :c], [:block, :d]], self.class.instance_method(:mo6).parameters) assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:block, :e]], self.class.instance_method(:mo7).parameters) - assert_equal([[:req, :a], [:opt, :b], [:rest], [:req, :d], [:block, :e]], self.class.instance_method(:mo8).parameters) assert_equal([[:req], [:block, :b]], self.class.instance_method(:ma1).parameters) assert_equal([[:keyrest]], self.class.instance_method(:mk1).parameters) assert_equal([[:keyrest, :o]], self.class.instance_method(:mk2).parameters) @@ -606,10 +554,6 @@ class TestMethod < Test::Unit::TestCase assert_equal([[:req, :a], [:opt, :b], [:keyrest, :o]], self.class.instance_method(:mk5).parameters) assert_equal([[:req, :a], [:opt, :b], [:req, :c], [:keyrest, :o]], self.class.instance_method(:mk6).parameters) assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:keyrest, :o]], self.class.instance_method(:mk7).parameters) - assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:keyreq, :e], [:key, :f], [:keyrest, :o]], self.class.instance_method(:mk8).parameters) - assert_equal([[:nokey]], self.class.instance_method(:mnk).parameters) - # pending - assert_equal([[:rest, :*], [:block, :&]], self.class.instance_method(:mf).parameters) end def test_bmethod_bound_parameters @@ -631,8 +575,6 @@ class TestMethod < Test::Unit::TestCase assert_equal([[:req, :a], [:opt, :b], [:keyrest, :o]], method(:pmk5).parameters) assert_equal([[:req, :a], [:opt, :b], [:req, :c], [:keyrest, :o]], method(:pmk6).parameters) assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:keyrest, :o]], method(:pmk7).parameters) - assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:keyreq, :e], [:key, :f], [:keyrest, :o]], method(:pmk8).parameters) - assert_equal([[:nokey]], method(:pmnk).parameters) end def test_bmethod_unbound_parameters @@ -655,8 +597,6 @@ class TestMethod < Test::Unit::TestCase assert_equal([[:req, :a], [:opt, :b], [:keyrest, :o]], self.class.instance_method(:pmk5).parameters) assert_equal([[:req, :a], [:opt, :b], [:req, :c], [:keyrest, :o]], self.class.instance_method(:pmk6).parameters) assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:keyrest, :o]], self.class.instance_method(:pmk7).parameters) - assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:keyreq, :e], [:key, :f], [:keyrest, :o]], self.class.instance_method(:pmk8).parameters) - assert_equal([[:nokey]], self.class.instance_method(:pmnk).parameters) end def test_hidden_parameters @@ -664,56 +604,6 @@ class TestMethod < Test::Unit::TestCase assert_empty(method(:m).parameters.map{|_,n|n}.compact) end - def test_method_parameters_inspect - assert_include(method(:m0).inspect, "()") - assert_include(method(:m1).inspect, "(a)") - assert_include(method(:m2).inspect, "(a, b)") - assert_include(method(:mo1).inspect, "(a=..., &b)") - assert_include(method(:mo2).inspect, "(a, b=...)") - assert_include(method(:mo3).inspect, "(*a)") - assert_include(method(:mo4).inspect, "(a, *b, &c)") - assert_include(method(:mo5).inspect, "(a, *b, c)") - assert_include(method(:mo6).inspect, "(a, *b, c, &d)") - assert_include(method(:mo7).inspect, "(a, b=..., *c, d, &e)") - assert_include(method(:mo8).inspect, "(a, b=..., *, d, &e)") - assert_include(method(:ma1).inspect, "(_, &b)") - assert_include(method(:mk1).inspect, "(**)") - assert_include(method(:mk2).inspect, "(**o)") - assert_include(method(:mk3).inspect, "(a, **o)") - assert_include(method(:mk4).inspect, "(a=..., **o)") - assert_include(method(:mk5).inspect, "(a, b=..., **o)") - assert_include(method(:mk6).inspect, "(a, b=..., c, **o)") - assert_include(method(:mk7).inspect, "(a, b=..., *c, d, **o)") - assert_include(method(:mk8).inspect, "(a, b=..., *c, d, e:, f: ..., **o)") - assert_include(method(:mnk).inspect, "(**nil)") - assert_include(method(:mf).inspect, "(...)") - end - - def test_unbound_method_parameters_inspect - assert_include(self.class.instance_method(:m0).inspect, "()") - assert_include(self.class.instance_method(:m1).inspect, "(a)") - assert_include(self.class.instance_method(:m2).inspect, "(a, b)") - assert_include(self.class.instance_method(:mo1).inspect, "(a=..., &b)") - assert_include(self.class.instance_method(:mo2).inspect, "(a, b=...)") - assert_include(self.class.instance_method(:mo3).inspect, "(*a)") - assert_include(self.class.instance_method(:mo4).inspect, "(a, *b, &c)") - assert_include(self.class.instance_method(:mo5).inspect, "(a, *b, c)") - assert_include(self.class.instance_method(:mo6).inspect, "(a, *b, c, &d)") - assert_include(self.class.instance_method(:mo7).inspect, "(a, b=..., *c, d, &e)") - assert_include(self.class.instance_method(:mo8).inspect, "(a, b=..., *, d, &e)") - assert_include(self.class.instance_method(:ma1).inspect, "(_, &b)") - assert_include(self.class.instance_method(:mk1).inspect, "(**)") - assert_include(self.class.instance_method(:mk2).inspect, "(**o)") - assert_include(self.class.instance_method(:mk3).inspect, "(a, **o)") - assert_include(self.class.instance_method(:mk4).inspect, "(a=..., **o)") - assert_include(self.class.instance_method(:mk5).inspect, "(a, b=..., **o)") - assert_include(self.class.instance_method(:mk6).inspect, "(a, b=..., c, **o)") - assert_include(self.class.instance_method(:mk7).inspect, "(a, b=..., *c, d, **o)") - assert_include(self.class.instance_method(:mk8).inspect, "(a, b=..., *c, d, e:, f: ..., **o)") - assert_include(self.class.instance_method(:mnk).inspect, "(**nil)") - assert_include(self.class.instance_method(:mf).inspect, "(...)") - end - def test_public_method_with_zsuper_method c = Class.new c.class_eval do @@ -761,8 +651,7 @@ class TestMethod < Test::Unit::TestCase assert_nothing_raised { mv3 } assert_nothing_raised { self.mv1 } - assert_nothing_raised { self.mv2 } - assert_raise(NoMethodError) { (self).mv2 } + assert_raise(NoMethodError) { self.mv2 } assert_nothing_raised { self.mv3 } v = Visibility.new @@ -817,9 +706,7 @@ class TestMethod < Test::Unit::TestCase assert_instance_of String, __dir__ assert_equal(File.dirname(File.realpath(__FILE__)), __dir__) bug8436 = '[ruby-core:55123] [Bug #8436]' - file, line = *binding.source_location - file = File.realpath(file) - assert_equal(__dir__, eval("__dir__", binding, file, line), bug8436) + assert_equal(__dir__, eval("__dir__", binding), bug8436) bug8662 = '[ruby-core:56099] [Bug #8662]' assert_equal("arbitrary", eval("__dir__", binding, "arbitrary/file.rb"), bug8662) assert_equal("arbitrary", Object.new.instance_eval("__dir__", "arbitrary/file.rb"), bug8662) @@ -841,7 +728,7 @@ class TestMethod < Test::Unit::TestCase assert_equal(c, c.instance_method(:foo).owner) assert_equal(c, x.method(:foo).owner) assert_equal(x.singleton_class, x.method(:bar).owner) - assert_equal(x.method(:foo), x.method(:bar), bug7613) + assert_not_equal(x.method(:foo), x.method(:bar), bug7613) assert_equal(c, x.method(:zot).owner, bug7993) assert_equal(c, c.instance_method(:zot).owner, bug7993) end @@ -1020,36 +907,6 @@ class TestMethod < Test::Unit::TestCase assert_nil(m.super_method) end - def test_super_method_bind_unbind_clone - bug15629_m1 = Module.new do - def foo; end - end - - bug15629_m2 = Module.new do - def foo; end - end - - bug15629_c = Class.new do - include bug15629_m1 - include bug15629_m2 - end - - o = bug15629_c.new - m = o.method(:foo) - sm = m.super_method - im = bug15629_c.instance_method(:foo) - sim = im.super_method - - assert_equal(sm, m.clone.super_method) - assert_equal(sim, m.unbind.super_method) - assert_equal(sim, m.unbind.clone.super_method) - assert_equal(sim, im.clone.super_method) - assert_equal(sm, m.unbind.bind(o).super_method) - assert_equal(sm, m.unbind.clone.bind(o).super_method) - assert_equal(sm, im.bind(o).super_method) - assert_equal(sm, im.clone.bind(o).super_method) - end - def test_super_method_removed c1 = Class.new {private def foo; end} c2 = Class.new(c1) {public :foo} @@ -1093,95 +950,11 @@ class TestMethod < Test::Unit::TestCase '[ruby-core:85231] [Bug #14421]' end - def test_super_method_alias - c0 = Class.new do - def m1 - [:C0_m1] - end - def m2 - [:C0_m2] - end - end - - c1 = Class.new(c0) do - def m1 - [:C1_m1] + super - end - alias m2 m1 - end - - c2 = Class.new(c1) do - def m2 - [:C2_m2] + super - end - end - o1 = c2.new - assert_equal([:C2_m2, :C1_m1, :C0_m1], o1.m2) - - m = o1.method(:m2) - assert_equal([:C2_m2, :C1_m1, :C0_m1], m.call) - - m = m.super_method - assert_equal([:C1_m1, :C0_m1], m.call) - - m = m.super_method - assert_equal([:C0_m1], m.call) - - assert_nil(m.super_method) - end - - def test_super_method_alias_to_prepended_module - m = Module.new do - def m1 - [:P_m1] + super - end - - def m2 - [:P_m2] + super - end - end - - c0 = Class.new do - def m1 - [:C0_m1] - end - end - - c1 = Class.new(c0) do - def m1 - [:C1_m1] + super - end - prepend m - alias m2 m1 - end - - o1 = c1.new - assert_equal([:P_m2, :P_m1, :C1_m1, :C0_m1], o1.m2) - - m = o1.method(:m2) - assert_equal([:P_m2, :P_m1, :C1_m1, :C0_m1], m.call) - - m = m.super_method - assert_equal([:P_m1, :C1_m1, :C0_m1], m.call) - - m = m.super_method - assert_equal([:C1_m1, :C0_m1], m.call) - - m = m.super_method - assert_equal([:C0_m1], m.call) - - assert_nil(m.super_method) - end - def rest_parameter(*rest) rest end def test_splat_long_array - if File.exist?('/etc/os-release') && File.read('/etc/os-release').include?('openSUSE Leap') - # For RubyCI's openSUSE machine http://rubyci.s3.amazonaws.com/opensuseleap/ruby-trunk/recent.html, which tends to die with NoMemoryError here. - skip 'do not exhaust memory on RubyCI openSUSE Leap machine' - end n = 10_000_000 assert_equal n , rest_parameter(*(1..n)).size, '[Feature #10440]' end @@ -1209,22 +982,17 @@ class TestMethod < Test::Unit::TestCase assert_equal([:bar, :foo], b.local_variables.sort, bug11012) end - MethodInMethodClass_Setup = -> do - remove_const :MethodInMethodClass if defined? MethodInMethodClass - - class MethodInMethodClass - def m1 - def m2 - end - self.class.send(:define_method, :m3){} # [Bug #11754] + class MethodInMethodClass + def m1 + def m2 end - private + + self.class.send(:define_method, :m3){} # [Bug #11754] end + private end def test_method_in_method_visibility_should_be_public - MethodInMethodClass_Setup.call - assert_equal([:m1].sort, MethodInMethodClass.public_instance_methods(false).sort) assert_equal([].sort, MethodInMethodClass.private_instance_methods(false).sort) @@ -1274,135 +1042,8 @@ class TestMethod < Test::Unit::TestCase assert_separately [], "RubyVM::InstructionSequence.compile_option = {trace_instruction: false}\n" + body end - def test_zsuper_private_override_instance_method - assert_separately(%w(--disable-gems), <<-'end;', timeout: 30) - # Bug #16942 [ruby-core:98691] - module M - def x - end - end - - module M2 - prepend Module.new - include M - private :x - end - - ::Object.prepend(M2) - - m = Object.instance_method(:x) - assert_equal M, m.owner - end; - end - def test_eqq assert_operator(0.method(:<), :===, 5) assert_not_operator(0.method(:<), :===, -5) end - - def test_compose_with_method - c = Class.new { - def f(x) x * 2 end - def g(x) x + 1 end - } - f = c.new.method(:f) - g = c.new.method(:g) - - assert_equal(6, (f << g).call(2)) - assert_equal(6, (g >> f).call(2)) - end - - def test_compose_with_proc - c = Class.new { - def f(x) x * 2 end - } - f = c.new.method(:f) - g = proc {|x| x + 1} - - assert_equal(6, (f << g).call(2)) - assert_equal(6, (g >> f).call(2)) - end - - def test_compose_with_callable - c = Class.new { - def f(x) x * 2 end - } - c2 = Class.new { - def call(x) x + 1 end - } - f = c.new.method(:f) - g = c2.new - - assert_equal(6, (f << g).call(2)) - assert_equal(5, (f >> g).call(2)) - end - - def test_compose_with_noncallable - c = Class.new { - def f(x) x * 2 end - } - f = c.new.method(:f) - - assert_raise(TypeError) { - f << 5 - } - assert_raise(TypeError) { - f >> 5 - } - end - - def test_umethod_bind_call - foo = Base.instance_method(:foo) - assert_equal(:base, foo.bind_call(Base.new)) - assert_equal(:base, foo.bind_call(Derived.new)) - - plus = Integer.instance_method(:+) - assert_equal(3, plus.bind_call(1, 2)) - end - - def test_method_list - # chkbuild lists all methods. - # The following code emulate this listing. - - # use_symbol = Object.instance_methods[0].is_a?(Symbol) - nummodule = nummethod = 0 - mods = [] - ObjectSpace.each_object(Module) {|m| mods << m if m.name } - mods = mods.sort_by {|m| m.name } - mods.each {|mod| - nummodule += 1 - mc = mod.kind_of?(Class) ? "class" : "module" - puts_line = "#{mc} #{mod.name} #{(mod.ancestors - [mod]).inspect}" - puts_line = puts_line # prevent unused var warning - mod.singleton_methods(false).sort.each {|methname| - nummethod += 1 - meth = mod.method(methname) - line = "#{mod.name}.#{methname} #{meth.arity}" - line << " not-implemented" if !mod.respond_to?(methname) - # puts line - } - ms = mod.instance_methods(false) - if true or use_symbol - ms << :initialize if mod.private_instance_methods(false).include? :initialize - else - ms << "initialize" if mod.private_instance_methods(false).include? "initialize" - end - - ms.sort.each {|methname| - nummethod += 1 - meth = mod.instance_method(methname) - line = "#{mod.name}\##{methname} #{meth.arity}" - line << " not-implemented" if /\(not-implemented\)/ =~ meth.inspect - # puts line - } - } - # puts "#{nummodule} modules, #{nummethod} methods" - - assert_operator nummodule, :>, 0 - assert_operator nummethod, :>, 0 - end - - def test_invalidating_CC_ASAN - assert_ruby_status(['-e', 'using Module.new']) - end end diff --git a/test/ruby/test_method_cache.rb b/test/ruby/test_method_cache.rb deleted file mode 100644 index a8e7e22ae3..0000000000 --- a/test/ruby/test_method_cache.rb +++ /dev/null @@ -1,65 +0,0 @@ -# frozen_string_literal: true -require 'test/unit' - -class TestMethodCache < Test::Unit::TestCase - def test_undef - # clear same - c0 = Class.new do - def foo; end - undef foo - end - - assert_raise(NoMethodError) do - c0.new.foo - end - - c0.class_eval do - def foo; :ok; end - end - - assert_equal :ok, c0.new.foo - end - - def test_undef_with_subclasses - # with subclasses - c0 = Class.new do - def foo; end - undef foo - end - - _c1 = Class.new(c0) - - assert_raise(NoMethodError) do - c0.new.foo - end - - c0.class_eval do - def foo; :ok; end - end - - assert_equal :ok, c0.new.foo - end - - def test_undef_with_subclasses_complicated - c0 = Class.new{ def foo; end } - c1 = Class.new(c0){ undef foo } - c2 = Class.new(c1) - c3 = Class.new(c2) - _c4 = Class.new(c3) - - assert_raise(NoMethodError) do - c3.new.foo - end - - c2.class_eval do - def foo; :c2; end - end - - assert_raise(NoMethodError) do - c1.new.foo - end - - assert_equal :c2, c3.new.foo - end -end - diff --git a/test/ruby/test_module.rb b/test/ruby/test_module.rb index 43f0c51753..076ea0901f 100644 --- a/test/ruby/test_module.rb +++ b/test/ruby/test_module.rb @@ -27,13 +27,11 @@ class TestModule < Test::Unit::TestCase def setup @verbose = $VERBOSE - @deprecated = Warning[:deprecated] - Warning[:deprecated] = true + $VERBOSE = nil end def teardown $VERBOSE = @verbose - Warning[:deprecated] = @deprecated end def test_LT_0 @@ -87,11 +85,8 @@ class TestModule < Test::Unit::TestCase private :user3 end - OtherSetup = -> do - remove_const :Other if defined? ::TestModule::Other - module Other - def other - end + module Other + def other end end @@ -225,8 +220,6 @@ class TestModule < Test::Unit::TestCase @@class_eval = 'b' def test_class_eval - OtherSetup.call - Other.class_eval("CLASS_EVAL = 1") assert_equal(1, Other::CLASS_EVAL) assert_include(Other.constants, :CLASS_EVAL) @@ -301,18 +294,11 @@ class TestModule < Test::Unit::TestCase end def test_nested_get - OtherSetup.call - - assert_equal Other, Object.const_get([self.class, 'Other'].join('::')) + assert_equal Other, Object.const_get([self.class, Other].join('::')) assert_equal User::USER, self.class.const_get([User, 'USER'].join('::')) - assert_raise(NameError) { - Object.const_get([self.class.name, 'String'].join('::')) - } end def test_nested_get_symbol - OtherSetup.call - const = [self.class, Other].join('::').to_sym assert_raise(NameError) {Object.const_get(const)} @@ -339,17 +325,12 @@ class TestModule < Test::Unit::TestCase end def test_nested_defined - OtherSetup.call - assert_send([Object, :const_defined?, [self.class.name, 'Other'].join('::')]) assert_send([self.class, :const_defined?, 'User::USER']) assert_not_send([self.class, :const_defined?, 'User::Foo']) - assert_not_send([Object, :const_defined?, [self.class.name, 'String'].join('::')]) end def test_nested_defined_symbol - OtherSetup.call - const = [self.class, Other].join('::').to_sym assert_raise(NameError) {Object.const_defined?(const)} @@ -357,17 +338,6 @@ class TestModule < Test::Unit::TestCase assert_raise(NameError) {self.class.const_defined?(const)} end - def test_nested_defined_inheritance - assert_send([Object, :const_defined?, [self.class.name, 'User', 'MIXIN'].join('::')]) - assert_send([self.class, :const_defined?, 'User::MIXIN']) - assert_send([Object, :const_defined?, 'File::SEEK_SET']) - - # const_defined? with `false` - assert_not_send([Object, :const_defined?, [self.class.name, 'User', 'MIXIN'].join('::'), false]) - assert_not_send([self.class, :const_defined?, 'User::MIXIN', false]) - assert_not_send([Object, :const_defined?, 'File::SEEK_SET', false]) - end - def test_nested_defined_bad_class assert_raise(TypeError) do self.class.const_defined?('User::USER::Foo') @@ -375,8 +345,6 @@ class TestModule < Test::Unit::TestCase end def test_const_set - OtherSetup.call - assert_not_operator(Other, :const_defined?, :KOALA) Other.const_set(:KOALA, 99) assert_operator(Other, :const_defined?, :KOALA) @@ -435,8 +403,6 @@ class TestModule < Test::Unit::TestCase end def test_dup - OtherSetup.call - bug6454 = '[ruby-core:45132]' a = Module.new @@ -478,139 +444,6 @@ class TestModule < Test::Unit::TestCase assert_raise(ArgumentError) { Module.new { include } } end - def test_prepend_works_with_duped_classes - m = Module.new - a = Class.new do - def b; 2 end - prepend m - end - a2 = a.dup.new - a.class_eval do - alias _b b - def b; 1 end - end - assert_equal(2, a2.b) - end - - def test_gc_prepend_chain - assert_separately([], <<-EOS) - 10000.times { |i| - m1 = Module.new do - def foo; end - end - m2 = Module.new do - prepend m1 - def bar; end - end - m3 = Module.new do - def baz; end - prepend m2 - end - Class.new do - prepend m3 - end - } - GC.start - EOS - end - - def test_refine_module_then_include - assert_separately([], "#{<<~"end;"}\n") - module M - end - class C - include M - end - module RefinementBug - refine M do - def refined_method - :rm - end - end - end - using RefinementBug - - class A - include M - end - - assert_equal(:rm, C.new.refined_method) - end; - end - - def test_include_into_module_already_included - c = Class.new{def foo; [:c] end} - modules = lambda do || - sub = Class.new(c){def foo; [:sc] + super end} - [ - Module.new{def foo; [:m1] + super end}, - Module.new{def foo; [:m2] + super end}, - Module.new{def foo; [:m3] + super end}, - sub, - sub.new - ] - end - - m1, m2, m3, sc, o = modules.call - assert_equal([:sc, :c], o.foo) - sc.include m1 - assert_equal([:sc, :m1, :c], o.foo) - m1.include m2 - assert_equal([:sc, :m1, :m2, :c], o.foo) - m2.include m3 - assert_equal([:sc, :m1, :m2, :m3, :c], o.foo) - - m1, m2, m3, sc, o = modules.call - sc.prepend m1 - assert_equal([:m1, :sc, :c], o.foo) - m1.include m2 - assert_equal([:m1, :m2, :sc, :c], o.foo) - m2.include m3 - assert_equal([:m1, :m2, :m3, :sc, :c], o.foo) - - m1, m2, m3, sc, o = modules.call - sc.include m2 - assert_equal([:sc, :m2, :c], o.foo) - sc.prepend m1 - assert_equal([:m1, :sc, :m2, :c], o.foo) - m1.include m2 - assert_equal([:m1, :sc, :m2, :c], o.foo) - m1.include m3 - assert_equal([:m1, :m3, :sc, :m2, :c], o.foo) - - m1, m2, m3, sc, o = modules.call - sc.include m3 - sc.include m2 - assert_equal([:sc, :m2, :m3, :c], o.foo) - sc.prepend m1 - assert_equal([:m1, :sc, :m2, :m3, :c], o.foo) - m1.include m2 - m1.include m3 - assert_equal([:m1, :sc, :m2, :m3, :c], o.foo) - - m1, m2, m3, sc, o = modules.call - assert_equal([:sc, :c], o.foo) - sc.prepend m1 - assert_equal([:m1, :sc, :c], o.foo) - m1.prepend m2 - assert_equal([:m2, :m1, :sc, :c], o.foo) - m2.prepend m3 - assert_equal([:m3, :m2, :m1, :sc, :c], o.foo) - m1, m2, m3, sc, o = modules.call - sc.include m1 - assert_equal([:sc, :m1, :c], o.foo) - sc.prepend m2 - assert_equal([:m2, :sc, :m1, :c], o.foo) - sc.prepend m3 - assert_equal([:m3, :m2, :sc, :m1, :c], o.foo) - m1, m2, m3, sc, o = modules.call - sc.include m1 - assert_equal([:sc, :m1, :c], o.foo) - m2.prepend m3 - m1.include m2 - assert_equal([:sc, :m1, :m3, :m2, :c], o.foo) - end - def test_included_modules assert_equal([], Mixin.included_modules) assert_equal([Mixin], User.included_modules) @@ -621,26 +454,6 @@ class TestModule < Test::Unit::TestCase assert_equal([Comparable, Kernel], String.included_modules - mixins) end - def test_included_modules_with_prepend - m1 = Module.new - m2 = Module.new - m3 = Module.new - - m2.prepend m1 - m3.include m2 - assert_equal([m1, m2], m3.included_modules) - end - - def test_include_with_prepend - c = Class.new{def m; [:c] end} - p = Module.new{def m; [:p] + super end} - q = Module.new{def m; [:q] + super end; include p} - r = Module.new{def m; [:r] + super end; prepend q} - s = Module.new{def m; [:s] + super end; include r} - a = Class.new(c){def m; [:a] + super end; prepend p; include s} - assert_equal([:p, :a, :s, :q, :r, :c], a.new.m) - end - def test_instance_methods assert_equal([:user, :user2], User.instance_methods(false).sort) assert_equal([:user, :user2, :mixin].sort, User.instance_methods(true).sort) @@ -649,53 +462,26 @@ class TestModule < Test::Unit::TestCase assert_equal([:cClass], (class << CClass; self; end).instance_methods(false)) assert_equal([], (class << BClass; self; end).instance_methods(false)) assert_equal([:cm2], (class << AClass; self; end).instance_methods(false)) + # Ruby 1.8 feature change: + # #instance_methods includes protected methods. + #assert_equal([:aClass], AClass.instance_methods(false)) assert_equal([:aClass, :aClass2], AClass.instance_methods(false).sort) assert_equal([:aClass, :aClass2], (AClass.instance_methods(true) - Object.instance_methods(true)).sort) end def test_method_defined? - [User, Class.new{include User}, Class.new{prepend User}].each do |klass| - [[], [true]].each do |args| - assert !klass.method_defined?(:wombat, *args) - assert klass.method_defined?(:mixin, *args) - assert klass.method_defined?(:user, *args) - assert klass.method_defined?(:user2, *args) - assert !klass.method_defined?(:user3, *args) - - assert !klass.method_defined?("wombat", *args) - assert klass.method_defined?("mixin", *args) - assert klass.method_defined?("user", *args) - assert klass.method_defined?("user2", *args) - assert !klass.method_defined?("user3", *args) - end - end - end + assert !User.method_defined?(:wombat) + assert User.method_defined?(:mixin) + assert User.method_defined?(:user) + assert User.method_defined?(:user2) + assert !User.method_defined?(:user3) - 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) - - User.const_set(:FOO, c = Class.new) - - c.prepend(User) - assert !c.method_defined?(:user, false) - c.define_method(:user){} - assert c.method_defined?(:user, false) - - assert !c.method_defined?(:mixin, false) - c.define_method(:mixin){} - assert c.method_defined?(:mixin, false) - - assert !c.method_defined?(:userx, false) - c.define_method(:userx){} - assert c.method_defined?(:userx, false) - - # cleanup - User.class_eval do - remove_const :FOO - end + assert !User.method_defined?("wombat") + assert User.method_defined?("mixin") + assert User.method_defined?("user") + assert User.method_defined?("user2") + assert !User.method_defined?("user3") end def module_exec_aux @@ -726,14 +512,6 @@ class TestModule < Test::Unit::TestCase def dynamically_added_method_4; end end assert_method_defined?(User, :dynamically_added_method_4) - - # cleanup - User.class_eval do - remove_method :dynamically_added_method_1 - remove_method :dynamically_added_method_2 - remove_method :dynamically_added_method_3 - remove_method :dynamically_added_method_4 - end end def test_module_eval @@ -748,28 +526,6 @@ class TestModule < Test::Unit::TestCase assert_equal("Integer", Integer.name) assert_equal("TestModule::Mixin", Mixin.name) assert_equal("TestModule::User", User.name) - - assert_predicate Integer.name, :frozen? - assert_predicate Mixin.name, :frozen? - assert_predicate User.name, :frozen? - end - - def test_accidental_singleton_naming_with_module - o = Object.new - assert_nil(o.singleton_class.name) - class << o - module Hi; end - end - assert_nil(o.singleton_class.name) - end - - def test_accidental_singleton_naming_with_class - o = Object.new - assert_nil(o.singleton_class.name) - class << o - class Hi; end - end - assert_nil(o.singleton_class.name) end def test_classpath @@ -777,13 +533,13 @@ class TestModule < Test::Unit::TestCase n = Module.new m.const_set(:N, n) assert_nil(m.name) - assert_match(/::N$/, n.name) + assert_nil(n.name) assert_equal([:N], m.constants) m.module_eval("module O end") assert_equal([:N, :O], m.constants.sort) m.module_eval("class C; end") assert_equal([:C, :N, :O], m.constants.sort) - assert_match(/::N$/, m::N.name) + assert_nil(m::N.name) assert_match(/\A#<Module:.*>::O\z/, m::O.name) assert_match(/\A#<Module:.*>::C\z/, m::C.name) self.class.const_set(:M, m) @@ -791,19 +547,12 @@ class TestModule < Test::Unit::TestCase 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) end def test_private_class_method assert_raise(ExpectedException) { AClass.cm1 } assert_raise(ExpectedException) { AClass.cm3 } assert_equal("cm1cm2cm3", AClass.cm2) - - c = Class.new(AClass) - c.class_eval {private_class_method [:cm1, :cm2]} - assert_raise(NoMethodError, /private method/) {c.cm1} - assert_raise(NoMethodError, /private method/) {c.cm2} end def test_private_instance_methods @@ -826,11 +575,6 @@ class TestModule < Test::Unit::TestCase assert_equal("cm1", MyClass.cm1) assert_equal("cm1cm2cm3", MyClass.cm2) assert_raise(ExpectedException) { eval "MyClass.cm3" } - - c = Class.new(AClass) - c.class_eval {public_class_method [:cm1, :cm2]} - assert_equal("cm1", c.cm1) - assert_equal("cm1cm2cm3", c.cm2) end def test_public_instance_methods @@ -838,94 +582,12 @@ class TestModule < Test::Unit::TestCase assert_equal([:bClass1], BClass.public_instance_methods(false)) end - def test_s_public - o = (c = Class.new(AClass)).new - assert_raise(NoMethodError, /private method/) {o.aClass1} - assert_raise(NoMethodError, /protected method/) {o.aClass2} - c.class_eval {public :aClass1} - assert_equal(:aClass1, o.aClass1) - - o = (c = Class.new(AClass)).new - c.class_eval {public :aClass1, :aClass2} - assert_equal(:aClass1, o.aClass1) - assert_equal(:aClass2, o.aClass2) - - o = (c = Class.new(AClass)).new - c.class_eval {public [:aClass1, :aClass2]} - assert_equal(:aClass1, o.aClass1) - assert_equal(:aClass2, o.aClass2) - - o = AClass.new - assert_equal(:aClass, o.aClass) - assert_raise(NoMethodError, /private method/) {o.aClass1} - assert_raise(NoMethodError, /protected method/) {o.aClass2} - end - - def test_s_private - o = (c = Class.new(AClass)).new - assert_equal(:aClass, o.aClass) - c.class_eval {private :aClass} - assert_raise(NoMethodError, /private method/) {o.aClass} - - o = (c = Class.new(AClass)).new - c.class_eval {private :aClass, :aClass2} - assert_raise(NoMethodError, /private method/) {o.aClass} - assert_raise(NoMethodError, /private method/) {o.aClass2} - - o = (c = Class.new(AClass)).new - c.class_eval {private [:aClass, :aClass2]} - assert_raise(NoMethodError, /private method/) {o.aClass} - assert_raise(NoMethodError, /private method/) {o.aClass2} - - o = AClass.new - assert_equal(:aClass, o.aClass) - assert_raise(NoMethodError, /private method/) {o.aClass1} - assert_raise(NoMethodError, /protected method/) {o.aClass2} - end - - def test_s_protected - aclass = Class.new(AClass) do - def _aClass(o) o.aClass; end - def _aClass1(o) o.aClass1; end - def _aClass2(o) o.aClass2; end - end - - o = (c = Class.new(aclass)).new - assert_equal(:aClass, o.aClass) - c.class_eval {protected :aClass} - assert_raise(NoMethodError, /protected method/) {o.aClass} - assert_equal(:aClass, c.new._aClass(o)) - - o = (c = Class.new(aclass)).new - c.class_eval {protected :aClass, :aClass1} - assert_raise(NoMethodError, /protected method/) {o.aClass} - assert_raise(NoMethodError, /protected method/) {o.aClass1} - assert_equal(:aClass, c.new._aClass(o)) - assert_equal(:aClass1, c.new._aClass1(o)) - - o = (c = Class.new(aclass)).new - c.class_eval {protected [:aClass, :aClass1]} - assert_raise(NoMethodError, /protected method/) {o.aClass} - assert_raise(NoMethodError, /protected method/) {o.aClass1} - assert_equal(:aClass, c.new._aClass(o)) - assert_equal(:aClass1, c.new._aClass1(o)) - - o = AClass.new - assert_equal(:aClass, o.aClass) - assert_raise(NoMethodError, /private method/) {o.aClass1} - assert_raise(NoMethodError, /protected method/) {o.aClass2} - end - def test_s_constants c1 = Module.constants Object.module_eval "WALTER = 99" c2 = Module.constants assert_equal([:WALTER], c2 - c1) - Object.class_eval do - remove_const :WALTER - end - assert_equal([], Module.constants(true)) assert_equal([], Module.constants(false)) @@ -988,18 +650,14 @@ class TestModule < Test::Unit::TestCase end def test_attr_obsoleted_flag - c = Class.new do - extend Test::Unit::Assertions + c = Class.new + c.class_eval do def initialize @foo = :foo @bar = :bar end - assert_deprecated_warning(/optional boolean argument/) do - attr :foo, true - end - assert_deprecated_warning(/optional boolean argument/) do - attr :bar, false - end + attr :foo, true + attr :bar, false end o = c.new assert_equal(true, o.respond_to?(:foo)) @@ -1008,32 +666,6 @@ class TestModule < Test::Unit::TestCase assert_equal(false, o.respond_to?(:bar=)) end - def test_attr_public_at_toplevel - s = Object.new - TOPLEVEL_BINDING.eval(<<-END).call(s.singleton_class) - proc do |c| - c.send(:attr_accessor, :x) - c.send(:attr, :y) - c.send(:attr_reader, :z) - c.send(:attr_writer, :w) - end - END - assert_nil s.x - s.x = 1 - assert_equal 1, s.x - - assert_nil s.y - s.instance_variable_set(:@y, 2) - assert_equal 2, s.y - - assert_nil s.z - s.instance_variable_set(:@z, 3) - assert_equal 3, s.z - - s.w = 4 - assert_equal 4, s.instance_variable_get(:@w) - end - def test_const_get_evaled c1 = Class.new c2 = Class.new(c1) @@ -1044,7 +676,6 @@ class TestModule < Test::Unit::TestCase assert_equal(:foo, c2.const_get(:Foo)) assert_raise(NameError) { c2.const_get(:Foo, false) } - c1.__send__(:remove_const, :Foo) eval("c1::Foo = :foo") assert_raise(NameError) { c1::Bar } assert_raise(NameError) { c2::Bar } @@ -1092,6 +723,10 @@ class TestModule < Test::Unit::TestCase assert_raise(NameError) { c1.const_get(:foo) } bug5084 = '[ruby-dev:44200]' assert_raise(TypeError, bug5084) { c1.const_get(1) } + bug7574 = '[ruby-dev:46749]' + assert_raise_with_message(NameError, "wrong constant name \"String\\u0000\"", bug7574) { + Object.const_get("String\0") + } end def test_const_defined_invalid_name @@ -1099,6 +734,10 @@ class TestModule < Test::Unit::TestCase assert_raise(NameError) { c1.const_defined?(:foo) } bug5084 = '[ruby-dev:44200]' assert_raise(TypeError, bug5084) { c1.const_defined?(1) } + bug7574 = '[ruby-dev:46749]' + assert_raise_with_message(NameError, "wrong constant name \"String\\u0000\"", bug7574) { + Object.const_defined?("String\0") + } end def test_const_get_no_inherited @@ -1242,28 +881,6 @@ class TestModule < Test::Unit::TestCase assert_raise(NameError) do c.instance_eval { attr_reader :"." } end - - assert_equal([:a], c.class_eval { attr :a }) - assert_equal([:b, :c], c.class_eval { attr :b, :c }) - assert_equal([:d], c.class_eval { attr_reader :d }) - assert_equal([:e, :f], c.class_eval { attr_reader :e, :f }) - assert_equal([:g=], c.class_eval { attr_writer :g }) - assert_equal([:h=, :i=], c.class_eval { attr_writer :h, :i }) - assert_equal([:j, :j=], c.class_eval { attr_accessor :j }) - assert_equal([:k, :k=, :l, :l=], c.class_eval { attr_accessor :k, :l }) - end - - def test_alias_method - c = Class.new do - def foo; :foo end - end - o = c.new - assert_respond_to(o, :foo) - assert_not_respond_to(o, :bar) - r = c.class_eval {alias_method :bar, :foo} - assert_respond_to(o, :bar) - assert_equal(:foo, o.bar) - assert_equal(:bar, r) end def test_undef @@ -1360,8 +977,8 @@ class TestModule < Test::Unit::TestCase end def test_method_defined - cl = Class.new - def_methods = proc do + c = Class.new + c.class_eval do def foo; end def bar; end def baz; end @@ -1369,69 +986,43 @@ class TestModule < Test::Unit::TestCase protected :bar private :baz end - cl.class_eval(&def_methods) - sc = Class.new(cl) - mod = Module.new(&def_methods) - only_prepend = Class.new{prepend(mod)} - empty_prepend = cl.clone - empty_prepend.prepend(Module.new) - overlap_prepend = cl.clone - overlap_prepend.prepend(mod) - [[], [true], [false]].each do |args| - [cl, sc, only_prepend, empty_prepend, overlap_prepend].each do |c| - always_false = [sc, only_prepend].include?(c) && args == [false] + assert_equal(true, c.public_method_defined?(:foo)) + assert_equal(false, c.public_method_defined?(:bar)) + assert_equal(false, c.public_method_defined?(:baz)) - assert_equal(always_false ? false : true, c.public_method_defined?(:foo, *args)) - assert_equal(always_false ? false : false, c.public_method_defined?(:bar, *args)) - assert_equal(always_false ? false : false, c.public_method_defined?(:baz, *args)) + # Test if string arguments are converted to symbols + assert_equal(true, c.public_method_defined?("foo")) + assert_equal(false, c.public_method_defined?("bar")) + assert_equal(false, c.public_method_defined?("baz")) - # Test if string arguments are converted to symbols - assert_equal(always_false ? false : true, c.public_method_defined?("foo", *args)) - assert_equal(always_false ? false : false, c.public_method_defined?("bar", *args)) - assert_equal(always_false ? false : false, c.public_method_defined?("baz", *args)) + assert_equal(false, c.protected_method_defined?(:foo)) + assert_equal(true, c.protected_method_defined?(:bar)) + assert_equal(false, c.protected_method_defined?(:baz)) - assert_equal(always_false ? false : false, c.protected_method_defined?(:foo, *args)) - assert_equal(always_false ? false : true, c.protected_method_defined?(:bar, *args)) - assert_equal(always_false ? false : false, c.protected_method_defined?(:baz, *args)) + # Test if string arguments are converted to symbols + assert_equal(false, c.protected_method_defined?("foo")) + assert_equal(true, c.protected_method_defined?("bar")) + assert_equal(false, c.protected_method_defined?("baz")) - # Test if string arguments are converted to symbols - assert_equal(always_false ? false : false, c.protected_method_defined?("foo", *args)) - assert_equal(always_false ? false : true, c.protected_method_defined?("bar", *args)) - assert_equal(always_false ? false : false, c.protected_method_defined?("baz", *args)) + assert_equal(false, c.private_method_defined?(:foo)) + assert_equal(false, c.private_method_defined?(:bar)) + assert_equal(true, c.private_method_defined?(:baz)) - assert_equal(always_false ? false : false, c.private_method_defined?(:foo, *args)) - assert_equal(always_false ? false : false, c.private_method_defined?(:bar, *args)) - assert_equal(always_false ? false : true, c.private_method_defined?(:baz, *args)) - - # Test if string arguments are converted to symbols - assert_equal(always_false ? false : false, c.private_method_defined?("foo", *args)) - assert_equal(always_false ? false : false, c.private_method_defined?("bar", *args)) - assert_equal(always_false ? false : true, c.private_method_defined?("baz", *args)) - end - end + # Test if string arguments are converted to symbols + assert_equal(false, c.private_method_defined?("foo")) + assert_equal(false, c.private_method_defined?("bar")) + assert_equal(true, c.private_method_defined?("baz")) end def test_top_public_private - assert_in_out_err([], <<-INPUT, %w([:foo] [:bar] [:bar,\ :foo] [] [:bar,\ :foo] []), []) + assert_in_out_err([], <<-INPUT, %w([:foo] [:bar]), []) private def foo; :foo; end public def bar; :bar; end p self.private_methods.grep(/^foo$|^bar$/) p self.methods.grep(/^foo$|^bar$/) - - private :foo, :bar - p self.private_methods.grep(/^foo$|^bar$/).sort - - public :foo, :bar - p self.private_methods.grep(/^foo$|^bar$/).sort - - private [:foo, :bar] - p self.private_methods.grep(/^foo$|^bar$/).sort - - public [:foo, :bar] - p self.private_methods.grep(/^foo$|^bar$/).sort INPUT end @@ -1710,17 +1301,6 @@ class TestModule < Test::Unit::TestCase assert_match(/: warning: previous definition of foo/, stderr) end - def test_module_function_inside_method - assert_warn(/calling module_function without arguments inside a method may not have the intended effect/, '[ruby-core:79751]') do - Module.new do - def self.foo - module_function - end - foo - end - end - end - def test_protected_singleton_method klass = Class.new x = klass.new @@ -1845,21 +1425,6 @@ class TestModule < Test::Unit::TestCase RUBY end - def test_private_constant_const_missing - c = Class.new - c.const_set(:FOO, "foo") - c.private_constant(:FOO) - class << c - attr_reader :const_missing_arg - def const_missing(name) - @const_missing_arg = name - name == :FOO ? const_get(:FOO) : super - end - end - assert_equal("foo", c::FOO) - assert_equal(:FOO, c.const_missing_arg) - end - class PrivateClass end private_constant :PrivateClass @@ -1892,31 +1457,10 @@ class TestModule < Test::Unit::TestCase c = Class.new c.const_set(:FOO, "foo") c.deprecate_constant(:FOO) - assert_warn(/deprecated/) do - Warning[:deprecated] = true - c::FOO - end - assert_warn(/#{c}::FOO is deprecated/) do - Warning[:deprecated] = true - Class.new(c)::FOO - end + assert_warn(/deprecated/) {c::FOO} + assert_warn(/#{c}::FOO is deprecated/) {Class.new(c)::FOO} bug12382 = '[ruby-core:75505] [Bug #12382]' - assert_warn(/deprecated/, bug12382) do - Warning[:deprecated] = true - c.class_eval "FOO" - end - assert_warn('') do - Warning[:deprecated] = false - c::FOO - end - assert_warn('') do - Warning[:deprecated] = false - Class.new(c)::FOO - end - assert_warn('') do - Warning[:deprecated] = false - c.class_eval "FOO" - end + assert_warn(/deprecated/, bug12382) {c.class_eval "FOO"} end def test_constants_with_private_constant @@ -2279,33 +1823,6 @@ class TestModule < Test::Unit::TestCase assert_include(im, mixin, bug8025) end - def test_prepended_module_with_super_and_alias - bug16736 = '[Bug #16736]' - - a = labeled_class("A") do - def m; "A"; end - end - m = labeled_module("M") do - prepend Module.new - - def self.included(base) - base.alias_method :base_m, :m - end - - def m - super + "M" - end - - def m2 - base_m - end - end - b = labeled_class("B", a) do - include m - end - assert_equal("AM", b.new.m2, bug16736) - end - def test_prepend_super_in_alias bug7842 = '[Bug #7842]' @@ -2424,22 +1941,6 @@ class TestModule < Test::Unit::TestCase assert_equal([:@@bar], m2.class_variables(false)) end - def test_class_variable_in_dup_class - a = Class.new do - @@a = 'A' - def a=(x) - @@a = x - end - def a - @@a - end - end - - b = a.dup - b.new.a = 'B' - assert_equal 'A', a.new.a, '[ruby-core:17019]' - end - Bug6891 = '[ruby-core:47241]' def test_extend_module_with_protected_method @@ -2506,19 +2007,20 @@ class TestModule < Test::Unit::TestCase $foo \u3042$ ].each do |name| - e = assert_raise(NameError) do + assert_raise_with_message(NameError, /#{Regexp.quote(quote(name))}/) do Module.new { attr_accessor name.to_sym } end - assert_equal(name, e.name.to_s) end end + private def quote(name) + encoding = Encoding.default_internal || Encoding.default_external + (name.encoding == encoding || name.ascii_only?) ? name : name.inspect + end + class AttrTest class << self attr_accessor :cattr - def reset - self.cattr = nil - end end attr_accessor :iattr def ivar @@ -2528,7 +2030,7 @@ class TestModule < Test::Unit::TestCase def test_uninitialized_instance_variable a = AttrTest.new - assert_warning('') do + assert_warning(/instance variable @ivar not initialized/) do assert_nil(a.ivar) end a.instance_variable_set(:@ivar, 42) @@ -2537,7 +2039,7 @@ class TestModule < Test::Unit::TestCase end name = "@\u{5909 6570}" - assert_warning('') do + assert_warning(/instance variable #{name} not initialized/) do assert_nil(a.instance_eval(name)) end end @@ -2561,8 +2063,6 @@ class TestModule < Test::Unit::TestCase assert_warning '' do assert_equal(42, AttrTest.cattr) end - - AttrTest.reset end def test_uninitialized_attr_non_object @@ -2666,6 +2166,31 @@ class TestModule < Test::Unit::TestCase assert_raise(NoMethodError, bug8284) {Object.remove_const} end + def test_include_module_with_constants_does_not_invalidate_method_cache + assert_in_out_err([], <<-RUBY, %w(123 456 true), []) + A = 123 + + class Foo + def self.a + A + end + end + + module M + A = 456 + end + + puts Foo.a + starting = RubyVM.stat[:global_method_state] + + Foo.send(:include, M) + + ending = RubyVM.stat[:global_method_state] + puts Foo.a + puts starting == ending + RUBY + end + def test_return_value_of_define_method retvals = [] Class.new.class_eval do @@ -2704,10 +2229,7 @@ class TestModule < Test::Unit::TestCase def test_inspect_segfault bug_10282 = '[ruby-core:65214] [Bug #10282]' - assert_separately [], "#{<<~"begin;"}\n#{<<~'end;'}" - bug_10282 = "#{bug_10282}" - begin; - line = __LINE__ + 2 + assert_separately [], <<-RUBY module ShallowInspect def shallow_inspect "foo" @@ -2724,9 +2246,9 @@ class TestModule < Test::Unit::TestCase A.prepend InspectIsShallow - expect = "#<Method: A(ShallowInspect)#inspect(shallow_inspect)() -:#{line}>" - assert_equal expect, A.new.method(:inspect).inspect, bug_10282 - end; + expect = "#<Method: A(ShallowInspect)#inspect(shallow_inspect)>" + assert_equal expect, A.new.method(:inspect).inspect, "#{bug_10282}" + RUBY end def test_define_method_with_unbound_method @@ -2750,17 +2272,15 @@ class TestModule < Test::Unit::TestCase def test_redefinition_mismatch m = Module.new - m.module_eval "A = 1", __FILE__, line = __LINE__ - e = assert_raise_with_message(TypeError, /is not a module/) { + m.module_eval "A = 1" + assert_raise_with_message(TypeError, /is not a module/) { m.module_eval "module A; end" } - assert_include(e.message, "#{__FILE__}:#{line}: previous definition") n = "M\u{1f5ff}" - m.module_eval "#{n} = 42", __FILE__, line = __LINE__ - e = assert_raise_with_message(TypeError, /#{n} is not a module/) { + m.module_eval "#{n} = 42" + assert_raise_with_message(TypeError, "#{n} is not a module") { m.module_eval "module #{n}; end" } - assert_include(e.message, "#{__FILE__}:#{line}: previous definition") assert_separately([], <<-"end;") Etc = (class C\u{1f5ff}; self; end).new @@ -2788,68 +2308,6 @@ class TestModule < Test::Unit::TestCase } end - ConstLocation = [__FILE__, __LINE__] - - def test_const_source_location - assert_equal(ConstLocation, self.class.const_source_location(:ConstLocation)) - assert_equal(ConstLocation, self.class.const_source_location("ConstLocation")) - assert_equal(ConstLocation, Object.const_source_location("#{self.class.name}::ConstLocation")) - assert_raise(TypeError) { - self.class.const_source_location(nil) - } - assert_raise_with_message(NameError, /wrong constant name/) { - self.class.const_source_location("xxx") - } - assert_raise_with_message(TypeError, %r'does not refer to class/module') { - self.class.const_source_location("ConstLocation::FILE") - } - end - - module CloneTestM_simple - C = 1 - def self.m; C; end - end - - module CloneTestM0 - def foo; TEST; end - end - - CloneTestM1 = CloneTestM0.clone - CloneTestM2 = CloneTestM0.clone - module CloneTestM1 - TEST = :M1 - end - module CloneTestM2 - TEST = :M2 - end - class CloneTestC1 - include CloneTestM1 - end - class CloneTestC2 - include CloneTestM2 - end - - def test_constant_access_from_method_in_cloned_module - m = CloneTestM_simple.dup - assert_equal 1, m::C, '[ruby-core:47834]' - assert_equal 1, m.m, '[ruby-core:47834]' - - assert_equal :M1, CloneTestC1.new.foo, '[Bug #15877]' - assert_equal :M2, CloneTestC2.new.foo, '[Bug #15877]' - end - - def test_clone_freeze - m = Module.new.freeze - assert_predicate m.clone, :frozen? - assert_not_predicate m.clone(freeze: false), :frozen? - end - - def test_module_name_in_singleton_method - s = Object.new.singleton_class - mod = s.const_set(:Foo, Module.new) - assert_match(/::Foo$/, mod.name, '[Bug #14895]') - end - private def assert_top_method_is_private(method) @@ -2858,8 +2316,7 @@ class TestModule < Test::Unit::TestCase assert_include(methods, :#{method}, ":#{method} should be private") assert_raise_with_message(NoMethodError, "private method `#{method}' called for main:Object") { - recv = self - recv.#{method} + self.#{method} } } end diff --git a/test/ruby/test_name_error.rb b/test/ruby/test_name_error.rb deleted file mode 100644 index 813a976e96..0000000000 --- a/test/ruby/test_name_error.rb +++ /dev/null @@ -1,156 +0,0 @@ -require 'test/unit' - -class TestNameError < Test::Unit::TestCase - def test_new_default - error = NameError.new - assert_equal("NameError", error.message) - end - - def test_new_message - error = NameError.new("Message") - assert_equal("Message", error.message) - end - - def test_new_name - error = NameError.new("Message") - assert_nil(error.name) - - error = NameError.new("Message", :foo) - assert_equal(:foo, error.name) - end - - def test_new_receiver - receiver = Object.new - - error = NameError.new - assert_raise(ArgumentError) {error.receiver} - assert_equal("NameError", error.message) - - error = NameError.new(receiver: receiver) - assert_equal(["NameError", receiver], - [error.message, error.receiver]) - - error = NameError.new("Message", :foo, receiver: receiver) - assert_equal(["Message", receiver, :foo], - [error.message, error.receiver, error.name]) - end - - PrettyObject = - Class.new(BasicObject) do - alias object_id __id__ - def pretty_inspect; "`obj'"; end - alias inspect pretty_inspect - end - - def test_info_const - obj = PrettyObject.new - - e = assert_raise(NameError) { - obj.instance_eval("Object") - } - assert_equal(:Object, e.name) - - e = assert_raise(NameError) { - BasicObject::X - } - assert_same(BasicObject, e.receiver) - assert_equal(:X, e.name) - end - - def test_info_const_name - mod = Module.new do - def self.name - "ModuleName" - end - - def self.inspect - raise "<unusable info>" - end - end - assert_raise_with_message(NameError, /ModuleName/) {mod::DOES_NOT_EXIST} - end - - def test_info_method - obj = PrettyObject.new - - e = assert_raise(NameError) { - obj.instance_eval {foo} - } - assert_equal(:foo, e.name) - assert_same(obj, e.receiver) - - e = assert_raise(NoMethodError) { - obj.foo(1, 2) - } - assert_equal(:foo, e.name) - assert_equal([1, 2], e.args) - assert_same(obj, e.receiver) - assert_not_predicate(e, :private_call?) - - e = assert_raise(NoMethodError) { - obj.instance_eval {foo(1, 2)} - } - assert_equal(:foo, e.name) - assert_equal([1, 2], e.args) - assert_same(obj, e.receiver) - assert_predicate(e, :private_call?) - end - - def test_info_local_variables - obj = PrettyObject.new - def obj.test(a, b=nil, *c, &d) - e = a - 1.times {|f| g = foo; g} - e - end - - e = assert_raise(NameError) { - obj.test(3) - } - assert_equal(:foo, e.name) - assert_same(obj, e.receiver) - assert_equal(%i[a b c d e f g], e.local_variables.sort) - end - - def test_info_method_missing - obj = PrettyObject.new - def obj.method_missing(*) - super - end - - e = assert_raise(NoMethodError) { - obj.foo(1, 2) - } - assert_equal(:foo, e.name) - assert_equal([1, 2], e.args) - assert_same(obj, e.receiver) - assert_not_predicate(e, :private_call?) - - e = assert_raise(NoMethodError) { - obj.instance_eval {foo(1, 2)} - } - assert_equal(:foo, e.name) - assert_equal([1, 2], e.args) - assert_same(obj, e.receiver) - assert_predicate(e, :private_call?) - end - - def test_info_parent_iseq_mark - assert_separately(['-', File.join(__dir__, 'bug-11928.rb')], <<-'end;') - -> {require ARGV[0]}.call - end; - end - - def test_large_receiver_inspect - receiver = Class.new do - def self.inspect - 'A' * 120 - end - end - - error = assert_raise(NameError) do - receiver::FOO - end - assert_equal "uninitialized constant #{'A' * 120}::FOO", error.message - end -end diff --git a/test/ruby/test_nomethod_error.rb b/test/ruby/test_nomethod_error.rb deleted file mode 100644 index 170a6c6c57..0000000000 --- a/test/ruby/test_nomethod_error.rb +++ /dev/null @@ -1,93 +0,0 @@ -require 'test/unit' - -class TestNoMethodError < Test::Unit::TestCase - def test_new_default - error = NoMethodError.new - assert_equal("NoMethodError", error.message) - end - - def test_new_message - error = NoMethodError.new("Message") - assert_equal("Message", error.message) - end - - def test_new_name - error = NoMethodError.new("Message") - assert_nil(error.name) - - error = NoMethodError.new("Message", :foo) - assert_equal(:foo, error.name) - end - - def test_new_name_args - error = NoMethodError.new("Message", :foo) - assert_nil(error.args) - - error = NoMethodError.new("Message", :foo, [1, 2]) - assert_equal([:foo, [1, 2]], [error.name, error.args]) - end - - def test_new_name_args_priv - error = NoMethodError.new("Message", :foo, [1, 2]) - assert_not_predicate(error, :private_call?) - - error = NoMethodError.new("Message", :foo, [1, 2], true) - assert_equal([:foo, [1, 2], true], - [error.name, error.args, error.private_call?]) - end - - def test_new_receiver - receiver = Object.new - - error = NoMethodError.new - assert_raise(ArgumentError) {error.receiver} - - error = NoMethodError.new(receiver: receiver) - assert_equal(receiver, error.receiver) - - error = NoMethodError.new("Message") - assert_raise(ArgumentError) {error.receiver} - - error = NoMethodError.new("Message", receiver: receiver) - assert_equal(["Message", receiver], - [error.message, error.receiver]) - - error = NoMethodError.new("Message", :foo) - assert_raise(ArgumentError) {error.receiver} - - msg = "Message" - - error = NoMethodError.new("Message", :foo, receiver: receiver) - assert_match msg, error.message - assert_equal :foo, error.name - assert_equal receiver, error.receiver - - error = NoMethodError.new("Message", :foo, [1, 2]) - assert_raise(ArgumentError) {error.receiver} - - error = NoMethodError.new("Message", :foo, [1, 2], receiver: receiver) - assert_match msg, error.message - assert_equal :foo, error.name - assert_equal [1, 2], error.args - assert_equal receiver, error.receiver - - error = NoMethodError.new("Message", :foo, [1, 2], true) - assert_raise(ArgumentError) {error.receiver} - - error = NoMethodError.new("Message", :foo, [1, 2], true, receiver: receiver) - assert_equal :foo, error.name - assert_equal [1, 2], error.args - assert_equal receiver, error.receiver - assert error.private_call?, "private_call? was false." - end - - def test_message_encoding - bug3237 = '[ruby-core:29948]' - str = "\u2600" - id = :"\u2604" - msg = "undefined method `#{id}' for \"#{str}\":String" - assert_raise_with_message(NoMethodError, msg, bug3237) do - str.__send__(id) - end - end -end diff --git a/test/ruby/test_not.rb b/test/ruby/test_not.rb index 12e4c4b696..721f868a5a 100644 --- a/test/ruby/test_not.rb +++ b/test/ruby/test_not.rb @@ -1,7 +1,7 @@ # frozen_string_literal: false require 'test/unit' -class TestNot < Test::Unit::TestCase +class TestIfunless < Test::Unit::TestCase def test_not_with_grouped_expression assert_equal(false, (not (true))) assert_equal(true, (not (false))) diff --git a/test/ruby/test_notimp.rb b/test/ruby/test_notimp.rb new file mode 100644 index 0000000000..ddebb657bf --- /dev/null +++ b/test/ruby/test_notimp.rb @@ -0,0 +1,85 @@ +# frozen_string_literal: false +require 'test/unit' +require 'timeout' +require 'tmpdir' + +class TestNotImplement < Test::Unit::TestCase + def test_respond_to_fork + assert_include(Process.methods, :fork) + if /linux/ =~ RUBY_PLATFORM + assert_equal(true, Process.respond_to?(:fork)) + end + end + + def test_respond_to_lchmod + assert_include(File.methods, :lchmod) + if /linux/ =~ RUBY_PLATFORM + assert_equal(false, File.respond_to?(:lchmod)) + end + if /freebsd/ =~ RUBY_PLATFORM + assert_equal(true, File.respond_to?(:lchmod)) + end + end + + def test_call_fork + GC.start + pid = nil + ps = + case RUBY_PLATFORM + when /linux/ # assume Linux Distribution uses procps + proc {`ps -eLf #{pid}`} + when /freebsd/ + proc {`ps -lH #{pid}`} + when /darwin/ + proc {`ps -lM #{pid}`} + else + proc {`ps -l #{pid}`} + end + assert_nothing_raised(Timeout::Error, ps) do + Timeout.timeout(EnvUtil.apply_timeout_scale(5)) { + pid = fork {} + Process.wait pid + pid = nil + } + end + ensure + if pid + Process.kill(:KILL, pid) + Process.wait pid + end + end if Process.respond_to?(:fork) + + def test_call_lchmod + if File.respond_to?(:lchmod) + Dir.mktmpdir {|d| + f = "#{d}/f" + g = "#{d}/g" + File.open(f, "w") {} + File.symlink f, g + newmode = 0444 + File.lchmod newmode, "#{d}/g" + snew = File.lstat(g) + assert_equal(newmode, snew.mode & 0777) + } + end + end + + def test_method_inspect_fork + m = Process.method(:fork) + if Process.respond_to?(:fork) + assert_not_match(/not-implemented/, m.inspect) + else + assert_match(/not-implemented/, m.inspect) + end + end + + def test_method_inspect_lchmod + m = File.method(:lchmod) + if File.respond_to?(:lchmod) + assert_not_match(/not-implemented/, m.inspect) + else + assert_match(/not-implemented/, m.inspect) + end + end + +end diff --git a/test/ruby/test_numeric.rb b/test/ruby/test_numeric.rb index c8751fbc57..6efc40320a 100644 --- a/test/ruby/test_numeric.rb +++ b/test/ruby/test_numeric.rb @@ -26,10 +26,6 @@ class TestNumeric < Test::Unit::TestCase 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, /:\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" @@ -56,6 +52,7 @@ class TestNumeric < Test::Unit::TestCase end.new assert_equal(-1, -a) + bug7688 = '[ruby-core:51389] [Bug #7688]' a = Class.new(Numeric) do def coerce(x); raise StandardError, "my error"; end end.new @@ -230,8 +227,7 @@ class TestNumeric < Test::Unit::TestCase end def assert_step(expected, (from, *args), inf: false) - kw = args.last.is_a?(Hash) ? args.pop : {} - enum = from.step(*args, **kw) + enum = from.step(*args) size = enum.size xsize = expected.size @@ -240,7 +236,7 @@ class TestNumeric < Test::Unit::TestCase assert_send [size, :>, 0], "step size: +infinity" a = [] - from.step(*args, **kw) { |x| a << x; break if a.size == xsize } + from.step(*args) { |x| a << x; break if a.size == xsize } assert_equal expected, a, "step" a = [] @@ -250,7 +246,7 @@ class TestNumeric < Test::Unit::TestCase assert_equal expected.size, size, "step size" a = [] - from.step(*args, **kw) { |x| a << x } + from.step(*args) { |x| a << x } assert_equal expected, a, "step" a = [] @@ -264,21 +260,18 @@ class TestNumeric < Test::Unit::TestCase assert_raise(ArgumentError) { 1.step(10, 1, 0) { } } assert_raise(ArgumentError) { 1.step(10, 1, 0).size } assert_raise(ArgumentError) { 1.step(10, 0) { } } + assert_raise(ArgumentError) { 1.step(10, 0).size } assert_raise(ArgumentError) { 1.step(10, "1") { } } assert_raise(ArgumentError) { 1.step(10, "1").size } assert_raise(TypeError) { 1.step(10, nil) { } } - assert_nothing_raised { 1.step(10, nil).size } + assert_raise(TypeError) { 1.step(10, nil).size } + assert_nothing_raised { 1.step(by: 0, to: nil) } + assert_nothing_raised { 1.step(by: 0, to: nil).size } + assert_nothing_raised { 1.step(by: 0) } + assert_nothing_raised { 1.step(by: 0).size } assert_nothing_raised { 1.step(by: nil) } assert_nothing_raised { 1.step(by: nil).size } - assert_kind_of(Enumerator::ArithmeticSequence, 1.step(10)) - assert_kind_of(Enumerator::ArithmeticSequence, 1.step(10, 2)) - assert_kind_of(Enumerator::ArithmeticSequence, 1.step(10, by: 2)) - assert_kind_of(Enumerator::ArithmeticSequence, 1.step(by: 2)) - assert_kind_of(Enumerator::ArithmeticSequence, 1.step(by: 2, to: nil)) - assert_kind_of(Enumerator::ArithmeticSequence, 1.step(by: 2, to: 10)) - assert_kind_of(Enumerator::ArithmeticSequence, 1.step(by: -1)) - bug9811 = '[ruby-dev:48177] [Bug #9811]' assert_raise(ArgumentError, bug9811) { 1.step(10, foo: nil) {} } assert_raise(ArgumentError, bug9811) { 1.step(10, foo: nil).size } @@ -287,27 +280,6 @@ class TestNumeric < Test::Unit::TestCase assert_raise(ArgumentError, bug9811) { 1.step(10, 1, by: 11) {} } assert_raise(ArgumentError, bug9811) { 1.step(10, 1, by: 11).size } - feature15573 = "[ruby-core:91324] [Feature #15573]" - assert_raise(ArgumentError, feature15573) { 1.step(10, 0) } - assert_raise(ArgumentError, feature15573) { 1.step(10, by: 0) } - assert_raise(ArgumentError, feature15573) { 1.step(10, 0) { break } } - assert_raise(ArgumentError, feature15573) { 1.step(10, by: 0) { break } } - assert_raise(ArgumentError, feature15573) { 42.step(by: 0, to: -Float::INFINITY) } - assert_raise(ArgumentError, feature15573) { 42.step(by: 0, to: 42.5) } - assert_raise(ArgumentError, feature15573) { 4.2.step(by: 0.0) } - assert_raise(ArgumentError, feature15573) { 4.2.step(by: -0.0) } - assert_raise(ArgumentError, feature15573) { 42.step(by: 0.0, to: 44) } - assert_raise(ArgumentError, feature15573) { 42.step(by: 0.0, to: 0) } - assert_raise(ArgumentError, feature15573) { 42.step(by: -0.0, to: 44) } - assert_raise(ArgumentError, feature15573) { bignum.step(by: 0) } - assert_raise(ArgumentError, feature15573) { bignum.step(by: 0.0) } - assert_raise(ArgumentError, feature15573) { bignum.step(by: 0, to: bignum+1) } - assert_raise(ArgumentError, feature15573) { bignum.step(by: 0, to: 0) } - - e = 1.step(10, {by: "1"}) - assert_raise(TypeError) {e.next} - assert_raise(TypeError) {e.size} - assert_equal(bignum*2+1, (-bignum).step(bignum, 1).size) assert_equal(bignum*2, (-bignum).step(bignum-1, 1).size) @@ -317,6 +289,7 @@ class TestNumeric < Test::Unit::TestCase i <<= 1 until (bigflo - i).to_i < bignum bigflo -= i >> 1 assert_equal(bigflo.to_i, (0.0).step(bigflo-1.0, 1.0).size) + assert_operator((0.0).step(bignum.to_f, 1.0).size, :>=, bignum) # may loose precision assert_step [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 10] assert_step [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, to: 10] @@ -333,6 +306,8 @@ class TestNumeric < Test::Unit::TestCase assert_step [], [2, 1, 3] assert_step [], [-2, -1, -3] + assert_step [3, 3, 3, 3], [3, by: 0], inf: true + assert_step [3, 3, 3, 3], [3, by: 0, to: 42], inf: true assert_step [10], [10, 1, -bignum] assert_step [], [1, 0, Float::INFINITY] @@ -342,20 +317,19 @@ class TestNumeric < Test::Unit::TestCase assert_step [10, 11, 12, 13], [10], inf: true assert_step [10, 9, 8, 7], [10, by: -1], inf: true assert_step [10, 9, 8, 7], [10, by: -1, to: nil], inf: true - end - def test_step_bug15537 - assert_step [10.0, 8.0, 6.0, 4.0, 2.0], [10.0, 1, -2] - assert_step [10.0, 8.0, 6.0, 4.0, 2.0], [10.0, to: 1, by: -2] - assert_step [10.0, 8.0, 6.0, 4.0, 2.0], [10.0, 1, -2] - assert_step [10.0, 8.0, 6.0, 4.0, 2.0], [10, to: 1.0, by: -2] - assert_step [10.0, 8.0, 6.0, 4.0, 2.0], [10, 1.0, -2] - - assert_step [10.0, 9.0, 8.0, 7.0], [10, by: -1.0], inf: true - assert_step [10.0, 9.0, 8.0, 7.0], [10, by: -1.0, to: nil], inf: true - assert_step [10.0, 9.0, 8.0, 7.0], [10, nil, -1.0], inf: true - assert_step [10.0, 9.0, 8.0, 7.0], [10.0, by: -1], inf: true - assert_step [10.0, 9.0, 8.0, 7.0], [10.0, nil, -1], inf: true + assert_step [42, 42, 42, 42], [42, by: 0, to: -Float::INFINITY], inf: true + assert_step [42, 42, 42, 42], [42, by: 0, to: 42.5], inf: true + assert_step [4.2, 4.2, 4.2, 4.2], [4.2, by: 0.0], inf: true + assert_step [4.2, 4.2, 4.2, 4.2], [4.2, by: -0.0], inf: true + assert_step [42.0, 42.0, 42.0, 42.0], [42, by: 0.0, to: 44], inf: true + assert_step [42.0, 42.0, 42.0, 42.0], [42, by: 0.0, to: 0], inf: true + assert_step [42.0, 42.0, 42.0, 42.0], [42, by: -0.0, to: 44], inf: true + + assert_step [bignum]*4, [bignum, by: 0], inf: true + assert_step [bignum]*4, [bignum, by: 0.0], inf: true + assert_step [bignum]*4, [bignum, by: 0, to: bignum+1], inf: true + assert_step [bignum]*4, [bignum, by: 0, to: 0], inf: true end def test_num2long @@ -431,26 +405,6 @@ class TestNumeric < Test::Unit::TestCase assert_equal(12, 12.pow(1, 10000000001), '[Bug #14259]') assert_equal(12, 12.pow(1, 10000000002), '[Bug #14259]') assert_equal(17298641040, 12.pow(72387894339363242, 243682743764), '[Bug #14259]') - - integers = [-2, -1, 0, 1, 2, 3, 6, 1234567890123456789] - integers.each do |i| - assert_equal(0, i.pow(0, 1), '[Bug #17257]') - assert_equal(1, i.pow(0, 2)) - assert_equal(1, i.pow(0, 3)) - assert_equal(1, i.pow(0, 6)) - assert_equal(1, i.pow(0, 1234567890123456789)) - - assert_equal(0, i.pow(0, -1)) - assert_equal(-1, i.pow(0, -2)) - assert_equal(-2, i.pow(0, -3)) - assert_equal(-5, i.pow(0, -6)) - assert_equal(-1234567890123456788, i.pow(0, -1234567890123456789)) - end - - assert_equal(0, 0.pow(2, 1)) - assert_equal(0, 0.pow(3, 1)) - assert_equal(0, 2.pow(3, 1)) - assert_equal(0, -2.pow(3, 1)) end end diff --git a/test/ruby/test_object.rb b/test/ruby/test_object.rb index 774b707742..c25dcf9c37 100644 --- a/test/ruby/test_object.rb +++ b/test/ruby/test_object.rb @@ -5,6 +5,7 @@ require 'test/unit' class TestObject < Test::Unit::TestCase def setup @verbose = $VERBOSE + $VERBOSE = nil end def teardown @@ -46,27 +47,15 @@ class TestObject < Test::Unit::TestCase a = Object.new def a.b; 2 end - c = a.clone - assert_equal(false, c.frozen?) - assert_equal(false, a.frozen?) - assert_equal(2, c.b) - - c = a.clone(freeze: true) - assert_equal(true, c.frozen?) - assert_equal(false, a.frozen?) - assert_equal(2, c.b) - a.freeze c = a.clone assert_equal(true, c.frozen?) - assert_equal(true, a.frozen?) assert_equal(2, c.b) assert_raise(ArgumentError) {a.clone(freeze: [])} d = a.clone(freeze: false) def d.e; 3; end assert_equal(false, d.frozen?) - assert_equal(true, a.frozen?) assert_equal(2, d.b) assert_equal(3, d.e) @@ -86,30 +75,6 @@ class TestObject < Test::Unit::TestCase assert_raise_with_message(ArgumentError, /\u{1f4a9}/) do Object.new.clone(freeze: x) end - - c = Class.new do - attr_reader :f - end - o = c.new - def o.initialize_clone(_, freeze: true) - @f = freeze - super - end - clone = o.clone - assert_kind_of c, clone - assert_equal true, clone.f - clone = o.clone(freeze: false) - assert_kind_of c, clone - assert_equal false, clone.f - - class << o - remove_method(:initialize_clone) - end - def o.initialize_clone(_) - super - end - assert_kind_of c, o.clone - assert_raise(ArgumentError) { o.clone(freeze: false) } end def test_init_dupclone @@ -131,6 +96,17 @@ class TestObject < Test::Unit::TestCase assert_raise(TypeError) { 1.kind_of?(1) } end + def test_taint_frozen_obj + o = Object.new + o.freeze + assert_raise(FrozenError) { o.taint } + + o = Object.new + o.taint + o.freeze + assert_raise(FrozenError) { o.untaint } + end + def test_freeze_immediate assert_equal(true, 1.frozen?) 1.freeze @@ -156,27 +132,6 @@ class TestObject < Test::Unit::TestCase assert_equal(0.0, nil.to_f) end - def test_nil_to_s - str = nil.to_s - assert_equal("", str) - assert_predicate(str, :frozen?) - assert_same(str, nil.to_s) - end - - def test_true_to_s - str = true.to_s - assert_equal("true", str) - assert_predicate(str, :frozen?) - assert_same(str, true.to_s) - end - - def test_false_to_s - str = false.to_s - assert_equal("false", str) - assert_predicate(str, :frozen?) - assert_same(str, false.to_s) - end - def test_not assert_equal(false, Object.new.send(:!)) assert_equal(true, nil.send(:!)) @@ -272,14 +227,6 @@ class TestObject < Test::Unit::TestCase assert_equal([:foo], o.methods(false), bug8044) end - def test_methods_prepend_singleton - c = Class.new(Module) {private def foo; end} - k = c.new - k.singleton_class - c.module_eval {prepend(Module.new)} - assert_equal([:foo], k.private_methods(false)) - end - def test_instance_variable_get o = Object.new o.instance_eval { @foo = :foo } @@ -359,7 +306,6 @@ class TestObject < Test::Unit::TestCase o = Object.new def o.to_s; 1; end assert_raise(TypeError) { String(o) } - o.singleton_class.remove_method(:to_s) def o.to_s; "o"; end assert_equal("o", String(o)) def o.to_str; "O"; end @@ -372,7 +318,6 @@ class TestObject < Test::Unit::TestCase o = Object.new def o.to_a; 1; end assert_raise(TypeError) { Array(o) } - o.singleton_class.remove_method(:to_a) def o.to_a; [1]; end assert_equal([1], Array(o)) def o.to_ary; [2]; end @@ -390,7 +335,6 @@ class TestObject < Test::Unit::TestCase o = Object.new def o.to_hash; {a: 1, b: 2}; end assert_equal({a: 1, b: 2}, Hash(o)) - o.singleton_class.remove_method(:to_hash) def o.to_hash; 9; end assert_raise(TypeError) { Hash(o) } end @@ -399,7 +343,6 @@ class TestObject < Test::Unit::TestCase o = Object.new def o.to_i; nil; end assert_raise(TypeError) { Integer(o) } - o.singleton_class.remove_method(:to_i) def o.to_i; 42; end assert_equal(42, Integer(o)) def o.respond_to?(*) false; end @@ -634,7 +577,7 @@ class TestObject < Test::Unit::TestCase called = [] p.singleton_class.class_eval do - define_method(:respond_to?) do |a, priv = false| + define_method(:respond_to?) do |a| called << [:respond_to?, a] false end @@ -822,7 +765,36 @@ class TestObject < Test::Unit::TestCase end end + def test_untrusted + verbose = $VERBOSE + $VERBOSE = false + begin + obj = Object.new + assert_equal(false, obj.untrusted?) + assert_equal(false, obj.tainted?) + obj.untrust + assert_equal(true, obj.untrusted?) + assert_equal(true, obj.tainted?) + obj.trust + assert_equal(false, obj.untrusted?) + assert_equal(false, obj.tainted?) + obj.taint + assert_equal(true, obj.untrusted?) + assert_equal(true, obj.tainted?) + obj.untaint + assert_equal(false, obj.untrusted?) + assert_equal(false, obj.tainted?) + ensure + $VERBOSE = verbose + end + end + def test_to_s + x = Object.new + x.taint + s = x.to_s + assert_equal(true, s.tainted?) + x = eval(<<-EOS) class ToS\u{3042} new.to_s @@ -831,10 +803,14 @@ class TestObject < Test::Unit::TestCase assert_match(/\bToS\u{3042}:/, x) name = "X".freeze - x = Object.new + x = Object.new.taint class<<x;self;end.class_eval {define_method(:to_s) {name}} assert_same(name, x.to_s) + assert_not_predicate(name, :tainted?) + assert_raise(FrozenError) {name.taint} assert_equal("X", [x].join("")) + assert_not_predicate(name, :tainted?) + assert_not_predicate(eval('"X".freeze'), :tainted?) end def test_inspect @@ -881,29 +857,6 @@ class TestObject < Test::Unit::TestCase assert_match(/@\u{3046}=6\b/, x.inspect) end - def test_singleton_methods - assert_equal([], Object.new.singleton_methods) - assert_equal([], Object.new.singleton_methods(false)) - c = Class.new - def c.foo; end - assert_equal([:foo], c.singleton_methods - [:yaml_tag]) - assert_equal([:foo], c.singleton_methods(false)) - assert_equal([], c.singleton_class.singleton_methods(false)) - c.singleton_class.singleton_class - assert_equal([], c.singleton_class.singleton_methods(false)) - - o = c.new.singleton_class - assert_equal([:foo], o.singleton_methods - [:yaml_tag]) - assert_equal([], o.singleton_methods(false)) - o.singleton_class - assert_equal([:foo], o.singleton_methods - [:yaml_tag]) - assert_equal([], o.singleton_methods(false)) - - c.extend(Module.new{def bar; end}) - assert_equal([:bar, :foo], c.singleton_methods.sort - [:yaml_tag]) - assert_equal([:foo], c.singleton_methods(false)) - end - def test_singleton_class x = Object.new xs = class << x; self; end @@ -930,7 +883,6 @@ class TestObject < Test::Unit::TestCase ['ArgumentError.new("bug5473")', 'ArgumentError, "bug5473"', '"bug5473"'].each do |code| exc = code[/\A[A-Z]\w+/] || 'RuntimeError' assert_separately([], <<-SRC) - $VERBOSE = nil class ::Object def method_missing(m, *a, &b) raise #{code} @@ -948,7 +900,7 @@ class TestObject < Test::Unit::TestCase assert_nothing_raised("copy") {a.instance_eval {initialize_copy(b)}} c = a.dup.freeze assert_raise(FrozenError, "frozen") {c.instance_eval {initialize_copy(b)}} - d = a.dup + d = a.dup.trust [a, b, c, d] end diff --git a/test/ruby/test_objectspace.rb b/test/ruby/test_objectspace.rb index 02c20aa261..c352b75b70 100644 --- a/test/ruby/test_objectspace.rb +++ b/test/ruby/test_objectspace.rb @@ -35,36 +35,6 @@ End deftest_id2ref(false) deftest_id2ref(nil) - def test_id2ref_liveness - assert_normal_exit <<-EOS - ids = [] - 10.times{ - 1_000.times{ - ids << 'hello'.object_id - } - objs = ids.map{|id| - begin - ObjectSpace._id2ref(id) - rescue RangeError - nil - end - } - GC.start - objs.each{|e| e.inspect} - } - EOS - end - - def test_id2ref_invalid_argument - msg = /no implicit conversion/ - assert_raise_with_message(TypeError, msg) {ObjectSpace._id2ref(nil)} - assert_raise_with_message(TypeError, msg) {ObjectSpace._id2ref(false)} - assert_raise_with_message(TypeError, msg) {ObjectSpace._id2ref(true)} - assert_raise_with_message(TypeError, msg) {ObjectSpace._id2ref(:a)} - assert_raise_with_message(TypeError, msg) {ObjectSpace._id2ref("0")} - assert_raise_with_message(TypeError, msg) {ObjectSpace._id2ref(Object.new)} - end - def test_count_objects h = {} ObjectSpace.count_objects(h) diff --git a/test/ruby/test_optimization.rb b/test/ruby/test_optimization.rb index d0790c7463..2a4cc19699 100644 --- a/test/ruby/test_optimization.rb +++ b/test/ruby/test_optimization.rb @@ -187,16 +187,6 @@ class TestRubyOptimization < Test::Unit::TestCase assert_redefine_method('String', '<<', 'assert_equal "b", "a" << "b"') end - def test_fixnum_and - assert_equal 1, 1&3 - assert_redefine_method('Integer', '&', 'assert_equal 3, 1&3') - end - - def test_fixnum_or - assert_equal 3, 1|3 - assert_redefine_method('Integer', '|', 'assert_equal 1, 3|1') - end - def test_array_plus assert_equal [1,2], [1]+[2] assert_redefine_method('Array', '+', 'assert_equal [2], [1]+[2]') @@ -272,7 +262,7 @@ class TestRubyOptimization < Test::Unit::TestCase unless file loc, = caller_locations(1, 1) file = loc.path - line ||= loc.lineno + 1 + line ||= loc.lineno end RubyVM::InstructionSequence.new("proc {|_|_.class_eval {#{src}}}", file, (path || file), line, @@ -347,7 +337,7 @@ class TestRubyOptimization < Test::Unit::TestCase def test_tailcall_inhibited_by_rescue bug12082 = '[ruby-core:73871] [Bug #12082]' - EnvUtil.suppress_warning {tailcall("#{<<-"begin;"}\n#{<<~"end;"}")} + tailcall("#{<<-"begin;"}\n#{<<~"end;"}") begin; def to_be_rescued return do_raise @@ -398,7 +388,7 @@ class TestRubyOptimization < Test::Unit::TestCase foo end;1 end; - status, _err = EnvUtil.invoke_ruby([], "", true, true, **{}) { + status, _err = EnvUtil.invoke_ruby([], "", true, true, {}) { |in_p, out_p, err_p, pid| in_p.write(script) in_p.close @@ -425,7 +415,7 @@ class TestRubyOptimization < Test::Unit::TestCase def test_tailcall_condition_block bug = '[ruby-core:78015] [Bug #12905]' - src = "#{<<-"begin;"}\n#{<<~"end;"}", __FILE__, nil, __LINE__+1 + src = "#{<<-"begin;"}\n#{<<~"end;"}" begin; def run(current, final) if current < final @@ -437,13 +427,13 @@ class TestRubyOptimization < Test::Unit::TestCase end; obj = Object.new - self.class.tailcall(obj.singleton_class, *src, tailcall: false) + self.class.tailcall(obj.singleton_class, src, tailcall: false) e = assert_raise(SystemStackError) { obj.run(1, Float::INFINITY) } level = e.backtrace_locations.size obj = Object.new - self.class.tailcall(obj.singleton_class, *src, tailcall: true) + self.class.tailcall(obj.singleton_class, src, tailcall: true) level *= 2 mesg = message {"#{bug}: #{$!.backtrace_locations.size} / #{level} stack levels"} assert_nothing_raised(SystemStackError, mesg) { @@ -451,22 +441,6 @@ class TestRubyOptimization < Test::Unit::TestCase } end - def test_tailcall_not_to_grow_stack - skip 'currently JIT-ed code always creates a new stack frame' if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? - bug16161 = '[ruby-core:94881]' - - tailcall("#{<<-"begin;"}\n#{<<~"end;"}") - begin; - def foo(n) - return :ok if n < 1 - foo(n - 1) - end - end; - assert_nothing_raised(SystemStackError, bug16161) do - assert_equal(:ok, foo(1_000_000), bug16161) - end - end - class Bug10557 def [](_) block_given? @@ -583,30 +557,12 @@ class TestRubyOptimization < Test::Unit::TestCase when "1.8.0"..."1.8.8" then :bar end end; - [ true, false ].each do |opt| - iseq = RubyVM::InstructionSequence.compile(code, - frozen_string_literal: opt) - insn = iseq.disasm - assert_match %r{putobject\s+#{Regexp.quote('"1.8.0"..."1.8.8"')}}, insn - assert_match %r{putobject\s+#{Regexp.quote('"2.0.0".."2.3.2"')}}, insn - assert_no_match(/putstring/, insn) - assert_no_match(/newrange/, insn) - end - end - - def test_peephole_dstr - code = "#{<<~'begin;'}\n#{<<~'end;'}" - begin; - exp = -'a' - z = 'a' - [exp, -"#{z}"] - end; - [ false, true ].each do |fsl| - iseq = RubyVM::InstructionSequence.compile(code, - frozen_string_literal: fsl) - assert_same(*iseq.eval, - "[ruby-core:85542] [Bug #14475] fsl: #{fsl}") - end + iseq = RubyVM::InstructionSequence.compile(code) + insn = iseq.disasm + assert_match %r{putobject\s+#{Regexp.quote('"1.8.0"..."1.8.8"')}}, insn + assert_match %r{putobject\s+#{Regexp.quote('"2.0.0".."2.3.2"')}}, insn + assert_no_match(/putstring/, insn) + assert_no_match(/newrange/, insn) end def test_branch_condition_backquote @@ -701,16 +657,27 @@ class TestRubyOptimization < Test::Unit::TestCase def test_block_parameter_should_not_create_objects assert_separately [], <<-END + # def foo &b end h1 = {}; h2 = {} - ObjectSpace.count_objects(h1) # rehearsal - GC.start; GC.disable # to disable GC while foo{} + ObjectSpace.count_objects(h1) # reharsal ObjectSpace.count_objects(h1) foo{} ObjectSpace.count_objects(h2) - assert_equal 0, h2[:T_DATA] - h1[:T_DATA] # Proc is T_DATA + assert_equal 0, h2[:TOTAL] - h1[:TOTAL] + END + end + + def test_block_parameter_should_restore_safe_level + assert_separately [], <<-END + # + def foo &b + $SAFE = 1 + b.call + end + assert_equal 0, foo{$SAFE} END end @@ -722,7 +689,7 @@ class TestRubyOptimization < Test::Unit::TestCase end def test_clear_unreachable_keyword_args - assert_separately [], <<-END, timeout: 60 + assert_separately [], <<-END, timeout: 15 script = <<-EOS if true else @@ -756,7 +723,6 @@ class TestRubyOptimization < Test::Unit::TestCase h = {} assert_equal(bug, eval('{ok: 42, **h}; bug')) assert_equal(:ok, eval('{ok: bug = :ok, **h}; bug')) - assert_empty(h) end def test_overwritten_blockparam @@ -769,18 +735,6 @@ class TestRubyOptimization < Test::Unit::TestCase assert_equal(:ok, obj.a()) end - def test_blockparam_in_rescue - obj = Object.new - def obj.foo(&b) - raise - rescue - b.call - end - result = nil - assert_equal(42, obj.foo {result = 42}) - assert_equal(42, result) - end - def test_unconditional_branch_to_leave_block assert_valid_syntax("#{<<~"begin;"}\n#{<<~'end;'}") begin; @@ -830,19 +784,4 @@ class TestRubyOptimization < Test::Unit::TestCase } end; end - - def test_optimized_rescue - assert_in_out_err("", "#{<<~"begin;"}\n#{<<~'end;'}", [], /END \(RuntimeError\)/) - begin; - if false - begin - require "some_mad_stuff" - rescue LoadError - puts "no mad stuff loaded" - end - end - - raise "END" - end; - end end diff --git a/test/ruby/test_pack.rb b/test/ruby/test_pack.rb index 60edd00186..aec418913e 100644 --- a/test/ruby/test_pack.rb +++ b/test/ruby/test_pack.rb @@ -428,7 +428,6 @@ class TestPack < Test::Unit::TestCase assert_operator(4, :<=, [1].pack("L!").bytesize) end - require 'rbconfig' def test_pack_unpack_qQ s1 = [578437695752307201, -506097522914230529].pack("q*") s2 = [578437695752307201, 17940646550795321087].pack("Q*") @@ -438,7 +437,6 @@ class TestPack < Test::Unit::TestCase # Note: q! and Q! should not work on platform which has no long long type. # Is there a such platform now? - # @shyouhei: Yes. gcc -ansi is one of such platform. s1 = [578437695752307201, -506097522914230529].pack("q!*") s2 = [578437695752307201, 17940646550795321087].pack("Q!*") assert_equal([578437695752307201, -506097522914230529], s2.unpack("q!*")) @@ -448,7 +446,7 @@ class TestPack < Test::Unit::TestCase assert_equal(8, [1].pack("Q").bytesize) assert_operator(8, :<=, [1].pack("q!").bytesize) assert_operator(8, :<=, [1].pack("Q!").bytesize) - end if RbConfig::CONFIG['HAVE_LONG_LONG'] + end def test_pack_unpack_jJ # Note: we assume that the size of intptr_t and uintptr_t equals to the size @@ -802,13 +800,6 @@ EXPECTED assert_warning(/\A(.* in '\u{3042}'\n)+\z/) { [].pack("\u{3042}") } - - assert_warning(/\A.* in '.*U'\Z/) { - assert_equal "\000", [0].pack("\0U") - } - assert_warning(/\A.* in '.*U'\Z/) { - "\000".unpack("\0U") - } end def test_pack_resize @@ -869,4 +860,20 @@ EXPECTED assert_equal "hogefuga", "aG9nZWZ1Z2E=".unpack1("m") assert_equal "01000001", "A".unpack1("B*") end + + def test_pack_infection + tainted_array_string = ["123456"] + tainted_array_string.first.taint + ['a', 'A', 'Z', 'B', 'b', 'H', 'h', 'u', 'M', 'm', 'P', 'p'].each do |f| + assert_predicate(tainted_array_string.pack(f), :tainted?) + end + end + + def test_unpack_infection + tainted_string = "123456" + tainted_string.taint + ['a', 'A', 'Z', 'B', 'b', 'H', 'h', 'u', 'M', 'm'].each do |f| + assert_predicate(tainted_string.unpack(f).first, :tainted?) + end + end end diff --git a/test/ruby/test_parse.rb b/test/ruby/test_parse.rb index 5f638afa01..b725634a38 100644 --- a/test/ruby/test_parse.rb +++ b/test/ruby/test_parse.rb @@ -6,30 +6,28 @@ require 'stringio' class TestParse < Test::Unit::TestCase def setup @verbose = $VERBOSE + $VERBOSE = nil end def teardown $VERBOSE = @verbose end - def test_error_line - assert_syntax_error('------,,', /\n\z/, 'Message to pipe should end with a newline') - end - def test_else_without_rescue - assert_syntax_error(<<-END, %r":#{__LINE__+2}: else without rescue"o, [__FILE__, __LINE__+1]) + x = eval <<-END, nil, __FILE__, __LINE__+1 begin else 42 end END + assert_equal(42, x) end def test_alias_backref - assert_syntax_error("#{<<~"begin;"}\n#{<<~'end;'}", /can't make alias/) do - begin; + assert_raise(SyntaxError) do + eval <<-END, nil, __FILE__, __LINE__+1 alias $foo $1 - end; + END end end @@ -84,10 +82,10 @@ class TestParse < Test::Unit::TestCase assert_equal([42, 42], [o.Foo, o.Bar]) assert_equal([42, 42], [o::baz, o::qux]) - assert_syntax_error("#{<<~"begin;"}\n#{<<~'end;'}", /Can't set variable/) do - begin; + assert_raise(SyntaxError) do + eval <<-END, nil, __FILE__, __LINE__+1 $1 ||= t.foo 42 - end; + END end def t.bar(x); x + yield; end @@ -152,65 +150,67 @@ class TestParse < Test::Unit::TestCase end def test_dynamic_constant_assignment - assert_syntax_error("#{<<~"begin;"}\n#{<<~'end;'}", /dynamic constant/) do - begin; + assert_raise(SyntaxError) do + Object.new.instance_eval <<-END, __FILE__, __LINE__+1 def foo self::FOO, self::BAR = 1, 2 ::FOO, ::BAR = 1, 2 end - end; + END end - assert_syntax_error("#{<<~"begin;"}\n#{<<~'end;'}", /Can't set variable/) do - begin; + assert_raise(SyntaxError) do + eval <<-END, nil, __FILE__, __LINE__+1 $1, $2 = 1, 2 - end; + END end - assert_syntax_error("#{<<~"begin;"}\n#{<<~'end;'}", /dynamic constant/) do - begin; + assert_raise(SyntaxError) do + Object.new.instance_eval <<-END, __FILE__, __LINE__+1 def foo ::FOO = 1 end - end; + END end c = Class.new c.freeze - assert_valid_syntax("#{<<~"begin;"}\n#{<<~'end;'}") do - begin; + assert_nothing_raised(SyntaxError) do + eval <<-END, nil, __FILE__, __LINE__+1 + if false c::FOO &= 1 ::FOO &= 1 - end; + end + END end - assert_syntax_error("#{<<~"begin;"}\n#{<<~'end;'}", /Can't set variable/) do - begin; + assert_raise(SyntaxError) do + eval <<-END, nil, __FILE__, __LINE__+1 $1 &= 1 - end; + END end end def test_class_module - assert_syntax_error("#{<<~"begin;"}\n#{<<~'end;'}", /must be CONSTANT/) do - begin; + assert_raise(SyntaxError) do + eval <<-END, nil, __FILE__, __LINE__+1 class foo; end - end; + END end - assert_syntax_error("#{<<~"begin;"}\n#{<<~'end;'}", /in method body/) do - begin; + assert_raise(SyntaxError) do + eval <<-END, nil, __FILE__, __LINE__+1 def foo class Foo; end module Bar; end end - end; + END end - assert_valid_syntax("#{<<~"begin;"}\n#{<<~'end;'}") do - begin; + assert_nothing_raised(SyntaxError) do + eval <<-END, nil, __FILE__, __LINE__+1 class Foo 1; end - end; + END end end @@ -270,34 +270,37 @@ class TestParse < Test::Unit::TestCase end def test_bad_arg - assert_syntax_error("#{<<~"begin;"}\n#{<<~'end;'}", /cannot be a constant/) do - begin; + assert_raise(SyntaxError) do + eval <<-END, nil, __FILE__, __LINE__+1 def foo(FOO); end - end; + END end - assert_syntax_error("#{<<~"begin;"}\n#{<<~'end;'}", /cannot be an instance variable/) do - begin; + assert_raise(SyntaxError) do + eval <<-END, nil, __FILE__, __LINE__+1 def foo(@foo); end - end; + END end - assert_syntax_error("#{<<~"begin;"}\n#{<<~'end;'}", /cannot be a global variable/) do - begin; + assert_raise(SyntaxError) do + eval <<-END, nil, __FILE__, __LINE__+1 def foo($foo); end - end; + END end - assert_syntax_error("#{<<~"begin;"}\n#{<<~'end;'}", /cannot be a class variable/) do - begin; + assert_raise(SyntaxError) do + eval <<-END, nil, __FILE__, __LINE__+1 def foo(@@foo); end - end; + END end - assert_syntax_error("#{<<~"begin;"}\n#{<<~'end;'}", /cannot be an instance variable/) do - begin; - o.foo {|; @a| @a = 42 } - end; + o = Object.new + def o.foo(*r); yield(*r); end + + assert_raise(SyntaxError) do + eval <<-END, nil, __FILE__, __LINE__+1 + o.foo 1 {|; @a| @a = 42 } + END end end @@ -349,7 +352,6 @@ class TestParse < Test::Unit::TestCase def test_words assert_equal([], %W( )) - assert_syntax_error('%w[abc', /unterminated list/) end def test_dstr @@ -357,12 +359,11 @@ class TestParse < Test::Unit::TestCase assert_equal("foo 1 bar", "foo #@@foo bar") "1" =~ /(.)/ assert_equal("foo 1 bar", "foo #$1 bar") - assert_equal('foo #@1 bar', eval('"foo #@1 bar"')) end def test_dstr_disallowed_variable bug8375 = '[ruby-core:54885] [Bug #8375]' - %w[@ @. @@ @@1 @@. $ $%].each do |src| + %w[@ @1 @. @@ @@1 @@. $ $%].each do |src| src = '#'+src+' ' str = assert_nothing_raised(SyntaxError, "#{bug8375} #{src.dump}") do break eval('"'+src+'"') @@ -375,29 +376,28 @@ class TestParse < Test::Unit::TestCase assert_nothing_raised { eval(':""') } end - def assert_disallowed_variable(type, noname, invalid) - noname.each do |name| - assert_syntax_error("proc{a = #{name} }", "`#{noname[0]}' without identifiers is not allowed as #{type} variable name") - end + def assert_disallowed_variable(type, noname, *invalid) + assert_syntax_error(noname, "`#{noname}' without identifiers is not allowed as #{type} variable name") invalid.each do |name| - assert_syntax_error("proc {a = #{name} }", "`#{name}' is not allowed as #{type} variable name") + assert_syntax_error(name, "`#{name}' is not allowed as #{type} variable name") end end def test_disallowed_instance_variable - assert_disallowed_variable("an instance", %w[@ @.], %w[]) + assert_disallowed_variable("an instance", *%w[@ @1 @.]) end def test_disallowed_class_variable - assert_disallowed_variable("a class", %w[@@ @@.], %w[@@1]) + assert_disallowed_variable("a class", *%w[@@ @@1 @@.]) end def test_disallowed_gloal_variable - assert_disallowed_variable("a global", %w[$], %w[$%]) + assert_disallowed_variable("a global", *%w[$ $%]) end def test_arg2 o = Object.new + assert_nothing_raised do eval <<-END, nil, __FILE__, __LINE__+1 def o.foo(a=42,*r,z,&b); b.call(r.inject(a*1000+z*100, :+)); end @@ -409,7 +409,6 @@ class TestParse < Test::Unit::TestCase assert_equal(-42100, o.foo(1) {|x| -x }) assert_raise(ArgumentError) { o.foo() } - o = Object.new assert_nothing_raised do eval <<-END, nil, __FILE__, __LINE__+1 def o.foo(a=42,z,&b); b.call(a*1000+z*100); end @@ -419,7 +418,6 @@ class TestParse < Test::Unit::TestCase assert_equal(-42100, o.foo(1) {|x| -x } ) assert_raise(ArgumentError) { o.foo() } - o = Object.new assert_nothing_raised do eval <<-END, nil, __FILE__, __LINE__+1 def o.foo(*r,z,&b); b.call(r.inject(z*100, :+)); end @@ -432,56 +430,31 @@ class TestParse < Test::Unit::TestCase end def test_duplicate_argument - assert_syntax_error("#{<<~"begin;"}\n#{<<~'end;'}", '') do - begin; + assert_raise(SyntaxError) do + eval <<-END, nil, __FILE__, __LINE__+1 1.times {|&b?| } - end; + END end - assert_syntax_error("#{<<~"begin;"}\n#{<<~'end;'}", /duplicated argument/) do - begin; + assert_raise(SyntaxError) do + eval <<-END, nil, __FILE__, __LINE__+1 1.times {|a, a|} - end; + END end - assert_syntax_error("#{<<~"begin;"}\n#{<<~'end;'}", /duplicated argument/) do - begin; + assert_raise(SyntaxError) do + eval <<-END, nil, __FILE__, __LINE__+1 def foo(a, a); end - end; + END end end def test_define_singleton_error - assert_syntax_error("#{<<~"begin;"}\n#{<<~'end;'}", /singleton method for literals/) do - begin; + assert_raise(SyntaxError) do + eval <<-END, nil, __FILE__, __LINE__+1 def ("foo").foo; end - end; - end - end - - def test_op_asgn1_with_block - t = Object.new - a = [] - blk = proc {|x| a << x } - def t.[](_) - yield(:aref) - nil - end - def t.[]=(_, _) - yield(:aset) - end - def t.dummy(_) + END end - eval <<-END, nil, __FILE__, __LINE__+1 - t[42, &blk] ||= 42 - END - assert_equal([:aref, :aset], a) - a.clear - eval <<-END, nil, __FILE__, __LINE__+1 - t[42, &blk] ||= t.dummy 42 # command_asgn test - END - assert_equal([:aref, :aset], a) - blk end def test_backquote @@ -514,13 +487,13 @@ class TestParse < Test::Unit::TestCase mesg = 'from the backslash through the invalid char' e = assert_syntax_error('"\xg1"', /hex escape/) - assert_equal(' ^~'"\n", e.message.lines.last, mesg) + assert_equal(' ^', e.message.lines.last, mesg) e = assert_syntax_error('"\u{1234"', 'unterminated Unicode escape') - assert_equal(' ^'"\n", e.message.lines.last, mesg) + assert_equal(' ^', e.message.lines.last, mesg) e = assert_syntax_error('"\u{xxxx}"', 'invalid Unicode escape') - assert_equal(' ^'"\n", e.message.lines.last, mesg) + assert_equal(' ^', e.message.lines.last, mesg) e = assert_syntax_error('"\u{xxxx', 'Unicode escape') assert_pattern_list([ @@ -531,14 +504,14 @@ class TestParse < Test::Unit::TestCase / \^/, /\n/, /.*: unterminated string.*\n.*\n/, - / \^\n/, + / \^/, ], e.message) e = assert_syntax_error('"\M1"', /escape character syntax/) - assert_equal(' ^~~'"\n", e.message.lines.last, mesg) + assert_equal(' ^~~', e.message.lines.last, mesg) e = assert_syntax_error('"\C1"', /escape character syntax/) - assert_equal(' ^~~'"\n", e.message.lines.last, mesg) + assert_equal(' ^~~', e.message.lines.last, mesg) src = '"\xD0\u{90'"\n""000000000000000000000000" assert_syntax_error(src, /:#{__LINE__}: unterminated/o) @@ -549,58 +522,27 @@ class TestParse < Test::Unit::TestCase assert_equal("\x81", eval('"\C-\M-a"')) assert_equal("\177", eval('"\c?"')) - - assert_warning(/use \\C-\\s/) {assert_equal("\x00", eval('"\C- "'))} - assert_warning(/use \\M-\\s/) {assert_equal("\xa0", eval('"\M- "'))} - assert_warning(/use \\M-\\C-\\s/) {assert_equal("\x80", eval('"\M-\C- "'))} - assert_warning(/use \\C-\\M-\\s/) {assert_equal("\x80", eval('"\C-\M- "'))} - assert_warning(/use \\t/) {assert_equal("\x09", eval("\"\\C-\t\""))} - assert_warning(/use \\M-\\t/) {assert_equal("\x89", eval("\"\\M-\t\""))} - assert_warning(/use \\M-\\t/) {assert_equal("\x89", eval("\"\\M-\\C-\t\""))} - assert_warning(/use \\M-\\t/) {assert_equal("\x89", eval("\"\\C-\\M-\t\""))} - assert_syntax_error("\"\\C-\x01\"", 'Invalid escape character syntax') - assert_syntax_error("\"\\M-\x01\"", 'Invalid escape character syntax') - assert_syntax_error("\"\\M-\\C-\x01\"", 'Invalid escape character syntax') - assert_syntax_error("\"\\C-\\M-\x01\"", 'Invalid escape character syntax') end def test_question - assert_syntax_error('?', /incomplete/) - assert_syntax_error('? ', /unexpected/) - assert_syntax_error("?\n", /unexpected/) - assert_syntax_error("?\t", /unexpected/) - assert_syntax_error("?\v", /unexpected/) - assert_syntax_error("?\r", /unexpected/) - assert_syntax_error("?\f", /unexpected/) - assert_syntax_error(" ?a\x8a".force_encoding("utf-8"), /invalid multibyte/) + assert_raise(SyntaxError) { eval('?') } + assert_raise(SyntaxError) { eval('? ') } + assert_raise(SyntaxError) { eval("?\n") } + assert_raise(SyntaxError) { eval("?\t") } + assert_raise(SyntaxError) { eval("?\v") } + assert_raise(SyntaxError) { eval("?\r") } + assert_raise(SyntaxError) { eval("?\f") } + assert_raise(SyntaxError) { eval("?\f") } + assert_raise(SyntaxError) { eval(" ?a\x8a".force_encoding("utf-8")) } assert_equal("\u{1234}", eval("?\u{1234}")) assert_equal("\u{1234}", eval('?\u{1234}')) - assert_equal("\u{1234}", eval('?\u1234')) - assert_syntax_error('?\u{41 42}', 'Multiple codepoints at single character literal') - e = assert_syntax_error('"#{?\u123}"', 'invalid Unicode escape') - assert_not_match(/end-of-input/, e.message) - - assert_warning(/use ?\\C-\\s/) {assert_equal("\x00", eval('?\C- '))} - assert_warning(/use ?\\M-\\s/) {assert_equal("\xa0", eval('?\M- '))} - assert_warning(/use ?\\M-\\C-\\s/) {assert_equal("\x80", eval('?\M-\C- '))} - assert_warning(/use ?\\C-\\M-\\s/) {assert_equal("\x80", eval('?\C-\M- '))} - assert_warning(/use ?\\t/) {assert_equal("\x09", eval("?\\C-\t"))} - assert_warning(/use ?\\M-\\t/) {assert_equal("\x89", eval("?\\M-\t"))} - assert_warning(/use ?\\M-\\t/) {assert_equal("\x89", eval("?\\M-\\C-\t"))} - assert_warning(/use ?\\M-\\t/) {assert_equal("\x89", eval("?\\C-\\M-\t"))} - assert_syntax_error("?\\C-\x01", 'Invalid escape character syntax') - assert_syntax_error("?\\M-\x01", 'Invalid escape character syntax') - assert_syntax_error("?\\M-\\C-\x01", 'Invalid escape character syntax') - assert_syntax_error("?\\C-\\M-\x01", 'Invalid escape character syntax') end def test_percent assert_equal(:foo, eval('%s(foo)')) - assert_syntax_error('%s', /unterminated quoted string/) - assert_syntax_error('%ss', /unknown type/) - assert_syntax_error('%z()', /unknown type/) - assert_syntax_error("%\u3042", /unknown type/) - assert_syntax_error("%q\u3042", /unknown type/) + assert_raise(SyntaxError) { eval('%s') } + assert_raise(SyntaxError) { eval('%ss') } + assert_raise(SyntaxError) { eval('%z()') } end def test_symbol @@ -619,21 +561,24 @@ class TestParse < Test::Unit::TestCase assert_equal(:foobar, eval(':"foo\u{}bar"')) assert_equal(:foobar, eval(':"foo\u{ }bar"')) end - - assert_syntax_error(':@@', /is not allowed/) - assert_syntax_error(':@@1', /is not allowed/) - assert_syntax_error(':@', /is not allowed/) - assert_syntax_error(':@1', /is not allowed/) end def test_parse_string - assert_syntax_error("/\n", /unterminated/) + assert_raise(SyntaxError) do + eval <<-END, nil, __FILE__, __LINE__+1 +/ + END + end end def test_here_document x = nil - assert_syntax_error("<\<FOO\n", /can't find string "FOO"/) + assert_raise(SyntaxError) do + eval %Q( +<\<FOO + ) + end assert_nothing_raised(SyntaxError) do x = eval %q( @@ -644,11 +589,23 @@ FOO end assert_equal "\#$\n", x - assert_syntax_error("<\<\"\n", /unterminated here document identifier/) + assert_raise(SyntaxError) do + eval %Q( +<\<\" + ) + end - assert_syntax_error("<<``\n", /can't find string ""/) + assert_raise(SyntaxError) do + eval %q( +<<`` + ) + end - assert_syntax_error("<<--\n", /unexpected <</) + assert_raise(SyntaxError) do + eval %q( +<<-- + ) + end assert_nothing_raised(SyntaxError) do x = eval %q( @@ -711,44 +668,37 @@ x = __ENCODING__ end def test_embedded_rd - assert_valid_syntax("=begin\n""=end") - assert_valid_syntax("=begin\n""=end\0") - assert_valid_syntax("=begin\n""=end\C-d") - assert_valid_syntax("=begin\n""=end\C-z") - end - - def test_embedded_rd_error - error = 'embedded document meets end of file' - assert_syntax_error("=begin\n", error) - assert_syntax_error("=begin", error) + assert_raise(SyntaxError) do + eval <<-END, nil, __FILE__, __LINE__+1 +=begin + END + end end def test_float - assert_predicate(assert_warning(/out of range/) {eval("1e10000")}, :infinite?) - assert_syntax_error('1_E', /trailing `_'/) - assert_syntax_error('1E1E1', /unexpected constant/) + assert_equal(1.0/0, eval("1e10000")) + assert_raise(SyntaxError) { eval('1_E') } + assert_raise(SyntaxError) { eval('1E1E1') } end def test_global_variable - assert_equal(nil, assert_warning(/not initialized/) {eval('$-x')}) + assert_equal(nil, eval('$-x')) assert_equal(nil, eval('alias $preserve_last_match $&')) assert_equal(nil, eval('alias $& $test_parse_foobarbazqux')) $test_parse_foobarbazqux = nil assert_equal(nil, $&) assert_equal(nil, eval('alias $& $preserve_last_match')) - assert_syntax_error('a = $#', /as a global variable name\na = \$\#\n \^~$/) + assert_raise(SyntaxError) { eval('$#') } end def test_invalid_instance_variable - pattern = /without identifiers is not allowed as an instance variable name/ - assert_syntax_error('@%', pattern) - assert_syntax_error('@', pattern) + assert_raise(SyntaxError) { eval('@#') } + assert_raise(SyntaxError) { eval('@') } end def test_invalid_class_variable - pattern = /without identifiers is not allowed as a class variable name/ - assert_syntax_error('@@%', pattern) - assert_syntax_error('@@', pattern) + assert_raise(SyntaxError) { eval('@@1') } + assert_raise(SyntaxError) { eval('@@') } end def test_invalid_char @@ -768,23 +718,56 @@ x = __ENCODING__ end def test_unassignable - assert_syntax_error(%q(self = 1), /Can't change the value of self/) - assert_syntax_error(%q(nil = 1), /Can't assign to nil/) - assert_syntax_error(%q(true = 1), /Can't assign to true/) - assert_syntax_error(%q(false = 1), /Can't assign to false/) - assert_syntax_error(%q(__FILE__ = 1), /Can't assign to __FILE__/) - assert_syntax_error(%q(__LINE__ = 1), /Can't assign to __LINE__/) - assert_syntax_error(%q(__ENCODING__ = 1), /Can't assign to __ENCODING__/) - assert_syntax_error("def foo; FOO = 1; end", /dynamic constant assignment/) - assert_syntax_error("x, true", /Can't assign to true/) + assert_raise(SyntaxError) do + eval %q(self = 1) + end + assert_raise(SyntaxError) do + eval %q(nil = 1) + end + assert_raise(SyntaxError) do + eval %q(true = 1) + end + assert_raise(SyntaxError) do + eval %q(false = 1) + end + assert_raise(SyntaxError) do + eval %q(__FILE__ = 1) + end + assert_raise(SyntaxError) do + eval %q(__LINE__ = 1) + end + assert_raise(SyntaxError) do + eval %q(__ENCODING__ = 1) + end + assert_raise(SyntaxError) do + eval <<-END, nil, __FILE__, __LINE__+1 + def foo + FOO = 1 + end + END + end + assert_raise(SyntaxError) do + eval "#{<<~"begin;"}\n#{<<~'end;'}", nil, __FILE__, __LINE__+1 + begin; + x, true + end; + end end def test_block_dup - assert_syntax_error("foo(&proc{}) {}", /both block arg and actual block/) + assert_raise(SyntaxError) do + eval <<-END, nil, __FILE__, __LINE__+1 + foo(&proc{}) {} + END + end end def test_set_backref - assert_syntax_error("$& = 1", /Can't set variable/) + assert_raise(SyntaxError) do + eval <<-END, nil, __FILE__, __LINE__+1 + $& = 1 + END + end end def test_arg_concat @@ -802,34 +785,42 @@ x = __ENCODING__ end def test_void_expr_stmts_value + # This test checks if void contexts are warned correctly. + # Thus, warnings MUST NOT be suppressed. + $VERBOSE = true + stderr = $stderr + $stderr = StringIO.new("") x = 1 - useless_use = /useless use/ - unused = /unused/ - assert_nil assert_warning(useless_use) {eval("x; nil")} - assert_nil assert_warning(useless_use) {eval("1+1; nil")} - assert_nil assert_warning('') {eval("1.+(1); nil")} - assert_nil assert_warning(useless_use) {eval("TestParse; nil")} - assert_nil assert_warning(useless_use) {eval("::TestParse; nil")} - assert_nil assert_warning(useless_use) {eval("x..x; nil")} - assert_nil assert_warning(useless_use) {eval("x...x; nil")} - assert_nil assert_warning(unused) {eval("self; nil")} - assert_nil assert_warning(unused) {eval("nil; nil")} - assert_nil assert_warning(unused) {eval("true; nil")} - assert_nil assert_warning(unused) {eval("false; nil")} - assert_nil assert_warning(useless_use) {eval("defined?(1); nil")} + assert_nil eval("x; nil") + assert_nil eval("1+1; nil") + assert_nil eval("1.+(1); nil") + assert_nil eval("TestParse; nil") + assert_nil eval("::TestParse; nil") + assert_nil eval("x..x; nil") + assert_nil eval("x...x; nil") + assert_nil eval("self; nil") + assert_nil eval("nil; nil") + assert_nil eval("true; nil") + assert_nil eval("false; nil") + assert_nil eval("defined?(1); nil") assert_equal 1, x - assert_syntax_error("1; next; 2", /Invalid next/) + assert_raise(SyntaxError) do + eval %q(1; next; 2) + end + + assert_equal(13, $stderr.string.lines.to_a.size) + $stderr = stderr end def test_assign_in_conditional - assert_warning(/`= literal' in conditional/) do + assert_nothing_raised do eval <<-END, nil, __FILE__, __LINE__+1 (x, y = 1, 2) ? 1 : 2 END end - assert_warning(/`= literal' in conditional/) do + assert_nothing_raised do eval <<-END, nil, __FILE__, __LINE__+1 if @x = true 1 @@ -841,13 +832,13 @@ x = __ENCODING__ end def test_literal_in_conditional - assert_warning(/string literal in condition/) do + assert_nothing_raised do eval <<-END, nil, __FILE__, __LINE__+1 "foo" ? 1 : 2 END end - assert_warning(/regex literal in condition/) do + assert_nothing_raised do x = "bar" eval <<-END, nil, __FILE__, __LINE__+1 /foo#{x}baz/ ? 1 : 2 @@ -860,13 +851,13 @@ x = __ENCODING__ END end - assert_warning(/string literal in flip-flop/) do + assert_nothing_raised do eval <<-END, nil, __FILE__, __LINE__+1 ("foo".."bar") ? 1 : 2 END end - assert_warning(/literal in condition/) do + assert_nothing_raised do x = "bar" eval <<-END, nil, __FILE__, __LINE__+1 :"foo#{"x"}baz" ? 1 : 2 @@ -876,7 +867,11 @@ x = __ENCODING__ end def test_no_blockarg - assert_syntax_error("yield(&:+)", /block argument should not be given/) + assert_raise(SyntaxError) do + eval <<-END, nil, __FILE__, __LINE__+1 + yield(&:+) + END + end end def test_method_block_location @@ -893,8 +888,10 @@ x = __ENCODING__ assert_equal(expected, actual, bug5614) end - def test_no_shadowing_variable_warning - assert_no_warning(/shadowing outer local variable/) {eval("a=1; tap {|a|}")} + def test_shadowing_variable + assert_warning(/shadowing outer local variable/) {eval("a=1; tap {|a|}")} + a = "\u{3042}" + assert_warning(/#{a}/o) {eval("#{a}=1; tap {|#{a}|}")} end def test_unused_variable @@ -902,12 +899,10 @@ x = __ENCODING__ assert_warning(/assigned but unused variable/) {o.instance_eval("def foo; a=1; nil; end")} assert_warning(/assigned but unused variable/) {o.instance_eval("def bar; a=1; a(); end")} a = "\u{3042}" - assert_warning(/#{a}/) {o.instance_eval("def foo0; #{a}=1; nil; end")} - assert_warning(/assigned but unused variable/) {o.instance_eval("def foo1; tap {a=1; a()}; end")} - assert_warning('') {o.instance_eval("def bar1; a=a=1; nil; end")} - assert_warning(/assigned but unused variable/) {o.instance_eval("def bar2; a, = 1, 2; end")} - assert_warning('') {o.instance_eval("def marg1(a); nil; end")} - assert_warning('') {o.instance_eval("def marg2((a)); nil; end")} + assert_warning(/#{a}/) {o.instance_eval("def foo; #{a}=1; nil; end")} + o = Object.new + assert_warning(/assigned but unused variable/) {o.instance_eval("def foo; tap {a=1; a()}; end")} + assert_warning('') {o.instance_eval("def bar; a=a=1; nil; end")} end def test_named_capture_conflict @@ -1048,26 +1043,35 @@ x = __ENCODING__ end def test_unexpected_token_error - assert_syntax_error('"x"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', /unexpected/) + assert_raise(SyntaxError) do + eval('"x"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx') + end end def test_unexpected_token_after_numeric - assert_syntax_error('0000xyz', /^ \^~~\Z/) - assert_syntax_error('1.2i1.1', /^ \^~~\Z/) - assert_syntax_error('1.2.3', /^ \^~\Z/) + assert_raise_with_message(SyntaxError, /^ \^~~\z/) do + eval('0000xyz') + end + assert_raise_with_message(SyntaxError, /^ \^~~\z/) do + eval('1.2i1.1') + end end def test_truncated_source_line - e = assert_syntax_error("'0123456789012345678901234567890123456789' abcdefghijklmnopqrstuvwxyz0123456789 0123456789012345678901234567890123456789", - /unexpected local variable or method/) + e = assert_raise_with_message(SyntaxError, /unexpected tIDENTIFIER/) do + eval("'0123456789012345678901234567890123456789' abcdefghijklmnopqrstuvwxyz0123456789 0123456789012345678901234567890123456789") + end line = e.message.lines[1] assert_operator(line, :start_with?, "...") assert_operator(line, :end_with?, "...\n") end def test_unterminated_regexp_error - e = assert_syntax_error("/x", /unterminated regexp meets end of file/) - assert_not_match(/unexpected tSTRING_END/, e.message) + e = assert_raise(SyntaxError) do + eval("/x") + end.message + assert_match(/unterminated regexp meets end of file/, e) + assert_not_match(/unexpected tSTRING_END/, e) end def test_lparenarg @@ -1077,8 +1081,7 @@ x = __ENCODING__ end o.instance_eval {i (-1.3).abs} assert_equal(1.3, o.x) - o.i(nil) - o.instance_eval {i = 0; i (-1.3).abs; i} + o.instance_eval {i = 0; i (-1.3).abs} assert_equal(1.3, o.x) end @@ -1087,85 +1090,13 @@ x = __ENCODING__ $VERBOSE = true x = 1 eval("if false; 0 < x < 2; end") - x end end - def test_eof - assert_equal(42, eval("42\0""end")) - assert_equal(42, eval("42\C-d""end")) - assert_equal(42, eval("42\C-z""end")) - end - def test_eof_in_def - assert_syntax_error("def m\n\0""end", /unexpected/) - assert_syntax_error("def m\n\C-d""end", /unexpected/) - assert_syntax_error("def m\n\C-z""end", /unexpected/) - end - - def test_location_of_invalid_token - assert_syntax_error('class xxx end', /^ \^~~\Z/) - end - - def test_whitespace_warning - assert_syntax_error("\\foo", /backslash/) - assert_syntax_error("\\ ", /escaped space/) - assert_syntax_error("\\\t", /escaped horizontal tab/) - assert_syntax_error("\\\f", /escaped form feed/) - assert_syntax_error("\\\r", /escaped carriage return/) - assert_warn(/middle of line/) {eval(" \r ")} - assert_syntax_error("\\\v", /escaped vertical tab/) - end - - def test_command_def_cmdarg - assert_valid_syntax("\n#{<<~"begin;"}\n#{<<~'end;'}") - begin; - m def x(); end - 1.tap do end - end; - end - - NONASCII_CONSTANTS = [ - *%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| - m = Module.new - assert_not_operator(m, :const_defined?, n) - assert_raise_with_message(NameError, /uninitialized/) do - m.const_get(n) - end - assert_nil(eval("defined?(m::#{n})")) - - v = yield m, n - - assert_operator(m, :const_defined?, n) - assert_equal("constant", eval("defined?(m::#{n})")) - assert_same(v, m.const_get(n)) - - m.__send__(:remove_const, n) - assert_not_operator(m, :const_defined?, n) - assert_nil(eval("defined?(m::#{n})")) - end - end - - def test_nonascii_const_set - assert_nonascii_const do |m, n| - m.const_set(n, 42) - end - end - - def test_nonascii_constant - assert_nonascii_const do |m, n| - m.module_eval("class #{n}; self; end") - end - end - - def test_cdmarg_after_command_args_and_tlbrace_arg - assert_valid_syntax('let () { m(a) do; end }') + assert_raise(SyntaxError) { eval("def m\n\0""end") } + assert_raise(SyntaxError) { eval("def m\n\C-d""end") } + assert_raise(SyntaxError) { eval("def m\n\C-z""end") } end def test_void_value_in_command_rhs @@ -1174,122 +1105,6 @@ x = __ENCODING__ assert_equal(1, ex.message.scan(w).size, "same #{w.inspect} warning should be just once") end - def eval_separately(code) - Class.new.class_eval(code) - end - - def assert_raise_separately(error, message, code) - assert_raise_with_message(error, message) do - eval_separately(code) - end - end - - def assert_ractor_shareable(obj) - assert Ractor.shareable?(obj), ->{"Expected #{mu_pp(obj)} to be ractor shareable"} - end - - def assert_not_ractor_shareable(obj) - assert !Ractor.shareable?(obj), ->{"Expected #{mu_pp(obj)} not to be ractor shareable"} - end - - def test_shareable_constant_value_invalid - assert_warning(/invalid value/) do - assert_valid_syntax("# shareable_constant_value: invalid-option", verbose: true) - end - end - - def test_shareable_constant_value_ignored - assert_warning(/ignored/) do - assert_valid_syntax("nil # shareable_constant_value: true", verbose: true) - end - end - - def test_shareable_constant_value_simple - obj = [['unsharable_value']] - a, b, c = eval_separately("#{<<~"begin;"}\n#{<<~'end;'}") - begin; - # shareable_constant_value: experimental_everything - A = [[1]] - # shareable_constant_value: none - B = [[2]] - # shareable_constant_value: literal - C = [["shareable", "constant#{nil}"]] - D = A - - [A, B, C] - end; - assert_ractor_shareable(a) - assert_not_ractor_shareable(b) - assert_ractor_shareable(c) - assert_equal([1], a[0]) - assert_ractor_shareable(a[0]) - - a, obj = eval_separately(<<~'end;') - # shareable_constant_value: experimental_copy - obj = [["unshareable"]] - A = obj - [A, obj] - end; - - assert_ractor_shareable(a) - assert_not_ractor_shareable(obj) - assert_equal obj, a - assert !obj.equal?(a) - end - - def test_shareable_constant_value_nested - a, b = eval_separately("#{<<~"begin;"}\n#{<<~'end;'}") - begin; - # shareable_constant_value: none - class X - # shareable_constant_value: experimental_everything - var = [[1]] - A = var - end - B = [] - [X::A, B] - end; - assert_ractor_shareable(a) - assert_not_ractor_shareable(b) - assert_equal([1], a[0]) - assert_ractor_shareable(a[0]) - end - - def test_shareable_constant_value_unshareable_literal - assert_raise_separately(Ractor::IsolationError, /unshareable/, - "#{<<~"begin;"}\n#{<<~'end;'}") - begin; - # shareable_constant_value: literal - C = ["Not " + "shareable"] - end; - end - - def test_shareable_constant_value_nonliteral - assert_raise_separately(Ractor::IsolationError, /unshareable/, "#{<<~"begin;"}\n#{<<~'end;'}") - begin; - # shareable_constant_value: literal - var = [:not_frozen] - C = var - end; - - assert_raise_separately(Ractor::IsolationError, /unshareable/, "#{<<~"begin;"}\n#{<<~'end;'}") - begin; - # shareable_constant_value: literal - D = begin [] end - end; - end - - def test_shareable_constant_value_unfrozen - assert_raise_separately(Ractor::Error, /does not freeze object correctly/, - "#{<<~"begin;"}\n#{<<~'end;'}") - begin; - # shareable_constant_value: experimental_everything - o = Object.new - def o.freeze; self; end - C = [o] - end; - end - =begin def test_past_scope_variable assert_warning(/past scope/) {catch {|tag| eval("BEGIN{throw tag}; tap {a = 1}; a")}} diff --git a/test/ruby/test_path.rb b/test/ruby/test_path.rb index b35e942a2a..6af4fb6ac0 100644 --- a/test/ruby/test_path.rb +++ b/test/ruby/test_path.rb @@ -236,14 +236,10 @@ class TestPath < Test::Unit::TestCase assert_equal(ext, File.extname('.a/b/d/test.rb')) unless /mswin|bccwin|mingw/ =~ RUBY_PLATFORM # trailing spaces and dots are ignored on NTFS. - ext = '.' - end - assert_equal(ext, File.extname('a.rb.')) - if /mswin|bccwin|mingw/ =~ RUBY_PLATFORM - # trailing spaces and dots are ignored on NTFS. ext = '' end - assert_equal(ext, File.extname('a.')) + assert_equal(ext, File.extname('a.rb.')) + assert_equal('', File.extname('a.')) assert_equal('', File.extname('.x')) assert_equal('', File.extname('..x')) end diff --git a/test/ruby/test_pattern_matching.rb b/test/ruby/test_pattern_matching.rb deleted file mode 100644 index 243a4cd2bd..0000000000 --- a/test/ruby/test_pattern_matching.rb +++ /dev/null @@ -1,1495 +0,0 @@ -# frozen_string_literal: true -require 'test/unit' - -experimental, Warning[:experimental] = Warning[:experimental], false # suppress "warning: Pattern matching is experimental, and the behavior may change in future versions of Ruby!" -eval "\n#{<<~'END_of_GUARD'}", binding, __FILE__, __LINE__ -class TestPatternMatching < Test::Unit::TestCase - class C - class << self - attr_accessor :keys - end - - def initialize(obj) - @obj = obj - end - - def deconstruct - @obj - end - - def deconstruct_keys(keys) - C.keys = keys - @obj - end - end - - def test_basic - assert_block do - case 0 - in 0 - true - else - false - end - end - - assert_block do - case 0 - in 1 - false - else - true - end - end - - assert_raise(NoMatchingPatternError) do - case 0 - in 1 - false - end - end - - begin - o = [0] - case o - in 1 - false - end - rescue => e - assert_match o.inspect, e.message - end - - assert_block do - begin - true - ensure - case 0 - in 0 - false - end - end - end - - assert_block do - begin - true - ensure - case 0 - in 1 - else - false - end - end - end - - assert_raise(NoMatchingPatternError) do - begin - ensure - case 0 - in 1 - end - end - end - - assert_block do - # suppress "warning: Pattern matching is experimental, and the behavior may change in future versions of Ruby!" - experimental, Warning[:experimental] = Warning[:experimental], false - eval(%q{ - case true - in a - a - end - }) - ensure - Warning[:experimental] = experimental - end - - assert_block do - tap do |a| - tap do - case true - in a - a - end - end - end - end - - assert_raise(NoMatchingPatternError) do - o = BasicObject.new - def o.match - case 0 - in 1 - end - end - o.match - end - end - - def test_modifier - assert_block do - case 0 - in a if a == 0 - true - end - end - - assert_block do - case 0 - in a if a != 0 - else - true - end - end - - assert_block do - case 0 - in a unless a != 0 - true - end - end - - assert_block do - case 0 - in a unless a == 0 - else - true - end - end - end - - def test_as_pattern - assert_block do - case 0 - in 0 => a - a == 0 - end - end - end - - def test_alternative_pattern - assert_block do - [0, 1].all? do |i| - case i - in 0 | 1 - true - end - end - end - - assert_block do - case 0 - in _ | _a - true - end - end - - assert_syntax_error(%q{ - case 0 - in a | 0 - end - }, /illegal variable in alternative pattern/) - end - - def test_var_pattern - # NODE_DASGN_CURR - assert_block do - case 0 - in a - a == 0 - end - end - - # NODE_DASGN - b = 0 - assert_block do - case 1 - in b - b == 1 - end - end - - # NODE_LASGN - case 0 - in c - assert_equal(0, c) - else - flunk - end - - assert_syntax_error(%q{ - case 0 - in ^a - end - }, /no such local variable/) - - assert_syntax_error(%q{ - case 0 - in a, a - end - }, /duplicated variable name/) - - assert_block do - case [0, 1, 2, 3] - in _, _, _a, _a - true - end - end - - assert_syntax_error(%q{ - case 0 - in a, {a:} - end - }, /duplicated variable name/) - - assert_syntax_error(%q{ - case 0 - in a, {"a":} - end - }, /duplicated variable name/) - - assert_block do - case [0, "1"] - in a, "#{case 1; in a; a; end}" - true - end - end - - assert_syntax_error(%q{ - case [0, "1"] - in a, "#{case 1; in a; a; end}", a - end - }, /duplicated variable name/) - - assert_block do - case 0 - in a - assert_equal(0, a) - true - in a - flunk - end - end - - assert_syntax_error(%q{ - 0 => [a, a] - }, /duplicated variable name/) - end - - def test_literal_value_pattern - assert_block do - case [nil, self, true, false] - in [nil, self, true, false] - true - end - end - - assert_block do - case [0d170, 0D170, 0xaa, 0xAa, 0xAA, 0Xaa, 0XAa, 0XaA, 0252, 0o252, 0O252] - in [0d170, 0D170, 0xaa, 0xAa, 0xAA, 0Xaa, 0XAa, 0XaA, 0252, 0o252, 0O252] - true - end - - case [0b10101010, 0B10101010, 12r, 12.3r, 1i, 12.3ri] - in [0b10101010, 0B10101010, 12r, 12.3r, 1i, 12.3ri] - true - end - end - - assert_block do - x = 'x' - case ['a', 'a', x] - in ['a', "a", "#{x}"] - true - end - end - - assert_block do - case ["a\n"] - in [<<END] -a -END - true - end - end - - assert_block do - case [:a, :"a"] - in [:a, :"a"] - true - end - end - - assert_block do - case [0, 1, 2, 3, 4, 5] - in [0..1, 0...2, 0.., 0..., (...5), (..5)] - true - end - end - - assert_syntax_error(%q{ - case 0 - in a..b - end - }, /unexpected/) - - assert_block do - case 'abc' - in /a/ - true - end - end - - assert_block do - case 0 - in ->(i) { i == 0 } - true - end - end - - assert_block do - case [%(a), %q(a), %Q(a), %w(a), %W(a), %i(a), %I(a), %s(a), %x(echo a), %(), %q(), %Q(), %w(), %W(), %i(), %I(), %s(), 'a'] - in [%(a), %q(a), %Q(a), %w(a), %W(a), %i(a), %I(a), %s(a), %x(echo a), %(), %q(), %Q(), %w(), %W(), %i(), %I(), %s(), %r(a)] - true - end - end - - assert_block do - case [__FILE__, __LINE__ + 1, __ENCODING__] - in [__FILE__, __LINE__, __ENCODING__] - true - end - end - end - - def test_constant_value_pattern - assert_block do - case 0 - in Integer - true - end - end - - assert_block do - case 0 - in Object::Integer - true - end - end - - assert_block do - case 0 - in ::Object::Integer - true - end - end - end - - def test_pin_operator_value_pattern - assert_block do - a = /a/ - case 'abc' - in ^a - true - end - end - - assert_block do - case [0, 0] - in a, ^a - a == 0 - end - end - end - - def test_array_pattern - assert_block do - [[0], C.new([0])].all? do |i| - case i - in 0,; - true - end - end - end - - assert_block do - [[0, 1], C.new([0, 1])].all? do |i| - case i - in 0,; - true - end - end - end - - assert_block do - [[], C.new([])].all? do |i| - case i - in 0,; - else - true - end - end - end - - assert_block do - [[0, 1], C.new([0, 1])].all? do |i| - case i - in 0, 1 - true - end - end - end - - assert_block do - [[0], C.new([0])].all? do |i| - case i - in 0, 1 - else - true - end - end - end - - assert_block do - [[], C.new([])].all? do |i| - case i - in *a - a == [] - end - end - end - - assert_block do - [[0], C.new([0])].all? do |i| - case i - in *a - a == [0] - end - end - end - - assert_block do - [[0], C.new([0])].all? do |i| - case i - in *a, 0, 1 - raise a # suppress "unused variable: a" warning - else - true - end - end - end - - assert_block do - [[0, 1], C.new([0, 1])].all? do |i| - case i - in *a, 0, 1 - a == [] - end - end - end - - assert_block do - [[0, 1, 2], C.new([0, 1, 2])].all? do |i| - case i - in *a, 1, 2 - a == [0] - end - end - end - - assert_block do - [[], C.new([])].all? do |i| - case i - in *; - true - end - end - end - - assert_block do - [[0], C.new([0])].all? do |i| - case i - in *, 0, 1 - else - true - end - end - end - - assert_block do - [[0, 1], C.new([0, 1])].all? do |i| - case i - in *, 0, 1 - true - end - end - end - - assert_block do - [[0, 1, 2], C.new([0, 1, 2])].all? do |i| - case i - in *, 1, 2 - true - end - end - end - - assert_block do - case C.new([0]) - in C(0) - true - end - end - - assert_block do - case C.new([0]) - in Array(0) - else - true - end - end - - assert_block do - case C.new([]) - in C() - true - end - end - - assert_block do - case C.new([]) - in Array() - else - true - end - end - - assert_block do - case C.new([0]) - in C[0] - true - end - end - - assert_block do - case C.new([0]) - in Array[0] - else - true - end - end - - assert_block do - case C.new([]) - in C[] - true - end - end - - assert_block do - case C.new([]) - in Array[] - else - true - end - end - - assert_block do - case [] - in [] - true - end - end - - assert_block do - case C.new([]) - in [] - true - end - end - - assert_block do - case [0] - in [0] - true - end - end - - assert_block do - case C.new([0]) - in [0] - true - end - end - - assert_block do - case [0] - in [0,] - true - end - end - - assert_block do - case [0, 1] - in [0,] - true - end - end - - assert_block do - case [] - in [0, *a] - raise a # suppress "unused variable: a" warning - else - true - end - end - - assert_block do - case [0] - in [0, *a] - a == [] - end - end - - assert_block do - case [0] - in [0, *a, 1] - raise a # suppress "unused variable: a" warning - else - true - end - end - - assert_block do - case [0, 1] - in [0, *a, 1] - a == [] - end - end - - assert_block do - case [0, 1, 2] - in [0, *a, 2] - a == [1] - end - end - - assert_block do - case [] - in [0, *] - else - true - end - end - - assert_block do - case [0] - in [0, *] - true - end - end - - assert_block do - case [0, 1] - in [0, *] - true - end - end - - assert_block do - case [] - in [0, *a] - raise a # suppress "unused variable: a" warning - else - true - end - end - - assert_block do - case [0] - in [0, *a] - a == [] - end - end - - assert_block do - case [0, 1] - in [0, *a] - a == [1] - end - end - - assert_block do - case [0] - in [0, *, 1] - else - true - end - end - - assert_block do - case [0, 1] - in [0, *, 1] - true - end - end - end - - def test_find_pattern - [0, 1, 2] => [*, 1 => a, *] - assert_equal(1, a) - - [0, 1, 2] => [*a, 1 => b, *c] - assert_equal([0], a) - assert_equal(1, b) - assert_equal([2], c) - - assert_block do - case [0, 1, 2] - in [*, 9, *] - false - else - true - end - end - - assert_block do - case [0, 1, 2] - in [*, Integer, String, *] - false - else - true - end - end - - [0, 1, 2] => [*a, 1 => b, 2 => c, *d] - assert_equal([0], a) - assert_equal(1, b) - assert_equal(2, c) - assert_equal([], d) - - case [0, 1, 2] - in *, 1 => a, *; - assert_equal(1, a) - end - - assert_block do - case [0, 1, 2] - in String(*, 1, *) - false - in Array(*, 1, *) - true - end - end - - assert_block do - case [0, 1, 2] - in String[*, 1, *] - false - in Array[*, 1, *] - true - end - end - end - - def test_hash_pattern - assert_block do - [{}, C.new({})].all? do |i| - case i - in a: 0 - else - true - end - end - end - - assert_block do - [{a: 0}, C.new({a: 0})].all? do |i| - case i - in a: 0 - true - end - end - end - - assert_block do - [{a: 0, b: 1}, C.new({a: 0, b: 1})].all? do |i| - case i - in a: 0 - true - end - end - end - - assert_block do - [{a: 0}, C.new({a: 0})].all? do |i| - case i - in a: 0, b: 1 - else - true - end - end - end - - assert_block do - [{a: 0, b: 1}, C.new({a: 0, b: 1})].all? do |i| - case i - in a: 0, b: 1 - true - end - end - end - - assert_block do - [{a: 0, b: 1, c: 2}, C.new({a: 0, b: 1, c: 2})].all? do |i| - case i - in a: 0, b: 1 - true - end - end - end - - assert_block do - [{}, C.new({})].all? do |i| - case i - in a: - raise a # suppress "unused variable: a" warning - else - true - end - end - end - - assert_block do - [{a: 0}, C.new({a: 0})].all? do |i| - case i - in a: - a == 0 - end - end - end - - assert_block do - [{a: 0, b: 1}, C.new({a: 0, b: 1})].all? do |i| - case i - in a: - a == 0 - end - end - end - - assert_block do - [{a: 0}, C.new({a: 0})].all? do |i| - case i - in "a": 0 - true - end - end - end - - assert_block do - [{a: 0}, C.new({a: 0})].all? do |i| - case i - in "a":; - a == 0 - end - end - end - - assert_block do - [{}, C.new({})].all? do |i| - case i - in **a - a == {} - end - end - end - - assert_block do - [{a: 0}, C.new({a: 0})].all? do |i| - case i - in **a - a == {a: 0} - end - end - end - - assert_block do - [{}, C.new({})].all? do |i| - case i - in **; - true - end - end - end - - assert_block do - [{a: 0}, C.new({a: 0})].all? do |i| - case i - in **; - true - end - end - end - - assert_block do - [{}, C.new({})].all? do |i| - case i - in a:, **b - raise a # suppress "unused variable: a" warning - raise b # suppress "unused variable: b" warning - else - true - end - end - end - - assert_block do - [{a: 0}, C.new({a: 0})].all? do |i| - case i - in a:, **b - a == 0 && b == {} - end - end - end - - assert_block do - [{a: 0, b: 1}, C.new({a: 0, b: 1})].all? do |i| - case i - in a:, **b - a == 0 && b == {b: 1} - end - end - end - - assert_block do - [{}, C.new({})].all? do |i| - case i - in **nil - true - end - end - end - - assert_block do - [{a: 0}, C.new({a: 0})].all? do |i| - case i - in **nil - else - true - end - end - end - - assert_block do - [{a: 0}, C.new({a: 0})].all? do |i| - case i - in a:, **nil - assert_equal(0, a) - true - end - end - end - - assert_block do - [{a: 0, b: 1}, C.new({a: 0, b: 1})].all? do |i| - case i - in a:, **nil - assert_equal(0, a) - else - true - end - end - end - - assert_block do - case C.new({a: 0}) - in C(a: 0) - true - end - end - - assert_block do - case {a: 0} - in C(a: 0) - else - true - end - end - - assert_block do - case C.new({a: 0}) - in C[a: 0] - true - end - end - - assert_block do - case {a: 0} - in C[a: 0] - else - true - end - end - - assert_block do - [{}, C.new({})].all? do |i| - case i - in {a: 0} - else - true - end - end - end - - assert_block do - [{a: 0}, C.new({a: 0})].all? do |i| - case i - in {a: 0} - true - end - end - end - - assert_block do - [{a: 0, b: 1}, C.new({a: 0, b: 1})].all? do |i| - case i - in {a: 0} - true - end - end - end - - assert_block do - [{}, C.new({})].all? do |i| - case i - in {} - true - end - end - end - - assert_block do - [{a: 0}, C.new({a: 0})].all? do |i| - case i - in {} - else - true - end - end - end - - assert_syntax_error(%q{ - case _ - in a:, a: - end - }, /duplicated key name/) - - assert_syntax_error(%q{ - case _ - in a?: - end - }, /key must be valid as local variables/) - - assert_block do - case {a?: true} - in a?: true - true - end - end - - assert_block do - case {a: 0, b: 1} - in {a: 1,} - false - in {a:,} - _a = a - true - end - end - - assert_block do - case {a: 0} - in {a: 1 - } - false - in {a: - 2} - false - in a: {b:}, c: - _b = b - p c - in {a: - } - _a = a - true - end - end - - assert_syntax_error(%q{ - case _ - in "a-b": - end - }, /key must be valid as local variables/) - - assert_block do - case {"a-b": true} - in "a-b": true - true - end - end - - assert_syntax_error(%q{ - case _ - in "#{a}": a - end - }, /symbol literal with interpolation is not allowed/) - - assert_syntax_error(%q{ - case _ - in "#{a}": - end - }, /symbol literal with interpolation is not allowed/) - end - - def test_paren - assert_block do - case 0 - in (0) - true - end - end - end - - def test_nomatchingpatternerror - assert_equal(StandardError, NoMatchingPatternError.superclass) - end - - def test_invalid_syntax - assert_syntax_error(%q{ - case 0 - in a, b: - end - }, /unexpected/) - - assert_syntax_error(%q{ - case 0 - in [a:] - end - }, /unexpected/) - - assert_syntax_error(%q{ - case 0 - in {a} - end - }, /unexpected/) - - assert_syntax_error(%q{ - case 0 - in {0 => a} - end - }, /unexpected/) - end - - ################################################################ - - class CTypeError - def deconstruct - nil - end - - def deconstruct_keys(keys) - nil - end - end - - def test_deconstruct - assert_raise(TypeError) do - case CTypeError.new - in [] - end - end - end - - def test_deconstruct_keys - assert_raise(TypeError) do - case CTypeError.new - in {} - end - end - - assert_block do - case {} - in {} - C.keys == nil - end - end - - assert_block do - case C.new({a: 0, b: 0, c: 0}) - in {a: 0, b:} - assert_equal(0, b) - C.keys == [:a, :b] - end - end - - assert_block do - case C.new({a: 0, b: 0, c: 0}) - in {a: 0, b:, **} - assert_equal(0, b) - C.keys == [:a, :b] - end - end - - assert_block do - case C.new({a: 0, b: 0, c: 0}) - in {a: 0, b:, **r} - assert_equal(0, b) - assert_equal({c: 0}, r) - C.keys == nil - end - end - - assert_block do - case C.new({a: 0, b: 0, c: 0}) - in {**} - C.keys == [] - end - end - - assert_block do - case C.new({a: 0, b: 0, c: 0}) - in {**r} - assert_equal({a: 0, b: 0, c: 0}, r) - C.keys == nil - end - end - end - - ################################################################ - - class CDeconstructCache - def initialize(v) - @v = v - end - - def deconstruct - @v.shift - end - end - - def test_deconstruct_cache - assert_block do - case CDeconstructCache.new([[0]]) - in [1] - in [0] - true - end - end - - assert_block do - case CDeconstructCache.new([[0, 1]]) - in [1,] - in [0,] - true - end - end - - assert_block do - case CDeconstructCache.new([[[0]]]) - in [[1]] - in [[*a]] - a == [0] - end - end - - assert_block do - case CDeconstructCache.new([[0]]) - in [x] if x > 0 - in [0] - true - end - end - - assert_block do - case CDeconstructCache.new([[0]]) - in [] - in [1] | [0] - true - end - end - - assert_block do - case CDeconstructCache.new([[0]]) - in [1] => _ - in [0] => _ - true - end - end - - assert_block do - case CDeconstructCache.new([[0]]) - in C[0] - in CDeconstructCache[0] - true - end - end - - assert_block do - case [CDeconstructCache.new([[0], [1]])] - in [[1]] - false - in [[1]] - true - end - end - - assert_block do - case CDeconstructCache.new([[0, :a, 1]]) - in [*, String => x, *] - false - in [*, Symbol => x, *] - x == :a - end - end - end - - ################################################################ - - class TestPatternMatchingRefinements < Test::Unit::TestCase - class C1 - def deconstruct - [:C1] - end - end - - class C2 - end - - module M - refine Array do - def deconstruct - [0] - end - end - - refine Hash do - def deconstruct_keys(_) - {a: 0} - end - end - - refine C2.singleton_class do - def ===(obj) - obj.kind_of?(C1) - end - end - end - - using M - - def test_refinements - assert_block do - case [] - in [0] - true - end - end - - assert_block do - case {} - in {a: 0} - true - end - end - - assert_block do - case C1.new - in C2(:C1) - true - end - end - end - end - - ################################################################ - - def test_struct - assert_block do - s = Struct.new(:a, :b) - case s[0, 1] - in 0, 1 - true - end - end - - s = Struct.new(:a, :b, keyword_init: true) - assert_block do - case s[a: 0, b: 1] - in **r - r == {a: 0, b: 1} - end - end - assert_block do - s = Struct.new(:a, :b, keyword_init: true) - case s[a: 0, b: 1] - in a:, b: - a == 0 && b == 1 - end - end - assert_block do - s = Struct.new(:a, :b, keyword_init: true) - case s[a: 0, b: 1] - in a:, c: - raise a # suppress "unused variable: a" warning - raise c # suppress "unused variable: c" warning - flunk - in a:, b:, c: - flunk - in b: - b == 1 - end - end - end - - ################################################################ - - def test_one_line - 1 => a - assert_equal 1, a - assert_raise(NoMatchingPatternError) do - {a: 1} => {a: 0} - end - assert_syntax_error("if {} => {a:}; end", /void value expression/) - assert_syntax_error(%q{ - 1 => a, b - }, /unexpected/, '[ruby-core:95098]') - assert_syntax_error(%q{ - 1 => a: - }, /unexpected/, '[ruby-core:95098]') - - assert_equal true, (1 in 1) - assert_equal false, (1 in 2) - end - - def assert_experimental_warning(code) - w = Warning[:experimental] - - Warning[:experimental] = false - assert_warn('') {eval(code)} - - Warning[:experimental] = true - assert_warn(/is experimental/) {eval(code)} - ensure - Warning[:experimental] = w - end - - def test_experimental_warning - assert_experimental_warning("case [0]; in [*, 0, *]; end") - assert_experimental_warning("0 => 0") - assert_experimental_warning("0 in a") - end -end -END_of_GUARD -Warning[:experimental] = experimental diff --git a/test/ruby/test_pipe.rb b/test/ruby/test_pipe.rb index 9fa42fd375..efca8f28c1 100644 --- a/test/ruby/test_pipe.rb +++ b/test/ruby/test_pipe.rb @@ -27,23 +27,4 @@ class TestPipe < Test::Unit::TestCase end end end - - def test_stdout_epipe - assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") - begin; - io = STDOUT - begin - save = io.dup - IO.popen("echo", "w", out: IO::NULL) do |f| - io.reopen(f) - Process.wait(f.pid) - assert_raise(Errno::EPIPE) do - io.print "foo\n" - end - end - ensure - io.reopen(save) - end - end; - end end diff --git a/test/ruby/test_primitive.rb b/test/ruby/test_primitive.rb index f1db934000..19af44ad32 100644 --- a/test/ruby/test_primitive.rb +++ b/test/ruby/test_primitive.rb @@ -26,31 +26,24 @@ class TestRubyPrimitive < Test::Unit::TestCase assert_equal 4, c end - C_Setup = -> do - remove_const :C if defined? ::TestRubyPrimitive::C - remove_const :A if defined? ::TestRubyPrimitive::A - - C = 1 - class A - Const = 1 - class B - Const = 2 - class C - Const = 3 - def const - Const - end + C = 1 + class A + Const = 1 + class B + Const = 2 + class C + Const = 3 + def const + Const end end end - (1..2).map { - A::B::C::Const - } end + (1..2).map { + A::B::C::Const + } def test_constant - C_Setup.call - assert_equal 1, C assert_equal 1, C assert_equal 1, A::Const @@ -152,60 +145,42 @@ class TestRubyPrimitive < Test::Unit::TestCase assert_equal 7, ($test_ruby_primitive_gvar = 7) end - A7_Setup = -> do - remove_const :A7 if defined? TestRubyPrimitive::A7 - - class A7 - @@c = 1 - def m - @@c += 1 - end + class A7 + @@c = 1 + def m + @@c += 1 end end def test_cvar_from_instance_method - A7_Setup.call - assert_equal 2, A7.new.m assert_equal 3, A7.new.m assert_equal 4, A7.new.m end - A8_Setup = -> do - remove_const :A8 if defined? TestRubyPrimitive::A8 - - class A8 - @@c = 1 - class << self - def m - @@c += 1 - end + class A8 + @@c = 1 + class << self + def m + @@c += 1 end end end def test_cvar_from_singleton_method - A8_Setup.call - assert_equal 2, A8.m assert_equal 3, A8.m assert_equal 4, A8.m end - A9_Setup = -> do - remove_const :A8 if defined? TestRubyPrimitive::A8 - - class A9 - @@c = 1 - def self.m - @@c += 1 - end + class A9 + @@c = 1 + def self.m + @@c += 1 end end def test_cvar_from_singleton_method2 - A9_Setup.call - assert_equal 2, A9.m assert_equal 3, A9.m assert_equal 4, A9.m @@ -224,9 +199,6 @@ class TestRubyPrimitive < Test::Unit::TestCase @iv += 2 assert_equal 4, @iv - # init @@cv - @@cv = nil - @@cv ||= 1 assert_equal 1, @@cv @@cv &&= 2 diff --git a/test/ruby/test_proc.rb b/test/ruby/test_proc.rb index 5f2f797992..df9bb5f549 100644 --- a/test/ruby/test_proc.rb +++ b/test/ruby/test_proc.rb @@ -4,6 +4,7 @@ require 'test/unit' class TestProc < Test::Unit::TestCase def setup @verbose = $VERBOSE + $VERBOSE = nil end def teardown @@ -52,14 +53,10 @@ class TestProc < Test::Unit::TestCase assert_equal(5, x) end - def assert_arity(n, &block) + def assert_arity(n) meta = class << self; self; end - b = Proc.new(&block) - meta.class_eval { - remove_method(:foo_arity) if method_defined?(:foo_arity) - define_method(:foo_arity, b) - } - assert_equal(n, method(:foo_arity).arity) + meta.class_eval {define_method(:foo, Proc.new)} + assert_equal(n, method(:foo).arity) end def test_arity @@ -136,14 +133,6 @@ class TestProc < Test::Unit::TestCase lambda { x } end - def m_nest0(&block) - block - end - - def m_nest(&block) - [m_nest0(&block), m_nest0(&block)] - end - def test_eq a = m(1) b = m(2) @@ -155,8 +144,6 @@ class TestProc < Test::Unit::TestCase a = lambda {|x| lambda {} }.call(1) b = lambda {} assert_not_equal(a, b, "[ruby-dev:22601]") - - assert_equal(*m_nest{}, "[ruby-core:84583] Feature #14627") end def test_block_par @@ -164,6 +151,37 @@ class TestProc < Test::Unit::TestCase assert_equal(12, Proc.new{|a,&b| b.call(a)}.call(12) {|x| x}) end + def test_safe + safe = $SAFE + c = Class.new + x = c.new + + p = proc { + $SAFE += 1 + proc {$SAFE} + }.call + assert_equal(safe, $SAFE) + assert_equal(safe + 1, p.call) + assert_equal(safe, $SAFE) + + c.class_eval {define_method(:safe, p)} + assert_equal(safe, x.safe) + assert_equal(safe, x.method(:safe).call) + assert_equal(safe, x.method(:safe).to_proc.call) + + p = proc {$SAFE += 1} + assert_equal(safe + 1, p.call) + assert_equal(safe, $SAFE) + + c.class_eval {define_method(:inc, p)} + assert_equal(safe + 1, proc {x.inc; $SAFE}.call) + assert_equal(safe, $SAFE) + assert_equal(safe + 1, proc {x.method(:inc).call; $SAFE}.call) + assert_equal(safe, $SAFE) + assert_equal(safe + 1, proc {x.method(:inc).to_proc.call; $SAFE}.call) + assert_equal(safe, $SAFE) + end + def m2 "OK" end @@ -270,7 +288,7 @@ class TestProc < Test::Unit::TestCase def test_curry_given_blocks b = lambda {|x, y, &blk| blk.call(x + y) }.curry - b = assert_warning(/given block not used/) {b.call(2) { raise }} + b = b.call(2) { raise } b = b.call(3) {|x| x + 4 } assert_equal(9, b) end @@ -280,7 +298,7 @@ class TestProc < Test::Unit::TestCase assert_equal(false, l.lambda?) assert_equal(false, l.curry.lambda?, '[ruby-core:24127]') assert_equal(false, proc(&l).lambda?) - assert_equal(false, assert_deprecated_warning {lambda(&l)}.lambda?) + assert_equal(false, lambda(&l).lambda?) assert_equal(false, Proc.new(&l).lambda?) l = lambda {} assert_equal(true, l.lambda?) @@ -290,49 +308,6 @@ class TestProc < Test::Unit::TestCase assert_equal(true, Proc.new(&l).lambda?) end - def self.helper_test_warn_lamda_with_passed_block &b - lambda(&b) - end - - def self.def_lambda_warning name, warn - define_method(name, proc do - prev = Warning[:deprecated] - assert_warn warn do - Warning[:deprecated] = true - yield - end - ensure - Warning[:deprecated] = prev - end) - end - - def_lambda_warning 'test_lambda_warning_normal', '' do - lambda{} - end - - def_lambda_warning 'test_lambda_warning_pass_lambda', '' do - b = lambda{} - lambda(&b) - end - - def_lambda_warning 'test_lambda_warning_pass_symbol_proc', '' do - lambda(&:to_s) - end - - def_lambda_warning 'test_lambda_warning_pass_proc', /deprecated/ do - b = proc{} - lambda(&b) - end - - def_lambda_warning 'test_lambda_warning_pass_block', /deprecated/ do - helper_test_warn_lamda_with_passed_block{} - end - - def_lambda_warning 'test_lambda_warning_pass_block_symbol_proc', '' do - # Symbol#to_proc returns lambda - helper_test_warn_lamda_with_passed_block(&:to_s) - end - def test_curry_ski_fib s = proc {|f, g, x| f[x][g[x]] }.curry k = proc {|x, y| x }.curry @@ -422,18 +397,9 @@ class TestProc < Test::Unit::TestCase assert_equal([1, 2, 3], b.eval("[x, y, z]")) end - def test_binding_source_location - b, expected_location = binding, [__FILE__, __LINE__] - assert_equal(expected_location, b.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, lineno, 'Bug #2427') - end - def test_proc_lambda assert_raise(ArgumentError) { proc } - assert_raise(ArgumentError) { assert_warn(/deprecated/) {lambda} } + assert_raise(ArgumentError) { lambda } o = Object.new def o.foo @@ -441,18 +407,14 @@ class TestProc < Test::Unit::TestCase 1.times { b = lambda } b end - assert_raise(ArgumentError) do - assert_deprecated_warning {o.foo { :foo }}.call - end + assert_equal(:foo, o.foo { :foo }.call) - def o.bar(&b) + def o.foo(&b) b = nil 1.times { b = lambda } b end - assert_raise(ArgumentError) do - assert_deprecated_warning {o.bar { :foo }}.call - end + assert_equal(:foo, o.foo { :foo }.call) end def test_arity2 @@ -838,33 +800,6 @@ class TestProc < Test::Unit::TestCase assert_equal [[1, 2], Proc, :x], (pr.call(1, 2){|x| x}) end - def test_proc_args_only_rest - pr = proc {|*c| c } - assert_equal [], pr.call() - assert_equal [1], pr.call(1) - assert_equal [[1]], pr.call([1]) - assert_equal [1, 2], pr.call(1,2) - assert_equal [[1, 2]], pr.call([1,2]) - end - - def test_proc_args_rest_kw - pr = proc {|*c, a: 1| [c, a] } - assert_equal [[], 1], pr.call() - assert_equal [[1], 1], pr.call(1) - assert_equal [[[1]], 1], pr.call([1]) - assert_equal [[1, 2], 1], pr.call(1,2) - assert_equal [[[1, 2]], 1], pr.call([1,2]) - end - - def test_proc_args_rest_kwsplat - pr = proc {|*c, **kw| [c, kw] } - assert_equal [[], {}], pr.call() - assert_equal [[1], {}], pr.call(1) - assert_equal [[[1]], {}], pr.call([1]) - assert_equal [[1, 2], {}], pr.call(1,2) - assert_equal [[[1, 2]], {}], pr.call([1,2]) - end - def test_proc_args_pos_rest_post_block pr = proc {|a,b,*c,d,e,&f| [a, b, c, d, e, f.class, f&&f.call(:x)] @@ -1168,36 +1103,6 @@ class TestProc < Test::Unit::TestCase assert_equal([1,2,[3],4,5], r, "[ruby-core:19485]") end - def test_proc_autosplat - def self.a(arg, kw) - yield arg - yield arg, **kw - yield arg, kw - end - - arr = [] - a([1,2,3], {}) do |arg1, arg2=0| - arr << [arg1, arg2] - end - assert_equal([[1, 2], [[1, 2, 3], 0], [[1, 2, 3], {}]], arr) - - arr = [] - a([1,2,3], a: 1) do |arg1, arg2=0| - arr << [arg1, arg2] - end - assert_equal([[1, 2], [[1, 2, 3], {a: 1}], [[1, 2, 3], {a: 1}]], arr) - end - - def test_proc_single_arg_with_keywords_accepted_and_yielded - def self.a - yield [], **{a: 1} - end - res = a do |arg, **opts| - [arg, opts] - end - assert_equal([[], {a: 1}], res) - end - def test_parameters assert_equal([], proc {}.parameters) assert_equal([], proc {||}.parameters) @@ -1266,9 +1171,12 @@ class TestProc < Test::Unit::TestCase end def test_to_s - assert_match(/^#<Proc:0x\h+ #{ Regexp.quote(__FILE__) }:\d+>$/, proc {}.to_s) - assert_match(/^#<Proc:0x\h+ #{ Regexp.quote(__FILE__) }:\d+ \(lambda\)>$/, lambda {}.to_s) + assert_match(/^#<Proc:0x\h+@#{ Regexp.quote(__FILE__) }:\d+>$/, proc {}.to_s) + assert_match(/^#<Proc:0x\h+@#{ Regexp.quote(__FILE__) }:\d+ \(lambda\)>$/, lambda {}.to_s) assert_match(/^#<Proc:0x\h+ \(lambda\)>$/, method(:p).to_proc.to_s) + x = proc {} + x.taint + assert_predicate(x.to_s, :tainted?) name = "Proc\u{1f37b}" assert_include(EnvUtil.labeled_class(name, Proc).new {}.to_s, name) end @@ -1377,7 +1285,7 @@ class TestProc < Test::Unit::TestCase def test_local_variables b = get_binding assert_equal(%i'if case when begin end a', b.local_variables) - a = tap {|;x, y| x = y = x; break binding.local_variables} + a = tap {|;x, y| x = y; break binding.local_variables} assert_equal(%i[a b x y], a.sort) end @@ -1420,7 +1328,7 @@ class TestProc < Test::Unit::TestCase end def test_local_variable_set_wb - assert_ruby_status([], <<-'end;', '[Bug #13605]', timeout: 30) + assert_ruby_status([], <<-'end;', '[Bug #13605]', timeout: 15) b = binding n = 20_000 @@ -1468,245 +1376,4 @@ class TestProc < Test::Unit::TestCase e.each {} EOS end - - def test_prepended_call - assert_in_out_err([], "#{<<~"begin;"}\n#{<<~'end;'}", ["call"]) - begin; - Proc.prepend Module.new {def call() puts "call"; super; end} - def m(&blk) blk.call; end - m {} - end; - end - - def test_refined_call - assert_in_out_err([], "#{<<~"begin;"}\n#{<<~'end;'}", ["call"]) - begin; - using Module.new {refine(Proc) {def call() puts "call"; super; end}} - def m(&blk) blk.call; end - m {} - end; - end - - def test_compose - f = proc {|x| x * 2} - g = proc {|x| x + 1} - - assert_equal(6, (f << g).call(2)) - assert_equal(6, (g >> f).call(2)) - end - - def test_compose_with_multiple_args - f = proc {|x| x * 2} - g = proc {|x, y| x + y} - - assert_equal(6, (f << g).call(1, 2)) - assert_equal(6, (g >> f).call(1, 2)) - end - - def test_compose_with_block - f = proc {|x| x * 2} - g = proc {|&blk| blk.call(1) } - - assert_equal(8, (f << g).call { |x| x + 3 }) - assert_equal(8, (g >> f).call { |x| x + 3 }) - end - - def test_compose_with_lambda - f = lambda {|x| x * 2} - g = lambda {|x| x} - not_lambda = proc {|x| x} - - assert_predicate((f << g), :lambda?) - assert_predicate((g >> f), :lambda?) - assert_predicate((not_lambda << f), :lambda?) - assert_not_predicate((f << not_lambda), :lambda?) - assert_not_predicate((not_lambda >> f), :lambda?) - end - - def test_compose_with_method - f = proc {|x| x * 2} - c = Class.new { - def g(x) x + 1 end - } - g = c.new.method(:g) - - assert_equal(6, (f << g).call(2)) - assert_equal(5, (f >> g).call(2)) - assert_predicate((f << g), :lambda?) - end - - def test_compose_with_callable - f = proc {|x| x * 2} - c = Class.new { - def call(x) x + 1 end - } - g = c.new - - assert_equal(6, (f << g).call(2)) - assert_equal(5, (f >> g).call(2)) - assert_predicate((f << g), :lambda?) - end - - def test_compose_with_noncallable - f = proc {|x| x * 2} - - assert_raise(TypeError) { - (f << 5).call(2) - } - assert_raise(TypeError) { - (f >> 5).call(2) - } - end - - def test_orphan_return - assert_equal(42, Module.new { extend self - def m1(&b) b.call end; def m2(); m1 { return 42 } end }.m2) - assert_equal(42, Module.new { extend self - def m1(&b) b end; def m2(); m1 { return 42 }.call end }.m2) - assert_raise(LocalJumpError) { Module.new { extend self - def m1(&b) b end; def m2(); m1 { return 42 } end }.m2.call } - end - - def test_orphan_break - assert_equal(42, Module.new { extend self - def m1(&b) b.call end; def m2(); m1 { break 42 } end }.m2 ) - assert_raise(LocalJumpError) { Module.new { extend self - def m1(&b) b end; def m2(); m1 { break 42 }.call end }.m2 } - assert_raise(LocalJumpError) { Module.new { extend self - def m1(&b) b end; def m2(); m1 { break 42 } end }.m2.call } - end - - def test_not_orphan_next - assert_equal(42, Module.new { extend self - def m1(&b) b.call end; def m2(); m1 { next 42 } end }.m2) - assert_equal(42, Module.new { extend self - def m1(&b) b end; def m2(); m1 { next 42 }.call end }.m2) - assert_equal(42, Module.new { extend self - def m1(&b) b end; def m2(); m1 { next 42 } end }.m2.call) - end - - def test_isolate - assert_raise_with_message ArgumentError, /\(a\)/ do - a = :a - Proc.new{p a}.isolate.call - end - - assert_raise_with_message ArgumentError, /\(a\)/ do - a = :a - 1.times{ - Proc.new{p a}.isolate.call - } - end - - assert_raise_with_message ArgumentError, /yield/ do - Proc.new{yield}.isolate.call - end - - # binding - - :a.tap{|a| - :b.tap{|b| - Proc.new{ - :c.tap{|c| - assert_equal :c, eval('c') - - assert_raise_with_message SyntaxError, /\`a\'/ do - eval('p a') - end - - assert_raise_with_message SyntaxError, /\`b\'/ do - eval('p b') - end - - assert_raise_with_message SyntaxError, /can not yield from isolated Proc/ do - eval('p yield') - end - - assert_equal :c, binding.local_variable_get(:c) - - assert_raise_with_message NameError, /local variable \`a\' is not defined/ do - binding.local_variable_get(:a) - end - - assert_equal [:c], local_variables - assert_equal [:c], binding.local_variables - } - }.isolate.call - } - } - end if proc{}.respond_to? :isolate end - -class TestProcKeywords < Test::Unit::TestCase - def test_compose_keywords - f = ->(**kw) { kw.merge(:a=>1) } - g = ->(kw) { kw.merge(:a=>2) } - - assert_equal(2, (f >> g).call(a: 3)[:a]) - assert_raise(ArgumentError) { (f << g).call(a: 3)[:a] } - assert_equal(2, (f >> g).call(a: 3)[:a]) - assert_raise(ArgumentError) { (f << g).call({a: 3})[:a] } - assert_raise(ArgumentError) { (f >> g).call({a: 3})[:a] } - assert_equal(2, (g << f).call(a: 3)[:a]) - assert_raise(ArgumentError) { (g >> f).call(a: 3)[:a] } - assert_raise(ArgumentError) { (g << f).call({a: 3})[:a] } - assert_raise(ArgumentError) { (g >> f).call({a: 3})[:a] } - assert_raise(ArgumentError) { (f << g).call(**{})[:a] } - assert_equal(2, (f >> g).call(**{})[:a]) - end - - def test_compose_keywords_method - f = ->(**kw) { kw.merge(:a=>1) }.method(:call) - g = ->(kw) { kw.merge(:a=>2) }.method(:call) - - assert_raise(ArgumentError) { (f << g).call(a: 3)[:a] } - assert_equal(2, (f >> g).call(a: 3)[:a]) - assert_raise(ArgumentError) { (f << g).call({a: 3})[:a] } - assert_raise(ArgumentError) { (f >> g).call({a: 3})[:a] } - assert_equal(2, (g << f).call(a: 3)[:a]) - assert_raise(ArgumentError) { (g >> f).call(a: 3)[:a] } - assert_raise(ArgumentError) { (g << f).call({a: 3})[:a] } - assert_raise(ArgumentError) { (g >> f).call({a: 3})[:a] } - assert_raise(ArgumentError) { (f << g).call(**{})[:a] } - assert_equal(2, (f >> g).call(**{})[:a]) - end - - def test_compose_keywords_non_proc - f = ->(**kw) { kw.merge(:a=>1) } - g = Object.new - def g.call(kw) kw.merge(:a=>2) end - def g.to_proc; method(:call).to_proc; end - def g.<<(f) to_proc << f end - def g.>>(f) to_proc >> f end - - assert_raise(ArgumentError) { (f << g).call(a: 3)[:a] } - assert_equal(2, (f >> g).call(a: 3)[:a]) - assert_raise(ArgumentError) { (f << g).call({a: 3})[:a] } - assert_raise(ArgumentError) { (f >> g).call({a: 3})[:a] } - assert_equal(2, (g << f).call(a: 3)[:a]) - assert_raise(ArgumentError) { (g >> f).call(a: 3)[:a] } - assert_raise(ArgumentError) { (g << f).call({a: 3})[:a] } - assert_raise(ArgumentError) { (g >> f).call({a: 3})[:a] } - assert_raise(ArgumentError) { (f << g).call(**{})[:a] } - assert_equal(2, (f >> g).call(**{})[:a]) - - f = ->(kw) { kw.merge(:a=>1) } - g = Object.new - def g.call(**kw) kw.merge(:a=>2) end - def g.to_proc; method(:call).to_proc; end - def g.<<(f) to_proc << f end - def g.>>(f) to_proc >> f end - - assert_equal(1, (f << g).call(a: 3)[:a]) - assert_raise(ArgumentError) { (f >> g).call(a: 3)[:a] } - assert_raise(ArgumentError) { (f << g).call({a: 3})[:a] } - assert_raise(ArgumentError) { (f >> g).call({a: 3})[:a] } - assert_raise(ArgumentError) { (g << f).call(a: 3)[:a] } - assert_equal(1, (g >> f).call(a: 3)[:a]) - assert_raise(ArgumentError) { (g << f).call({a: 3})[:a] } - assert_raise(ArgumentError) { (g >> f).call({a: 3})[:a] } - assert_equal(1, (f << g).call(**{})[:a]) - assert_raise(ArgumentError) { (f >> g).call(**{})[:a] } - end -end - diff --git a/test/ruby/test_process.rb b/test/ruby/test_process.rb index a114f279ba..ba7b0f1177 100644 --- a/test/ruby/test_process.rb +++ b/test/ruby/test_process.rb @@ -246,22 +246,21 @@ class TestProcess < Test::Unit::TestCase assert_raise(ArgumentError) do system(RUBY, '-e', 'exit', 'rlimit_bogus'.to_sym => 123) end - assert_separately([],"#{<<~"begin;"}\n#{<<~'end;'}", 'rlimit_cpu'.to_sym => 3600) - BUG = "[ruby-core:82033] [Bug #13744]" - begin; - assert_equal([3600,3600], Process.getrlimit(:CPU), BUG) + assert_separately([],<<-"end;") # [ruby-core:82033] [Bug #13744] + assert(system("#{RUBY}", "-e", + "exit([3600,3600] == Process.getrlimit(:CPU))", + 'rlimit_cpu'.to_sym => 3600)) + assert_raise(ArgumentError) do + system("#{RUBY}", '-e', 'exit', :rlimit_bogus => 123) + end end; - assert_raise_with_message(ArgumentError, /bogus/) do - system(RUBY, '-e', 'exit', :rlimit_bogus => 123) - end - - assert_raise_with_message(ArgumentError, /rlimit_cpu/) { + assert_raise(ArgumentError, /rlimit_cpu/) { system(RUBY, '-e', 'exit', "rlimit_cpu\0".to_sym => 3600) } end - MANDATORY_ENVS = %w[RUBYLIB MJIT_SEARCH_BUILD_DIR] + MANDATORY_ENVS = %w[RUBYLIB] case RbConfig::CONFIG['target_os'] when /linux/ MANDATORY_ENVS << 'LD_PRELOAD' @@ -273,9 +272,6 @@ class TestProcess < Test::Unit::TestCase if e = RbConfig::CONFIG['LIBPATHENV'] MANDATORY_ENVS << e end - 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) @@ -338,13 +334,6 @@ class TestProcess < Test::Unit::TestCase ensure ENV["hmm"] = old end - - assert_raise_with_message(ArgumentError, /fo=fo/) { - system({"fo=fo"=>"ha"}, *ENVCOMMAND) - } - assert_raise_with_message(ArgumentError, /\u{30c0}=\u{30e1}/) { - system({"\u{30c0}=\u{30e1}"=>"ha"}, *ENVCOMMAND) - } end def test_execopt_env_path @@ -641,7 +630,7 @@ class TestProcess < Test::Unit::TestCase rescue NotImplementedError return end - assert_file.pipe?("fifo") + assert(FileTest.pipe?("fifo"), "should be pipe") t1 = Thread.new { system(*ECHO["output to fifo"], :out=>"fifo") } @@ -687,17 +676,14 @@ class TestProcess < Test::Unit::TestCase return end IO.popen([RUBY, '-e', <<-'EOS']) {|io| - STDOUT.sync = true trap(:USR1) { print "trap\n" } - puts "start" system("cat", :in => "fifo") EOS - assert_equal("start\n", io.gets) - sleep 0.2 # wait for the child to stop at opening "fifo" + sleep 1 Process.kill(:USR1, io.pid) - assert_equal("trap\n", io.readpartial(8)) + sleep 1 File.write("fifo", "ok\n") - assert_equal("ok\n", io.read) + assert_equal("trap\nok\n", io.read) } } end unless windows? # does not support fifo @@ -770,15 +756,6 @@ class TestProcess < Test::Unit::TestCase Process.wait pid end } - - # ensure standard FDs we redirect to are blocking for compatibility - with_pipes(3) do |pipes| - src = 'p [STDIN,STDOUT,STDERR].map(&:nonblock?)' - rdr = { 0 => pipes[0][0], 1 => pipes[1][1], 2 => pipes[2][1] } - pid = spawn(RUBY, '-rio/nonblock', '-e', src, rdr) - assert_equal("[false, false, false]\n", pipes[1][0].gets) - Process.wait pid - end end end @@ -1026,15 +1003,6 @@ class TestProcess < Test::Unit::TestCase } end - def test_close_others_default_false - IO.pipe do |r,w| - w.close_on_exec = false - src = "IO.new(#{w.fileno}).puts(:hi)" - assert_equal true, system(*%W(#{RUBY} --disable=gems -e #{src})) - assert_equal "hi\n", r.gets - end - end unless windows? # passing non-stdio fds is not supported on Windows - def test_execopts_redirect_self begin with_pipe {|r, w| @@ -1425,8 +1393,6 @@ class TestProcess < Test::Unit::TestCase assert_equal(s.to_i >> 1, s >> 1) assert_equal(false, s.stopped?) assert_equal(nil, s.stopsig) - - assert_equal(s, Marshal.load(Marshal.dump(s))) end end @@ -1444,8 +1410,6 @@ class TestProcess < Test::Unit::TestCase assert_equal(expected, [s.exited?, s.signaled?, s.stopped?, s.success?], "[s.exited?, s.signaled?, s.stopped?, s.success?]") - - assert_equal(s, Marshal.load(Marshal.dump(s))) end end @@ -1460,15 +1424,9 @@ class TestProcess < Test::Unit::TestCase "[s.exited?, s.signaled?, s.stopped?, s.success?]") assert_equal("#<Process::Status: pid #{ s.pid } SIGQUIT (signal #{ s.termsig })>", s.inspect.sub(/ \(core dumped\)(?=>\z)/, '')) - - assert_equal(s, Marshal.load(Marshal.dump(s))) end end - def test_status_fail - assert_nil(Process::Status.wait($$)) - end - def test_wait_without_arg with_tmpchdir do write_file("foo", "sleep 0.1") @@ -1500,9 +1458,7 @@ class TestProcess < Test::Unit::TestCase def test_wait_exception bug11340 = '[ruby-dev:49176] [Bug #11340]' t0 = t1 = nil - sec = 3 - code = "puts;STDOUT.flush;Thread.start{gets;exit};sleep(#{sec})" - IO.popen([RUBY, '-e', code], 'r+') do |f| + IO.popen([RUBY, '-e', 'puts;STDOUT.flush;Thread.start{gets;exit};sleep(3)'], 'r+') do |f| pid = f.pid f.gets t0 = Time.now @@ -1516,35 +1472,21 @@ class TestProcess < Test::Unit::TestCase th.kill.join end t1 = Time.now - diff = t1 - t0 - assert_operator(diff, :<, sec, - ->{"#{bug11340}: #{diff} seconds to interrupt Process.wait"}) f.puts end + assert_operator(t1 - t0, :<, 3, + ->{"#{bug11340}: #{t1-t0} seconds to interrupt Process.wait"}) end def test_abort with_tmpchdir do s = run_in_child("abort") - assert_not_predicate(s, :success?) - write_file("test-script", "#{<<~"begin;"}\n#{<<~'end;'}") - begin; - STDERR.reopen(STDOUT) - begin - raise "[Bug #16424]" - rescue - abort - end - end; - assert_include(IO.popen([RUBY, "test-script"], &:read), "[Bug #16424]") + assert_not_equal(0, s.exitstatus) end end def test_sleep assert_raise(ArgumentError) { sleep(1, 1) } - [-1, -1.0, -1r].each do |sec| - assert_raise_with_message(ArgumentError, /not.*negative/) { sleep(sec) } - end end def test_getpgid @@ -1582,8 +1524,6 @@ class TestProcess < Test::Unit::TestCase rescue NotImplementedError else assert_kind_of(Integer, max) - assert_predicate(max, :positive?) - skip "not limited to NGROUPS_MAX" if /darwin/ =~ RUBY_PLATFORM gs = Process.groups assert_operator(gs.size, :<=, max) gs[0] ||= 0 @@ -1600,7 +1540,7 @@ class TestProcess < Test::Unit::TestCase end def test_seteuid_name - user = (Etc.getpwuid(Process.euid).name rescue ENV["USER"]) or return + user = ENV["USER"] or return assert_nothing_raised(TypeError) {Process.euid = user} rescue NotImplementedError end @@ -1610,39 +1550,10 @@ class TestProcess < Test::Unit::TestCase end def test_setegid - skip "root can use Process.egid on Android platform" if RUBY_PLATFORM =~ /android/ assert_nothing_raised(TypeError) {Process.egid += 0} rescue NotImplementedError end - 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) - end - assert_raise_with_message(ArgumentError, /\u{4e0d 5b58 5728}/) { - Process::UID.from_name("\u{4e0d 5b58 5728}") - } - end - end - - 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) - end - expected_excs = [ArgumentError] - expected_excs << Errno::ENOENT if defined?(Errno::ENOENT) - expected_excs << Errno::ESRCH if defined?(Errno::ESRCH) # WSL 2 actually raises Errno::ESRCH - expected_excs << Errno::EBADF if defined?(Errno::EBADF) - expected_excs << Errno::EPERM if defined?(Errno::EPERM) - exc = assert_raise(*expected_excs) do - Process::GID.from_name("\u{4e0d 5b58 5728}") # fu son zai ("absent" in Kanji) - end - assert_match(/\u{4e0d 5b58 5728}/, exc.message) if exc.is_a?(ArgumentError) - end - end - def test_uid_re_exchangeable_p r = Process::UID.re_exchangeable? assert_include([true, false], r) @@ -1674,28 +1585,22 @@ class TestProcess < Test::Unit::TestCase skip "this fails on FreeBSD and OpenBSD on multithreaded environment" end signal_received = [] - IO.pipe do |sig_r, sig_w| - Signal.trap(:CHLD) do - signal_received << true - sig_w.write('?') - end - pid = nil - IO.pipe do |r, w| - pid = fork { r.read(1); exit } - Thread.start { - Thread.current.report_on_exception = false - raise - } - w.puts - end - Process.wait pid - assert_send [sig_r, :wait_readable, 5], 'self-pipe not readable' + Signal.trap(:CHLD) { signal_received << true } + pid = nil + IO.pipe do |r, w| + pid = fork { r.read(1); exit } + Thread.start { + Thread.current.report_on_exception = false + raise + } + w.puts end - if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # checking -DMJIT_FORCE_ENABLE. It may trigger extra SIGCHLD. - assert_equal [true], signal_received.uniq, "[ruby-core:19744]" - else - assert_equal [true], signal_received, "[ruby-core:19744]" + Process.wait pid + 10.times do + break unless signal_received.empty? + sleep 0.01 end + assert_equal [true], signal_received, " [ruby-core:19744]" rescue NotImplementedError, ArgumentError ensure begin @@ -1786,7 +1691,7 @@ class TestProcess < Test::Unit::TestCase with_tmpchdir do assert_nothing_raised('[ruby-dev:12261]') do - EnvUtil.timeout(3) do + Timeout.timeout(3) do pid = spawn('yes | ls') Process.waitpid pid end @@ -1853,12 +1758,12 @@ class TestProcess < Test::Unit::TestCase puts Dir.entries("/proc/self/task") - %W[. ..] end bug4920 = '[ruby-dev:43873]' - assert_include(1..2, data.size, bug4920) + assert_equal(2, data.size, bug4920) assert_not_include(data.map(&:to_i), pid) end else # darwin def test_daemon_no_threads - data = EnvUtil.timeout(3) do + data = Timeout.timeout(3) do IO.popen("-") do |f| break f.readlines.map(&:chomp) if f th = Thread.start {sleep 3} @@ -1907,16 +1812,6 @@ class TestProcess < Test::Unit::TestCase end end - def test_popen_reopen - assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") - begin; - io = File.open(IO::NULL) - io2 = io.dup - IO.popen("echo") {|f| io.reopen(f)} - io.reopen(io2) - end; - end - def test_execopts_new_pgroup return unless windows? @@ -1927,23 +1822,22 @@ class TestProcess < Test::Unit::TestCase end def test_execopts_uid - skip "root can use uid option of Kernel#system on Android platform" if RUBY_PLATFORM =~ /android/ feature6975 = '[ruby-core:47414]' [30000, [Process.uid, ENV["USER"]]].each do |uid, user| if user assert_nothing_raised(feature6975) do begin - system(*TRUECOMMAND, uid: user, exception: true) - rescue Errno::EPERM, Errno::EACCES, NotImplementedError + system(*TRUECOMMAND, uid: user) + rescue Errno::EPERM, NotImplementedError end end end assert_nothing_raised(feature6975) do begin - system(*TRUECOMMAND, uid: uid, exception: true) - rescue Errno::EPERM, Errno::EACCES, NotImplementedError + system(*TRUECOMMAND, uid: uid) + rescue Errno::EPERM, NotImplementedError end end @@ -1951,7 +1845,7 @@ class TestProcess < Test::Unit::TestCase begin u = IO.popen([RUBY, "-e", "print Process.uid", uid: user||uid], &:read) assert_equal(uid.to_s, u, feature6975) - rescue Errno::EPERM, Errno::EACCES, NotImplementedError + rescue Errno::EPERM, NotImplementedError end end end @@ -1959,15 +1853,9 @@ class TestProcess < Test::Unit::TestCase def test_execopts_gid skip "Process.groups not implemented on Windows platform" if windows? - skip "root can use Process.groups on Android platform" if RUBY_PLATFORM =~ /android/ feature6975 = '[ruby-core:47414]' - groups = Process.groups.map do |g| - g = Etc.getgrgid(g) rescue next - [g.name, g.gid] - end - groups.compact! - [30000, *groups].each do |group, gid| + [30000, *Process.groups.map {|g| g = Etc.getgrgid(g); [g.name, g.gid]}].each do |group, gid| assert_nothing_raised(feature6975) do begin system(*TRUECOMMAND, gid: group) @@ -2143,11 +2031,7 @@ EOS def test_clock_gettime_GETTIMEOFDAY_BASED_CLOCK_REALTIME n = :GETTIMEOFDAY_BASED_CLOCK_REALTIME - begin - t = Process.clock_gettime(n) - rescue Errno::EINVAL - return - end + t = Process.clock_gettime(n) assert_kind_of(Float, t, "Process.clock_gettime(:#{n})") end @@ -2225,11 +2109,7 @@ EOS def test_clock_getres_GETTIMEOFDAY_BASED_CLOCK_REALTIME n = :GETTIMEOFDAY_BASED_CLOCK_REALTIME - begin - t = Process.clock_getres(n) - rescue Errno::EINVAL - return - end + t = Process.clock_getres(n) assert_kind_of(Float, t, "Process.clock_getres(:#{n})") assert_equal(1000, Process.clock_getres(n, :nanosecond)) end @@ -2295,7 +2175,7 @@ EOS end def test_deadlock_by_signal_at_forking - assert_separately(%W(--disable=gems - #{RUBY}), <<-INPUT, timeout: 100) + assert_separately(["-", RUBY], <<-INPUT, timeout: 80) ruby = ARGV.shift GC.start # reduce garbage GC.disable # avoid triggering CoW after forks @@ -2303,8 +2183,10 @@ EOS parent = $$ 100.times do |i| pid = fork {Process.kill(:QUIT, parent)} - IO.popen([ruby, -'--disable=gems'], -'r+'){} + IO.popen(ruby, 'r+'){} Process.wait(pid) + $stdout.puts + $stdout.flush end INPUT end if defined?(fork) @@ -2314,7 +2196,7 @@ EOS th = Process.detach(pid) assert_equal pid, th.pid status = th.value - assert_predicate status, :success? + assert status.success?, status.inspect end if defined?(fork) def test_kill_at_spawn_failure @@ -2322,9 +2204,7 @@ EOS th = nil x = with_tmpchdir {|d| prog = "#{d}/notexist" - q = Thread::Queue.new - th = Thread.start {system(prog);q.push(nil);sleep} - q.pop + th = Thread.start {system(prog);sleep} th.kill th.join(0.1) } @@ -2375,7 +2255,7 @@ EOS def test_signals_work_after_exec_fail r, w = IO.pipe pid = status = nil - EnvUtil.timeout(30) do + Timeout.timeout(30) do pid = fork do r.close begin @@ -2409,7 +2289,7 @@ EOS def test_threading_works_after_exec_fail r, w = IO.pipe pid = status = nil - EnvUtil.timeout(90) do + Timeout.timeout(90) do pid = fork do r.close begin @@ -2418,6 +2298,7 @@ EOS w.syswrite("exec failed\n") end q = Queue.new + run = true th1 = Thread.new { i = 0; i += 1 while q.empty?; i } th2 = Thread.new { j = 0; j += 1 while q.empty? && Thread.pass.nil?; j } sleep 0.5 @@ -2426,7 +2307,7 @@ EOS end w.close assert_equal "exec failed\n", r.gets - vals = r.gets.split.map!(&:to_i) + vals = r.gets.chomp.split.map!(&:to_i) assert_operator vals[0], :>, vals[1], vals.inspect _, status = Process.waitpid2(pid) end @@ -2442,15 +2323,6 @@ EOS r.close if r end if defined?(fork) - def test_rescue_exec_fail - assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") - begin; - assert_raise(Errno::ENOENT) do - exec("", in: "") - end - end; - end - def test_many_args bug11418 = '[ruby-core:70251] [Bug #11418]' assert_in_out_err([], <<-"end;", ["x"]*256, [], bug11418, timeout: 60) @@ -2501,17 +2373,4 @@ EOS Process.wait spawn(RUBY, "-e", "exit 13") assert_same(Process.last_status, $?) end - - def test_last_status_failure - assert_nil system("sad") - assert_not_predicate $?, :success? - assert_equal $?.exitstatus, 127 - end - - def test_exec_failure_leaves_no_child - assert_raise(Errno::ENOENT) do - spawn('inexistent_command') - end - assert_empty(Process.waitall) - end end diff --git a/test/ruby/test_rand.rb b/test/ruby/test_rand.rb index 13b7329269..882d33fb40 100644 --- a/test/ruby/test_rand.rb +++ b/test/ruby/test_rand.rb @@ -2,13 +2,14 @@ require 'test/unit' class TestRand < Test::Unit::TestCase - def assert_random_int(m, init = 0, iterate: 5) + def assert_random_int(ws, m, init = 0) srand(init) rnds = [Random.new(init)] rnds2 = [rnds[0].dup] rnds3 = [rnds[0].dup] - iterate.times do |i| - w = rand(m) + ws.each_with_index do |w, i| + w = w.to_i + assert_equal(w, rand(m)) rnds.each do |rnd| assert_equal(w, rnd.rand(m)) end @@ -26,97 +27,133 @@ class TestRand < Test::Unit::TestCase end def test_mt - assert_random_int(0x100000000, 0x00000456_00000345_00000234_00000123) + assert_random_int(%w(1067595299 955945823 477289528 4107218783 4228976476), + 0x100000000, 0x00000456_00000345_00000234_00000123) end def test_0x3fffffff - assert_random_int(0x3fffffff) + assert_random_int(%w(209652396 398764591 924231285 404868288 441365315), + 0x3fffffff) end def test_0x40000000 - assert_random_int(0x40000000) + assert_random_int(%w(209652396 398764591 924231285 404868288 441365315), + 0x40000000) end def test_0x40000001 - assert_random_int(0x40000001) + assert_random_int(%w(209652396 398764591 924231285 441365315 192771779), + 0x40000001) end def test_0xffffffff - assert_random_int(0xffffffff) + assert_random_int(%w(2357136044 2546248239 3071714933 3626093760 2588848963), + 0xffffffff) end def test_0x100000000 - assert_random_int(0x100000000) + assert_random_int(%w(2357136044 2546248239 3071714933 3626093760 2588848963), + 0x100000000) end def test_0x100000001 - assert_random_int(0x100000001) + assert_random_int(%w(2546248239 1277901399 243580376 1171049868 2051556033), + 0x100000001) end def test_rand_0x100000000 - assert_random_int(0x100000001, 311702798) + assert_random_int(%w(4119812344 3870378946 80324654 4294967296 410016213), + 0x100000001, 311702798) end def test_0x1000000000000 - assert_random_int(0x1000000000000) + assert_random_int(%w(11736396900911 + 183025067478208 + 197104029029115 + 130583529618791 + 180361239846611), + 0x1000000000000) end def test_0x1000000000001 - assert_random_int(0x1000000000001) + assert_random_int(%w(187121911899765 + 197104029029115 + 180361239846611 + 236336749852452 + 208739549485656), + 0x1000000000001) end def test_0x3fffffffffffffff - assert_random_int(0x3fffffffffffffff) + assert_random_int(%w(900450186894289455 + 3969543146641149120 + 1895649597198586619 + 827948490035658087 + 3203365596207111891), + 0x3fffffffffffffff) end def test_0x4000000000000000 - assert_random_int(0x4000000000000000) + assert_random_int(%w(900450186894289455 + 3969543146641149120 + 1895649597198586619 + 827948490035658087 + 3203365596207111891), + 0x4000000000000000) end def test_0x4000000000000001 - assert_random_int(0x4000000000000001) + assert_random_int(%w(900450186894289455 + 3969543146641149120 + 1895649597198586619 + 827948490035658087 + 2279347887019741461), + 0x4000000000000001) end def test_0x10000000000 - assert_random_int(0x10000000000, 3) + ws = %w(455570294424 1073054410371 790795084744 2445173525 1088503892627) + assert_random_int(ws, 0x10000000000, 3) end def test_0x10000 - assert_random_int(0x10000) - end - - def assert_same_numbers(type, *nums) - nums.each do |n| - assert_instance_of(type, n) - end - x = nums.shift - nums.each do |n| - assert_equal(x, n) - end - x + ws = %w(2732 43567 42613 52416 45891) + assert_random_int(ws, 0x10000) end def test_types - o = Object.new - class << o - def to_int; 100; end - def class; Integer; end - end + srand(0) + rnd = Random.new(0) + assert_equal(44, rand(100.0)) + assert_equal(44, rnd.rand(100)) + assert_equal(1245085576965981900420779258691, rand((2**100).to_f)) + assert_equal(1245085576965981900420779258691, rnd.rand(2**100)) + assert_equal(914679880601515615685077935113, rand(-(2**100).to_f)) srand(0) - nums = [100.0, (2**100).to_f, (2**100), o, o, o].map do |m| - k = Integer - assert_kind_of(k, x = rand(m), m.inspect) - [m, k, x] - end - assert_kind_of(Integer, rand(-(2**100).to_f)) + rnd = Random.new(0) + assert_equal(997707939797331598305742933184, rand(2**100)) + assert_equal(997707939797331598305742933184, rnd.rand(2**100)) + assert_in_delta(0.602763376071644, rand((2**100).coerce(0).first), + 0.000000000000001) + assert_raise(ArgumentError) {rnd.rand((2**100).coerce(0).first)} srand(0) rnd = Random.new(0) - rnd2 = Random.new(0) - nums.each do |m, k, x| - assert_same_numbers(m.class, Random.rand(m), rnd.rand(m), rnd2.rand(m)) - end + assert_in_delta(0.548813503927325, rand(nil), + 0.000000000000001) + assert_in_delta(0.548813503927325, rnd.rand(), + 0.000000000000001) + srand(0) + rnd = Random.new(0) + o = Object.new + def o.to_int; 100; end + assert_equal(44, rand(o)) + assert_equal(44, rnd.rand(o)) + assert_equal(47, rand(o)) + assert_equal(47, rnd.rand(o)) + assert_equal(64, rand(o)) + assert_equal(64, rnd.rand(o)) end def test_srand @@ -126,13 +163,10 @@ class TestRand < Test::Unit::TestCase srand(2**100) rnd = Random.new(2**100) - r = 3.times.map do - assert_same_numbers(Integer, rand(0x100000000), rnd.rand(0x100000000)) - end - srand(2**100) - r.each do |n| - assert_same_numbers(Integer, n, rand(0x100000000)) - end + %w(3258412053).each {|w| + assert_equal(w.to_i, rand(0x100000000)) + assert_equal(w.to_i, rnd.rand(0x100000000)) + } end def test_shuffle @@ -143,17 +177,17 @@ class TestRand < Test::Unit::TestCase end def test_big_seed - assert_random_int(0x100000000, 2**1000000-1) + assert_random_int(%w(2757555016), 0x100000000, 2**1000000-1) end def test_random_gc r = Random.new(0) - 3.times do - assert_kind_of(Integer, r.rand(0x100000000)) + %w(2357136044 2546248239 3071714933).each do |w| + assert_equal(w.to_i, r.rand(0x100000000)) end GC.start - 3.times do - assert_kind_of(Integer, r.rand(0x100000000)) + %w(3626093760 2588848963 3684848379).each do |w| + assert_equal(w.to_i, r.rand(0x100000000)) end end @@ -189,68 +223,183 @@ class TestRand < Test::Unit::TestCase def test_random_dup r1 = Random.new(0) r2 = r1.dup - 3.times do - assert_same_numbers(Integer, r1.rand(0x100000000), r2.rand(0x100000000)) + %w(2357136044 2546248239 3071714933).each do |w| + assert_equal(w.to_i, r1.rand(0x100000000)) + end + %w(2357136044 2546248239 3071714933).each do |w| + assert_equal(w.to_i, r2.rand(0x100000000)) end r2 = r1.dup - 3.times do - assert_same_numbers(Integer, r1.rand(0x100000000), r2.rand(0x100000000)) + %w(3626093760 2588848963 3684848379).each do |w| + assert_equal(w.to_i, r1.rand(0x100000000)) + end + %w(3626093760 2588848963 3684848379).each do |w| + assert_equal(w.to_i, r2.rand(0x100000000)) end end - def test_random_bytes - srand(0) + def test_random_state + state = <<END +3877134065023083674777481835852171977222677629000095857864323111193832400974413 +4782302161934463784850675209112299537259006497924090422596764895633625964527441 +6943943249411681406395713106007661119327771293929504639878577616749110507385924 +0173026285378896836022134086386136835407107422834685854738117043791709411958489 +3504364936306163473541948635570644161010981140452515307286926529085424765299100 +1255453260115310687580777474046203049197643434654645011966794531914127596390825 +0832232869378617194193100828000236737535657699356156021286278281306055217995213 +8911536025132779573429499813926910299964681785069915877910855089314686097947757 +2621451199734871158015842198110309034467412292693435515184023707918034746119728 +8223459645048255809852819129671833854560563104716892857257229121211527031509280 +2390605053896565646658122125171846129817536096211475312518457776328637574563312 +8113489216547503743508184872149896518488714209752552442327273883060730945969461 +6568672445225657265545983966820639165285082194907591432296265618266901318398982 +0560425129536975583916120558652408261759226803976460322062347123360444839683204 +9868507788028894111577023917218846128348302845774997500569465902983227180328307 +3735301552935104196244116381766459468172162284042207680945316590536094294865648 +5953156978630954893391701383648157037914019502853776972615500142898763385846315 +8457790690531675205213829055442306187692107777193071680668153335688203945049935 +3404449910419303330872435985327845889440458370416464132629866593538629877042969 +7589948685901343135964343582727302330074331803900821801076139161904900333497836 +6627028345784450211920229170280462474456504317367706849373957309797251052447898 +8436235456995644876515032202483449807136139063937892187299239634252391529822163 +9187055268750679730919937006195967184206072757082920250075756273182004964087790 +3812024063897424219316687828337007888030994779068081666133751070479581394604974 +6022215489604777611774245181115126041390161592199230774968475944753915533936834 +4740049163514318351045644344358598159463605453475585370226041981040238023241538 +4958436364776113598408428801867643946791659645708540669432995503575075657406359 +8086928867900590554805639837071298576728564946552163206007997000988745940681607 +4542883814997403673656291618517107133421335645430345871041730410669209035640945 +5024601618318371192091626092482640364669969307766919645222516407626038616667754 +5781148898846306894862390724358039251444333889446128074209417936830253204064223 +3424784857908022314095011879203259864909560830176189727132432100010493659154644 +8407326292884826469503093409465946018496358514999175268200846200025235441426140 +7783386235191526371372655894290440356560751680752191224383460972099834655086068 +9989413443881686756951804138910911737670495391762470293978321414964443502180391 +4665982575919524372985773336921990352313629822677022891307943536442258282401255 +5387646898976193134193506239982621725093291970351083631367582570375381334759004 +1784150668048523676387894646666460369896619585113435743180899362844070393586212 +5023920017185866399742380706352739465848708746963693663004068892056705603018655 +8686663087894205699555906146534549176352859823832196938386172810274748624517052 +8356758650653040545267425513047130342286119889879774951060662713807133125543465 +5104086026298674827575216701372513525846650644773241437066782037334367982012148 +7987782004646896468089089826267467005660035604553432197455616078731159778086155 +9443250946037119223468305483694093795324036812927501783593256716590840500905291 +2096608538205270323065573109227029887731553399324547696295234105140157179430410 +4003109602564833086703863221058381556776789018351726488797845637981974580864082 +1630093543020854542240690897858757985640869209737744458407777584279553258261599 +0246922348101147034463235613998979344685018577901996218099622190722307356620796 +5137485271371502385527388080824050288371607602101805675021790116223360483508538 +8832149997794718410946818866375912486788005950091851067237358294899771385995876 +7088239104394332452501033090159333224995108984871426750597513314521294001864578 +2353528356752869732412552685554334966798888534847483030947310518891788722418172 +6008607577773612004956373863580996793809969715725508939568919714424871639667201 +7922255031431159347210833846575355772055570279673262115911154370983086189948124 +4653677615895887099814174914248255026619941911735341818489822197472499295786997 +7728418516719104857455960900092226749725407204388193002835497055305427730656889 +1508308778869166073740855838213112709306743479676740893150000714099064468263284 +1873435518542972182497755500300784177067568586395485329021157235696300013490087 +2866571034916258390528533374944905429089028336079264760836949419754851422499614 +5732326011260304142074554782259843903215064144396140106592193961703288125005023 +5334375212799817540775536847622032852415253966587517800661605905489339306359573 +2234947905196298436841723673626428243649931398749552780311877734063703985375067 +1239508613417041942487245370152912391885566432830659640677893488723724763120121 +4111855277511356759926232894062814360449757490961653026194107761340614059045172 +1123363102660719217740126157997033682099769790976313166682432732518101889210276 +9574144065390305904944821051736021310524344626348851573631697771556587859836330 +6997324121866564283654784470215100159122764509197570402997911258816526554863326 +9877535269005418736225944874608987238997316999444215865249840762640949599725696 +0773083894168959823152054508672272612355108904098579447774398451678239199426513 +3439507737424049578587487505080347686371029156845461151278198605267053408259090 +3158676794894709281917034995611352710898103415304769654883981727681820369090169 +9295163908214854813365413456264812190842699054830709079275249714169405719140093 +1347572458245530016346604698682269779841803667099480215265926316505737171177810 +9969036572310084022695109125200937135540995157279354438704321290061646592229860 +0156566013602344870223183295508278359111174872740360473845615437106413256386849 +2286259982118315248148847764929974917157683083659364623458927512616369119194574 +2254080 +END + state = state.split.join.to_i r = Random.new(0) + srand(0) + assert_equal(state, r.instance_eval { state }) + assert_equal(state, Random.instance_eval { state }) + r.rand(0x100) + assert_equal(state, r.instance_eval { state }) + end - assert_equal("", r.bytes(0)) - assert_equal("", Random.bytes(0)) + def test_random_left + r = Random.new(0) + assert_equal(1, r.instance_eval { left }) + r.rand(0x100) + assert_equal(624, r.instance_eval { left }) + r.rand(0x100) + assert_equal(623, r.instance_eval { left }) + srand(0) + assert_equal(1, Random.instance_eval { left }) + rand(0x100) + assert_equal(624, Random.instance_eval { left }) + rand(0x100) + assert_equal(623, Random.instance_eval { left }) + end - x = r.bytes(1) - assert_equal(1, x.bytesize) - assert_equal(x, Random.bytes(1)) + def test_random_bytes + assert_random_bytes(Random.new(0)) + end - x = r.bytes(10) - assert_equal(10, x.bytesize) - assert_equal(x, Random.bytes(10)) + def assert_random_bytes(r) + assert_equal("", r.bytes(0)) + assert_equal("\xAC".force_encoding("ASCII-8BIT"), r.bytes(1)) + assert_equal("/\xAA\xC4\x97u\xA6\x16\xB7\xC0\xCC".force_encoding("ASCII-8BIT"), + r.bytes(10)) end def test_random_range srand(0) r = Random.new(0) - now = Time.now - [5..9, -1000..1000, 2**100+5..2**100+9, 3.1..4, now..(now+2)].each do |range| - 3.times do - x = rand(range) - assert_instance_of(range.first.class, x) - assert_equal(x, r.rand(range)) - assert_include(range, x) - end + %w(9 5 8).each {|w| + assert_equal(w.to_i, rand(5..9)) + assert_equal(w.to_i, r.rand(5..9)) + } + %w(-237 731 383).each {|w| + assert_equal(w.to_i, rand(-1000..1000)) + assert_equal(w.to_i, r.rand(-1000..1000)) + } + %w(1267650600228229401496703205382 + 1267650600228229401496703205384 + 1267650600228229401496703205383).each do |w| + assert_equal(w.to_i, rand(2**100+5..2**100+9)) + assert_equal(w.to_i, r.rand(2**100+5..2**100+9)) end + + v = rand(3.1..4) + assert_instance_of(Float, v, '[ruby-core:24679]') + assert_include(3.1..4, v) + + v = r.rand(3.1..4) + assert_instance_of(Float, v, '[ruby-core:24679]') + assert_include(3.1..4, v) + + now = Time.now + assert_equal(now, rand(now..now)) + assert_equal(now, r.rand(now..now)) end def test_random_float r = Random.new(0) - 3.times do - assert_include(0...1.0, r.rand) - end - [2.0, (2**100).to_f].each do |x| - range = 0...x - 3.times do - assert_include(range, r.rand(x), "rand(#{x})") - end - end + assert_in_delta(0.5488135039273248, r.rand, 0.0001) + assert_in_delta(0.7151893663724195, r.rand, 0.0001) + assert_in_delta(0.6027633760716439, r.rand, 0.0001) + assert_in_delta(1.0897663659937937, r.rand(2.0), 0.0001) + assert_in_delta(5.3704626067153264e+29, r.rand((2**100).to_f), 10**25) assert_raise(Errno::EDOM, Errno::ERANGE) { r.rand(1.0 / 0.0) } assert_raise(Errno::EDOM, Errno::ERANGE) { r.rand(0.0 / 0.0) } - assert_raise(Errno::EDOM) {r.rand(1..)} - assert_raise(Errno::EDOM) {r.rand(..1)} r = Random.new(0) - [1.0...2.0, 1.0...11.0, 2.0...4.0].each do |range| - 3.times do - assert_include(range, r.rand(range), "[ruby-core:24655] rand(#{range})") - end - end + assert_in_delta(1.5488135039273248, r.rand(1.0...2.0), 0.0001, '[ruby-core:24655]') + assert_in_delta(1.7151893663724195, r.rand(1.0...2.0), 0.0001, '[ruby-core:24655]') + assert_in_delta(7.027633760716439, r.rand(1.0...11.0), 0.0001, '[ruby-core:24655]') + assert_in_delta(3.0897663659937937, r.rand(2.0...4.0), 0.0001, '[ruby-core:24655]') assert_nothing_raised {r.rand(-Float::MAX..Float::MAX)} end @@ -336,6 +485,18 @@ class TestRand < Test::Unit::TestCase } end + def test_default + r1 = Random::DEFAULT.dup + r2 = Random::DEFAULT.dup + 3.times do + x0 = rand + x1 = r1.rand + x2 = r2.rand + assert_equal(x0, x1) + assert_equal(x0, x2) + end + end + def test_marshal bug3656 = '[ruby-core:31622]' assert_raise(TypeError, bug3656) { @@ -392,19 +553,16 @@ class TestRand < Test::Unit::TestCase end def test_default_seed - assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") - begin; - verbose, $VERBOSE = $VERBOSE, nil + assert_separately([], <<-End) seed = Random::DEFAULT::seed rand1 = Random::DEFAULT::rand - $VERBOSE = verbose rand2 = Random.new(seed).rand assert_equal(rand1, rand2) srand seed rand3 = rand assert_equal(rand1, rand3) - end; + End end def test_urandom diff --git a/test/ruby/test_range.rb b/test/ruby/test_range.rb index 8ac1930be6..da883767bc 100644 --- a/test/ruby/test_range.rb +++ b/test/ruby/test_range.rb @@ -3,7 +3,6 @@ require 'test/unit' require 'delegate' require 'timeout' require 'bigdecimal' -require 'rbconfig/sizeof' class TestRange < Test::Unit::TestCase def test_new @@ -13,9 +12,6 @@ class TestRange < Test::Unit::TestCase assert_raise(ArgumentError) { (1.."3") } - assert_equal((0..nil), Range.new(0, nil, false)) - assert_equal((0...nil), Range.new(0, nil, true)) - obj = Object.new def obj.<=>(other) raise RuntimeError, "cmp" @@ -35,17 +31,14 @@ class TestRange < Test::Unit::TestCase assert_equal(["a"], ("a" .. "a").to_a) assert_equal(["a"], ("a" ... "b").to_a) assert_equal(["a", "b"], ("a" .. "b").to_a) - assert_equal([*"a".."z", "aa"], ("a"..).take(27)) end def test_range_numeric_string assert_equal(["6", "7", "8"], ("6".."8").to_a, "[ruby-talk:343187]") assert_equal(["6", "7"], ("6"..."8").to_a) assert_equal(["9", "10"], ("9".."10").to_a) - assert_equal(["9", "10"], ("9"..).take(2)) assert_equal(["09", "10"], ("09".."10").to_a, "[ruby-dev:39361]") assert_equal(["9", "10"], (SimpleDelegator.new("9").."10").to_a) - assert_equal(["9", "10"], (SimpleDelegator.new("9")..).take(2)) assert_equal(["9", "10"], ("9"..SimpleDelegator.new("10")).to_a) end @@ -80,33 +73,22 @@ class TestRange < Test::Unit::TestCase assert_equal(1, (1..2).min) assert_equal(nil, (2..1).min) assert_equal(1, (1...2).min) - assert_equal(1, (1..).min) - assert_raise(RangeError) { (..1).min } - assert_raise(RangeError) { (...1).min } assert_equal(1.0, (1.0..2.0).min) assert_equal(nil, (2.0..1.0).min) assert_equal(1, (1.0...2.0).min) - assert_equal(1, (1.0..).min) assert_equal(0, (0..0).min) assert_equal(nil, (0...0).min) assert_equal([0,1,2], (0..10).min(3)) assert_equal([0,1], (0..1).min(3)) - assert_equal([0,1,2], (0..).min(3)) - assert_raise(RangeError) { (..1).min(3) } - assert_raise(RangeError) { (...1).min(3) } - - assert_raise(RangeError) { (0..).min {|a, b| a <=> b } } end def test_max assert_equal(2, (1..2).max) assert_equal(nil, (2..1).max) assert_equal(1, (1...2).max) - assert_raise(RangeError) { (1..).max } - assert_raise(RangeError) { (1...).max } assert_equal(2.0, (1.0..2.0).max) assert_equal(nil, (2.0..1.0).max) @@ -121,50 +103,12 @@ class TestRange < Test::Unit::TestCase assert_equal([10,9,8], (0..10).max(3)) assert_equal([9,8,7], (0...10).max(3)) - assert_raise(RangeError) { (1..).max(3) } - assert_raise(RangeError) { (1...).max(3) } - - assert_raise(RangeError) { (..0).min {|a, b| a <=> b } } - - assert_equal(2, (..2).max) - assert_raise(TypeError) { (...2).max } - assert_raise(TypeError) { (...2.0).max } - - assert_equal(Float::INFINITY, (1..Float::INFINITY).max) - assert_nil((1..-Float::INFINITY).max) - end - - def test_minmax - assert_equal([1, 2], (1..2).minmax) - assert_equal([nil, nil], (2..1).minmax) - assert_equal([1, 1], (1...2).minmax) - assert_raise(RangeError) { (1..).minmax } - assert_raise(RangeError) { (1...).minmax } - - assert_equal([1.0, 2.0], (1.0..2.0).minmax) - assert_equal([nil, nil], (2.0..1.0).minmax) - assert_raise(TypeError) { (1.0...2.0).minmax } - assert_raise(TypeError) { (1...1.5).minmax } - assert_raise(TypeError) { (1.5...2).minmax } - - assert_equal([-0x80000002, -0x80000002], ((-0x80000002)...(-0x80000001)).minmax) - - assert_equal([0, 0], (0..0).minmax) - assert_equal([nil, nil], (0...0).minmax) - - assert_equal([2, 1], (1..2).minmax{|a, b| b <=> a}) - - assert_equal(['a', 'c'], ('a'..'c').minmax) - assert_equal(['a', 'b'], ('a'...'c').minmax) - - assert_equal([1, Float::INFINITY], (1..Float::INFINITY).minmax) - assert_equal([nil, nil], (1..-Float::INFINITY).minmax) end def test_initialize_twice r = eval("1..2") - assert_raise(FrozenError) { r.instance_eval { initialize 3, 4 } } - assert_raise(FrozenError) { r.instance_eval { initialize_copy 3..4 } } + assert_raise(NameError) { r.instance_eval { initialize 3, 4 } } + assert_raise(NameError) { r.instance_eval { initialize_copy 3..4 } } end def test_uninitialized_range @@ -179,10 +123,9 @@ class TestRange < Test::Unit::TestCase assert_equal(r, Marshal.load(Marshal.dump(r))) r = 1...2 assert_equal(r, Marshal.load(Marshal.dump(r))) - r = (1..) - assert_equal(r, Marshal.load(Marshal.dump(r))) - r = (1...) - assert_equal(r, Marshal.load(Marshal.dump(r))) + s = Marshal.dump(r) + s.sub!(/endi./n, 'end0') + assert_raise(ArgumentError) {Marshal.load(s)} end def test_bad_value @@ -192,8 +135,6 @@ class TestRange < Test::Unit::TestCase def test_exclude_end assert_not_predicate(0..1, :exclude_end?) assert_predicate(0...1, :exclude_end?) - assert_not_predicate(0.., :exclude_end?) - assert_predicate(0..., :exclude_end?) end def test_eq @@ -204,17 +145,8 @@ class TestRange < Test::Unit::TestCase assert_not_equal(r, (1..2)) assert_not_equal(r, (0..2)) assert_not_equal(r, (0...1)) - assert_not_equal(r, (0..nil)) subclass = Class.new(Range) assert_equal(r, subclass.new(0,1)) - - r = (0..nil) - assert_equal(r, r) - assert_equal(r, (0..nil)) - assert_not_equal(r, 0) - assert_not_equal(r, (0...nil)) - subclass = Class.new(Range) - assert_equal(r, subclass.new(0,nil)) end def test_eql @@ -227,22 +159,12 @@ class TestRange < Test::Unit::TestCase assert_not_operator(r, :eql?, 0...1) subclass = Class.new(Range) assert_operator(r, :eql?, subclass.new(0,1)) - - r = (0..nil) - assert_operator(r, :eql?, r) - assert_operator(r, :eql?, 0..nil) - assert_not_operator(r, :eql?, 0) - assert_not_operator(r, :eql?, 0...nil) - subclass = Class.new(Range) - assert_operator(r, :eql?, subclass.new(0,nil)) end def test_hash assert_kind_of(Integer, (0..1).hash) assert_equal((0..1).hash, (0..1).hash) assert_not_equal((0..1).hash, (0...1).hash) - assert_equal((0..nil).hash, (0..nil).hash) - assert_not_equal((0..nil).hash, (0...nil).hash) assert_kind_of(String, (0..1).hash.to_s) end @@ -252,79 +174,31 @@ class TestRange < Test::Unit::TestCase assert_equal([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], a) a = [] - (0..).step {|x| a << x; break if a.size == 10 } - assert_equal([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], a) - - a = [] (0..10).step(2) {|x| a << x } assert_equal([0, 2, 4, 6, 8, 10], a) - a = [] - (0..).step(2) {|x| a << x; break if a.size == 10 } - assert_equal([0, 2, 4, 6, 8, 10, 12, 14, 16, 18], a) - - assert_kind_of(Enumerator::ArithmeticSequence, (0..10).step) - assert_kind_of(Enumerator::ArithmeticSequence, (0..10).step(2)) - assert_kind_of(Enumerator::ArithmeticSequence, (0..10).step(0.5)) - assert_kind_of(Enumerator::ArithmeticSequence, (10..0).step(-1)) - assert_kind_of(Enumerator::ArithmeticSequence, (..10).step(2)) - assert_kind_of(Enumerator::ArithmeticSequence, (1..).step(2)) - assert_raise(ArgumentError) { (0..10).step(-1) { } } - assert_raise(ArgumentError) { (0..10).step(0) } assert_raise(ArgumentError) { (0..10).step(0) { } } - assert_raise(ArgumentError) { (0..).step(-1) { } } - assert_raise(ArgumentError) { (0..).step(0) } - assert_raise(ArgumentError) { (0..).step(0) { } } a = [] ("a" .. "z").step(2) {|x| a << x } assert_equal(%w(a c e g i k m o q s u w y), a) a = [] - ("a" .. ).step(2) {|x| a << x; break if a.size == 13 } - assert_equal(%w(a c e g i k m o q s u w y), a) - - a = [] ("a" .. "z").step(2**32) {|x| a << x } assert_equal(["a"], a) a = [] - (:a .. :z).step(2) {|x| a << x } - assert_equal(%i(a c e g i k m o q s u w y), a) - - a = [] - (:a .. ).step(2) {|x| a << x; break if a.size == 13 } - assert_equal(%i(a c e g i k m o q s u w y), a) - - a = [] - (:a .. :z).step(2**32) {|x| a << x } - assert_equal([:a], a) - - a = [] (2**32-1 .. 2**32+1).step(2) {|x| a << x } assert_equal([4294967295, 4294967297], a) zero = (2**32).coerce(0).first - assert_raise(ArgumentError) { (2**32-1 .. 2**32+1).step(zero) } assert_raise(ArgumentError) { (2**32-1 .. 2**32+1).step(zero) { } } - a = [] - (2**32-1 .. ).step(2) {|x| a << x; break if a.size == 2 } - assert_equal([4294967295, 4294967297], a) - - max = RbConfig::LIMITS["FIXNUM_MAX"] - a = [] - (max..).step {|x| a << x; break if a.size == 2 } - assert_equal([max, max+1], a) - a = [] - (max..).step(max) {|x| a << x; break if a.size == 4 } - assert_equal([max, 2*max, 3*max, 4*max], a) o1 = Object.new o2 = Object.new def o1.<=>(x); -1; end def o2.<=>(x); 0; end assert_raise(TypeError) { (o1..o2).step(1) { } } - assert_raise(TypeError) { (o1..).step(1) { } } class << o1; self; end.class_eval do define_method(:succ) { o2 } @@ -344,43 +218,12 @@ class TestRange < Test::Unit::TestCase assert_equal([0, 0.5, 1.0, 1.5, 2.0], a) a = [] - (0..).step(0.5) {|x| a << x; break if a.size == 5 } - assert_equal([0, 0.5, 1.0, 1.5, 2.0], a) - - a = [] (0x40000000..0x40000002).step(0.5) {|x| a << x } assert_equal([1073741824, 1073741824.5, 1073741825.0, 1073741825.5, 1073741826], a) o = Object.new def o.to_int() 1 end assert_nothing_raised("[ruby-dev:34558]") { (0..2).step(o) {|x| } } - - o = Object.new - class << o - def to_str() "a" end - def <=>(other) to_str <=> other end - end - - a = [] - (o.."c").step(1) {|x| a << x} - assert_equal(["a", "b", "c"], a) - a = [] - (o..).step(1) {|x| a << x; break if a.size >= 3} - assert_equal(["a", "b", "c"], a) - end - - def test_step_bug15537 - assert_equal([10.0, 9.0, 8.0, 7.0], (10 ..).step(-1.0).take(4)) - assert_equal([10.0, 9.0, 8.0, 7.0], (10.0 ..).step(-1).take(4)) - end - - def test_percent_step - aseq = (1..10) % 2 - assert_equal(Enumerator::ArithmeticSequence, aseq.class) - assert_equal(1, aseq.begin) - assert_equal(10, aseq.end) - assert_equal(2, aseq.step) - assert_equal([1, 3, 5, 7, 9], aseq.to_a) end def test_step_ruby_core_35753 @@ -397,10 +240,6 @@ class TestRange < Test::Unit::TestCase (0..10).each {|x| a << x } assert_equal([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], a) - a = [] - (0..).each {|x| a << x; break if a.size == 10 } - assert_equal([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], a) - o1 = Object.new o2 = Object.new def o1.setcmp(v) @cmpresult = v end @@ -441,28 +280,12 @@ class TestRange < Test::Unit::TestCase a = [] r2.each {|x| a << x } assert_equal([], a) - - o = Object.new - class << o - def to_str() "a" end - def <=>(other) to_str <=> other end - end - - a = [] - (o.."c").each {|x| a << x} - assert_equal(["a", "b", "c"], a) - a = [] - (o..).each {|x| a << x; break if a.size >= 3} - assert_equal(["a", "b", "c"], a) end def test_begin_end assert_equal(0, (0..1).begin) assert_equal(1, (0..1).end) assert_equal(1, (0...1).end) - assert_equal(0, (0..nil).begin) - assert_equal(nil, (0..nil).end) - assert_equal(nil, (0...nil).end) end def test_first_last @@ -481,72 +304,31 @@ class TestRange < Test::Unit::TestCase assert_equal("a", ("a"..."c").first) assert_equal("c", ("a"..."c").last) assert_equal(0, (2...0).last) - - assert_equal([0, 1, 2], (0..nil).first(3)) - assert_equal(0, (0..nil).first) - assert_equal("a", ("a"..nil).first) - assert_raise(RangeError) { (0..nil).last } - assert_raise(RangeError) { (0..nil).last(3) } - assert_raise(RangeError) { (nil..0).first } - assert_raise(RangeError) { (nil..0).first(3) } - - assert_equal([0, 1, 2], (0..10).first(3.0)) - assert_equal([8, 9, 10], (0..10).last(3.0)) - assert_raise(TypeError) { (0..10).first("3") } - assert_raise(TypeError) { (0..10).last("3") } - class << (o = Object.new) - def to_int; 3; end - end - assert_equal([0, 1, 2], (0..10).first(o)) - assert_equal([8, 9, 10], (0..10).last(o)) - - assert_raise(ArgumentError) { (0..10).first(-1) } - assert_raise(ArgumentError) { (0..10).last(-1) } - end - - def test_last_with_redefine_each - assert_in_out_err([], <<-'end;', ['true'], []) - class Range - remove_method :each - def each(&b) - [1, 2, 3, 4, 5].each(&b) - end - end - puts [3, 4, 5] == (1..10).last(3) - end; end def test_to_s assert_equal("0..1", (0..1).to_s) assert_equal("0...1", (0...1).to_s) - assert_equal("0..", (0..nil).to_s) - assert_equal("0...", (0...nil).to_s) + + bug11767 = '[ruby-core:71811] [Bug #11767]' + assert_predicate(("0".taint.."1").to_s, :tainted?, bug11767) + assert_predicate(("0".."1".taint).to_s, :tainted?, bug11767) + assert_predicate(("0".."1").taint.to_s, :tainted?, bug11767) end def test_inspect assert_equal("0..1", (0..1).inspect) assert_equal("0...1", (0...1).inspect) - assert_equal("0..", (0..nil).inspect) - assert_equal("0...", (0...nil).inspect) - assert_equal("..1", (nil..1).inspect) - assert_equal("...1", (nil...1).inspect) - assert_equal("nil..nil", (nil..nil).inspect) - assert_equal("nil...nil", (nil...nil).inspect) + + bug11767 = '[ruby-core:71811] [Bug #11767]' + assert_predicate(("0".taint.."1").inspect, :tainted?, bug11767) + assert_predicate(("0".."1".taint).inspect, :tainted?, bug11767) + assert_predicate(("0".."1").taint.inspect, :tainted?, bug11767) end def test_eqq assert_operator(0..10, :===, 5) assert_not_operator(0..10, :===, 11) - assert_operator(5..nil, :===, 11) - assert_not_operator(5..nil, :===, 0) - end - - def test_eqq_string - assert_operator('A'..'Z', :===, 'ANA') - assert_not_operator('A'..'Z', :===, 'ana') - assert_operator('A'.., :===, 'ANA') - assert_operator(..'Z', :===, 'ANA') - assert_operator(nil..nil, :===, 'ANA') end def test_eqq_time @@ -554,8 +336,6 @@ class TestRange < Test::Unit::TestCase t = Time.now assert_nothing_raised(TypeError, bug11113) { assert_operator(t..(t+10), :===, t+5) - assert_operator(t.., :===, t+5) - assert_not_operator(t.., :===, t-5) } end @@ -583,27 +363,13 @@ class TestRange < Test::Unit::TestCase assert_operator(c.new(0)..c.new(10), :===, c.new(5), bug12003) end - def test_eqq_non_iteratable - k = Class.new do - include Comparable - attr_reader :i - def initialize(i) @i = i; end - def <=>(o); i <=> o.i; end - end - assert_operator(k.new(0)..k.new(2), :===, k.new(1)) - end - def test_include assert_include("a".."z", "c") assert_not_include("a".."z", "5") assert_include("a"..."z", "y") assert_not_include("a"..."z", "z") assert_not_include("a".."z", "cc") - assert_include("a".., "c") - assert_not_include("a".., "5") assert_include(0...10, 5) - assert_include(5..., 10) - assert_not_include(5..., 0) end def test_cover @@ -612,60 +378,6 @@ class TestRange < Test::Unit::TestCase assert_operator("a"..."z", :cover?, "y") assert_not_operator("a"..."z", :cover?, "z") assert_operator("a".."z", :cover?, "cc") - assert_not_operator(5..., :cover?, 0) - assert_not_operator(5..., :cover?, "a") - assert_operator(5.., :cover?, 10) - - assert_operator(2..5, :cover?, 2..5) - assert_operator(2...6, :cover?, 2...6) - assert_operator(2...6, :cover?, 2..5) - assert_operator(2..5, :cover?, 2...6) - assert_operator(2..5, :cover?, 2..4) - assert_operator(2..5, :cover?, 2...4) - assert_operator(2..5, :cover?, 2...5) - assert_operator(2..5, :cover?, 3..5) - assert_operator(2..5, :cover?, 3..4) - assert_operator(2..5, :cover?, 3...6) - assert_operator(2...6, :cover?, 2...5) - assert_operator(2...6, :cover?, 2..5) - assert_operator(2..6, :cover?, 2...6) - assert_operator(2.., :cover?, 2..) - assert_operator(2.., :cover?, 3..) - assert_operator(1.., :cover?, 1..10) - assert_operator(..2, :cover?, ..2) - assert_operator(..2, :cover?, ..1) - assert_operator(..2, :cover?, 0..1) - assert_operator(2.0..5.0, :cover?, 2..3) - assert_operator(2..5, :cover?, 2.0..3.0) - assert_operator(2..5, :cover?, 2.0...3.0) - assert_operator(2..5, :cover?, 2.0...5.0) - assert_operator(2.0..5.0, :cover?, 2.0...3.0) - assert_operator(2.0..5.0, :cover?, 2.0...5.0) - assert_operator('aa'..'zz', :cover?, 'aa'...'bb') - - assert_not_operator(2..5, :cover?, 1..5) - assert_not_operator(2...6, :cover?, 1..5) - assert_not_operator(2..5, :cover?, 1...6) - assert_not_operator(1..3, :cover?, 1...6) - assert_not_operator(2..5, :cover?, 2..6) - assert_not_operator(2...6, :cover?, 2..6) - assert_not_operator(2...6, :cover?, 2...7) - assert_not_operator(2..3, :cover?, 1..4) - assert_not_operator(1..2, :cover?, 1.0..3.0) - assert_not_operator(1.0..2.9, :cover?, 1.0..3.0) - assert_not_operator(1..2, :cover?, 4..3) - assert_not_operator(2..1, :cover?, 1..2) - assert_not_operator(1...2, :cover?, 1...3) - assert_not_operator(2.., :cover?, 1..) - assert_not_operator(2.., :cover?, 1..10) - assert_not_operator(2.., :cover?, ..10) - assert_not_operator(1..10, :cover?, 1..) - assert_not_operator(1..10, :cover?, ..1) - assert_not_operator(1..5, :cover?, 3..2) - assert_not_operator(1..10, :cover?, 3...2) - assert_not_operator(1..10, :cover?, 3...3) - assert_not_operator('aa'..'zz', :cover?, 'aa'...'zzz') - assert_not_operator(1..10, :cover?, 1...10.1) end def test_beg_len @@ -743,13 +455,6 @@ class TestRange < Test::Unit::TestCase assert_equal 6, (1...6.3).size assert_equal 5, (1.1...6).size assert_equal 42, (1..42).each.size - assert_nil ("a"..."z").size - - assert_equal Float::INFINITY, (1...).size - assert_equal Float::INFINITY, (1.0...).size - assert_equal Float::INFINITY, (...1).size - assert_equal Float::INFINITY, (...1.0).size - assert_nil ("a"...).size end def test_bsearch_typechecks_return_values @@ -791,9 +496,6 @@ class TestRange < Test::Unit::TestCase ary = [0, 100, 100, 100, 200] assert_equal(1, (0...ary.size).bsearch {|i| ary[i] >= 100 }) - - assert_equal(1_000_001, (0...).bsearch {|i| i > 1_000_000 }) - assert_equal( -999_999, (...0).bsearch {|i| i > -1_000_000 }) end def test_bsearch_for_float @@ -845,9 +547,6 @@ class TestRange < Test::Unit::TestCase assert_in_delta(1.0, (0.0..inf).bsearch {|x| Math.log(x) >= 0 }) assert_in_delta(7.0, (0.0..10).bsearch {|x| 7.0 - x }) - - assert_equal( 1_000_000.0.next_float, (0.0..).bsearch {|x| x > 1_000_000 }) - assert_equal(-1_000_000.0.next_float, (..0.0).bsearch {|x| x > -1_000_000 }) end def check_bsearch_values(range, search, a) @@ -949,8 +648,6 @@ class TestRange < Test::Unit::TestCase assert_equal(nil, (bignum...bignum+ary.size).bsearch {|i| ary[i - bignum] >= 100 }) assert_equal(bignum + 0, (bignum...bignum+ary.size).bsearch {|i| true }) assert_equal(nil, (bignum...bignum+ary.size).bsearch {|i| false }) - assert_equal(bignum * 2 + 1, (bignum...).bsearch {|i| i > bignum * 2 }) - assert_equal(-bignum * 2 + 1, (...-bignum).bsearch {|i| i > -bignum * 2 }) assert_raise(TypeError) { ("a".."z").bsearch {} } end @@ -962,18 +659,4 @@ class TestRange < Test::Unit::TestCase end (a.."c").each {|x, &b| assert_nil(b)} end - - def test_to_a - assert_equal([1,2,3,4,5], (1..5).to_a) - assert_equal([1,2,3,4], (1...5).to_a) - assert_raise(RangeError) { (1..).to_a } - end - - def test_beginless_range_iteration - assert_raise(TypeError) { (..1).each { } } - end - - def test_count - assert_equal(Float::INFINITY, (1..).count) - end end diff --git a/test/ruby/test_rational.rb b/test/ruby/test_rational.rb index 820dd30a82..2152486742 100644 --- a/test/ruby/test_rational.rb +++ b/test/ruby/test_rational.rb @@ -110,7 +110,6 @@ class Rational_Test < Test::Unit::TestCase assert_equal(Rational(3),Rational('3')) assert_equal(Rational(1),Rational('3.0','3.0')) assert_equal(Rational(1),Rational('3/3','3/3')) - assert_equal(Rational(111, 1), Rational('1.11e+2')) assert_equal(Rational(111, 10), Rational('1.11e+1')) assert_equal(Rational(111, 10), Rational('1.11e1')) assert_equal(Rational(111, 100), Rational('1.11e0')) @@ -120,42 +119,7 @@ class Rational_Test < Test::Unit::TestCase assert_raise_with_message(ArgumentError, /\u{221a 2668}/) { Rational("\u{221a 2668}") } - assert_warning('') { - assert_predicate(Rational('1e-99999999999999999999'), :zero?) - } - assert_raise(TypeError){Rational(Object.new)} - assert_raise(TypeError){Rational(Object.new, Object.new)} - assert_raise(TypeError){Rational(1, Object.new)} - - bug12485 = '[ruby-core:75995] [Bug #12485]' - o = Object.new - def o.to_int; 1; end - assert_equal(1, Rational(o, 1), bug12485) - assert_equal(1, Rational(1, o), bug12485) - assert_equal(1, Rational(o, o), bug12485) - - o = Object.new - def o.to_r; 1/42r; end - assert_equal(1/42r, Rational(o)) - assert_equal(1/84r, Rational(o, 2)) - assert_equal(42, Rational(1, o)) - assert_equal(1, Rational(o, o)) - - o = Object.new - def o.to_r; nil; end - assert_raise(TypeError) { Rational(o) } - assert_raise(TypeError) { Rational(o, 2) } - assert_raise(TypeError) { Rational(1, o) } - assert_raise(TypeError) { Rational(o, o) } - - o = Object.new - def o.to_r; raise; end - assert_raise(RuntimeError) { Rational(o) } - assert_raise(RuntimeError) { Rational(o, 2) } - assert_raise(RuntimeError) { Rational(1, o) } - assert_raise(RuntimeError) { Rational(o, o) } - assert_raise(ArgumentError){Rational()} assert_raise(ArgumentError){Rational(1,2,3)} @@ -165,14 +129,6 @@ class Rational_Test < Test::Unit::TestCase if (1.0/0).infinite? assert_raise(FloatDomainError){Rational(1.0/0)} end - - bug16518 = "[ruby-core:96942] [Bug #16518]" - cls = Class.new(Numeric) do - def /(y); 42; end - def to_r; 1r; end - def to_int; 1; end - end - assert_equal(1/2r, Rational(cls.new, 2), bug16518) end def test_attr @@ -610,7 +566,7 @@ class Rational_Test < Test::Unit::TestCase assert_equal([Rational(2.2),Rational(1)], Rational(1).coerce(2.2)) assert_equal([Rational(2),Rational(1)], Rational(1).coerce(Rational(2))) - assert_nothing_raised(TypeError, '[Bug #5020] [ruby-dev:44088]') do + assert_nothing_raised(TypeError, '[Bug #5020] [ruby-devl:44088]') do Rational(1,2).coerce(Complex(1,1)) end end @@ -823,54 +779,6 @@ class Rational_Test < Test::Unit::TestCase assert_raise(ZeroDivisionError) {Rational("1/0")} end - def test_Rational_with_invalid_exception - assert_raise(ArgumentError) { - Rational("1/1", exception: 1) - } - end - - def test_Rational_without_exception - assert_nothing_raised(ArgumentError) { - assert_equal(nil, Rational("5/3x", exception: false)) - } - assert_nothing_raised(ZeroDivisionError) { - assert_equal(nil, Rational("1/0", exception: false)) - } - assert_nothing_raised(TypeError) { - assert_equal(nil, Rational(nil, exception: false)) - } - assert_nothing_raised(TypeError) { - assert_equal(nil, Rational(Object.new, exception: false)) - } - assert_nothing_raised(TypeError) { - assert_equal(nil, Rational(1, nil, exception: false)) - } - assert_nothing_raised(TypeError) { - assert_equal(nil, Rational(1, Object.new, exception: false)) - } - - bug12485 = '[ruby-core:75995] [Bug #12485]' - assert_nothing_raised(RuntimeError, bug12485) { - o = Object.new - def o.to_int; raise; end - assert_equal(nil, Rational(o, exception: false)) - } - assert_nothing_raised(RuntimeError, bug12485) { - o = Object.new - def o.to_int; raise; end - assert_equal(nil, Rational(1, o, exception: false)) - } - - o = Object.new; - def o.to_r; raise; end - assert_nothing_raised(RuntimeError) { - assert_equal(nil, Rational(o, exception: false)) - } - assert_nothing_raised(TypeError) { - assert_equal(nil, Rational(1, o, exception: false)) - } - end - def test_to_i assert_equal(1, Rational(3,2).to_i) assert_equal(1, Integer(Rational(3,2))) @@ -879,7 +787,6 @@ class Rational_Test < Test::Unit::TestCase def test_to_f assert_equal(1.5, Rational(3,2).to_f) assert_equal(1.5, Float(Rational(3,2))) - assert_equal(1e-23, Rational(1, 10**23).to_f, "Bug #14637") end def test_to_c diff --git a/test/ruby/test_refinement.rb b/test/ruby/test_refinement.rb index c364de46e4..7725820038 100644 --- a/test/ruby/test_refinement.rb +++ b/test/ruby/test_refinement.rb @@ -19,10 +19,6 @@ class TestRefinement < Test::Unit::TestCase return "Foo#a" end - def b - return "Foo#b" - end - def call_x return x end @@ -45,10 +41,6 @@ class TestRefinement < Test::Unit::TestCase def a return "FooExt#a" end - - private def b - return "FooExt#b" - end end end @@ -102,26 +94,10 @@ class TestRefinement < Test::Unit::TestCase return foo.send(:z) end - def self.send_b_on(foo) - return foo.send(:b) - end - - def self.public_send_z_on(foo) - return foo.public_send(:z) - end - - def self.public_send_b_on(foo) - return foo.public_send(:b) - end - def self.method_z(foo) return foo.method(:z) end - def self.instance_method_z(foo) - return foo.class.instance_method(:z) - end - def self.invoke_call_x_on(foo) return foo.call_x end @@ -203,63 +179,16 @@ class TestRefinement < Test::Unit::TestCase foo = Foo.new assert_raise(NoMethodError) { foo.send(:z) } assert_equal("FooExt#z", FooExtClient.send_z_on(foo)) - assert_equal("FooExt#b", FooExtClient.send_b_on(foo)) assert_raise(NoMethodError) { foo.send(:z) } assert_equal(true, RespondTo::Sub.new.respond_to?(:foo)) end - def test_public_send_should_use_refinements - foo = Foo.new - assert_raise(NoMethodError) { foo.public_send(:z) } - assert_equal("FooExt#z", FooExtClient.public_send_z_on(foo)) - assert_equal("Foo#b", foo.public_send(:b)) - assert_raise(NoMethodError) { FooExtClient.public_send_b_on(foo) } - end - - module MethodIntegerPowEx - refine Integer do - def pow(*) - :refine_pow - end - end - end - def test_method_should_use_refinements - skip if Minitest::Unit.current_repeat_count > 0 - + def test_method_should_not_use_refinements foo = Foo.new assert_raise(NameError) { foo.method(:z) } - assert_equal("FooExt#z", FooExtClient.method_z(foo).call) + assert_raise(NameError) { FooExtClient.method_z(foo) } assert_raise(NameError) { foo.method(:z) } - assert_equal(8, eval(<<~EOS, Sandbox::BINDING)) - meth = 2.method(:pow) - using MethodIntegerPowEx - meth.call(3) - EOS - assert_equal(:refine_pow, eval_using(MethodIntegerPowEx, "2.pow(3)")) - assert_equal(:refine_pow, eval_using(MethodIntegerPowEx, "2.method(:pow).(3)")) - end - - module InstanceMethodIntegerPowEx - refine Integer do - def abs - :refine_abs - end - end - end - def test_instance_method_should_use_refinements - skip if Minitest::Unit.current_repeat_count > 0 - - foo = Foo.new - assert_raise(NameError) { Foo.instance_method(:z) } - assert_equal("FooExt#z", FooExtClient.instance_method_z(foo).bind(foo).call) - assert_raise(NameError) { Foo.instance_method(:z) } - assert_equal(4, eval(<<~EOS, Sandbox::BINDING)) - meth = Integer.instance_method(:abs) - using InstanceMethodIntegerPowEx - meth.bind(-4).call - EOS - assert_equal(:refine_abs, eval_using(InstanceMethodIntegerPowEx, "Integer.instance_method(:abs).bind(-4).call")) end def test_no_local_rebinding @@ -368,9 +297,9 @@ class TestRefinement < Test::Unit::TestCase end end - def test_respond_to_should_use_refinements + def test_respond_to_should_not_use_refinements assert_equal(false, 1.respond_to?(:foo)) - assert_equal(true, eval_using(IntegerFooExt, "1.respond_to?(:foo)")) + assert_equal(false, eval_using(IntegerFooExt, "1.respond_to?(:foo)")) end module StringCmpExt @@ -542,7 +471,7 @@ class TestRefinement < Test::Unit::TestCase def test_main_using_is_private assert_raise(NoMethodError) do - eval("recv = self; recv.using Module.new", Sandbox::BINDING) + eval("self.using Module.new", Sandbox::BINDING) end end @@ -920,7 +849,7 @@ class TestRefinement < Test::Unit::TestCase #{PrependAfterRefine_CODE} undef PrependAfterRefine } - }, timeout: 60 + } end def test_prepend_after_refine @@ -978,10 +907,6 @@ class TestRefinement < Test::Unit::TestCase return foo.send(:z) end - def self.public_send_z_on(foo) - return foo.public_send(:z) - end - def self.method_z(foo) return foo.method(:z) end @@ -1566,7 +1491,6 @@ class TestRefinement < Test::Unit::TestCase undef :foo end end - ext end def test_call_refined_method_in_duplicate_module @@ -1652,6 +1576,7 @@ class TestRefinement < Test::Unit::TestCase def test_reopen_refinement_module assert_separately([], <<-"end;") + $VERBOSE = nil class C end @@ -1668,7 +1593,6 @@ class TestRefinement < Test::Unit::TestCase module R refine C do - alias m m def m :bar end @@ -2068,6 +1992,7 @@ class TestRefinement < Test::Unit::TestCase def test_tostring assert_equal("ok", ToString.new.string) + assert_predicate(ToString.new.taint.string, :tainted?) end class ToSymbol @@ -2085,122 +2010,6 @@ class TestRefinement < Test::Unit::TestCase assert_equal(:foo, ToSymbol.new("foo").symbol) end - module ToProc - def self.call &block - block.call - end - - class ReturnProc - c = self - using Module.new { - refine c do - def to_proc - proc { "to_proc" } - end - end - } - def call - ToProc.call(&self) - end - end - - class ReturnNoProc - c = self - using Module.new { - refine c do - def to_proc - true - end - end - } - - def call - ToProc.call(&self) - end - end - - class PrivateToProc - c = self - using Module.new { - refine c do - private - def to_proc - proc { "private_to_proc" } - end - end - } - - def call - ToProc.call(&self) - end - end - - - class NonProc - def call - ToProc.call(&self) - end - end - - class MethodMissing - def method_missing *args - proc { "method_missing" } - end - - def call - ToProc.call(&self) - end - end - - class ToProcAndMethodMissing - def method_missing *args - proc { "method_missing" } - end - - c = self - using Module.new { - refine c do - def to_proc - proc { "to_proc" } - end - end - } - - def call - ToProc.call(&self) - end - end - - class ToProcAndRefinements - def to_proc - proc { "to_proc" } - end - - c = self - using Module.new { - refine c do - def to_proc - proc { "refinements_to_proc" } - end - end - } - - def call - ToProc.call(&self) - end - end - end - - def test_to_proc - assert_equal("to_proc", ToProc::ReturnProc.new.call) - assert_equal("private_to_proc", ToProc::PrivateToProc.new.call) - assert_raise(TypeError){ ToProc::ReturnNoProc.new.call } - assert_raise(TypeError){ ToProc::NonProc.new.call } - assert_equal("method_missing", ToProc::MethodMissing.new.call) - assert_equal("to_proc", ToProc::ToProcAndMethodMissing.new.call) - assert_equal("refinements_to_proc", ToProc::ToProcAndRefinements.new.call) - end - def test_unused_refinement_for_module bug14068 = '[ruby-core:83613] [Bug #14068]' assert_in_out_err([], <<-INPUT, ["M1#foo"], [], bug14068) @@ -2295,197 +2104,6 @@ class TestRefinement < Test::Unit::TestCase end end assert_equal("[C[A[B]]]", c.new.foo, '[ruby-dev:50390] [Bug #14232]') - d - end - - class RefineInUsing - module M1 - refine RefineInUsing do - def foo - :ok - end - end - end - - module M2 - using M1 - refine RefineInUsing do - def call_foo - RefineInUsing.new.foo - end - end - end - - using M2 - def self.test - new.call_foo - end - end - - def test_refine_in_using - assert_equal(:ok, RefineInUsing.test) - end - - class Bug16242 - module OtherM - end - - module M - prepend OtherM - - refine M do - def refine_method - "refine_method" - end - end - using M - - def hoge - refine_method - end - end - - class X - include M - end - end - - def test_refine_prepended_module - assert_equal("refine_method", Bug16242::X.new.hoge) - end - - module Bug13446 - module Enumerable - def sum(*args) - i = 0 - args.each { |arg| i += a } - i - end - end - - using Module.new { - refine Enumerable do - alias :orig_sum :sum - end - } - - module Enumerable - def sum(*args) - orig_sum(*args) - end - end - - class GenericEnumerable - include Enumerable - end - - Enumerable.prepend(Module.new) - end - - def test_prepend_refined_module - assert_equal(0, Bug13446::GenericEnumerable.new.sum) - end - - def test_unbound_refine_method - a = EnvUtil.labeled_class("A") do - def foo - self.class - end - end - b = EnvUtil.labeled_class("B") - bar = EnvUtil.labeled_module("R") do - break refine a do - def foo - super - end - end - end - assert_raise(TypeError) do - bar.instance_method(:foo).bind(b.new) - end - end - - def test_refine_frozen_class - verbose_bak, $VERBOSE = $VERBOSE, nil - singleton_class.instance_variable_set(:@x, self) - class << self - c = Class.new do - def foo - :cfoo - end - end - foo = Module.new do - refine c do - def foo - :rfoo - end - end - end - using foo - @x.assert_equal(:rfoo, c.new.foo) - c.freeze - foo.module_eval do - refine c do - def foo - :rfoo2 - end - def bar - :rbar - end - end - end - @x.assert_equal(:rfoo2, c.new.foo) - @x.assert_equal(:rbar, c.new.bar, '[ruby-core:71391] [Bug #11669]') - end - ensure - $VERBOSE = verbose_bak - end - - # [Bug #17386] - def test_prepended_with_method_cache - foo = Class.new do - def foo - :Foo - end - end - - code = Module.new do - def foo - :Code - end - end - - _ext = Module.new do - refine foo do - def foo; end - end - end - - obj = foo.new - - assert_equal :Foo, obj.foo - foo.prepend code - assert_equal :Code, obj.foo - end - - # [Bug #17417] - def test_prepended_with_method_cache_17417 - assert_normal_exit %q{ - module M - def hoge; end - end - - module R - refine Hash do - def except *args; end - end - end - - h = {} - h.method(:except) # put it on pCMC - Hash.prepend(M) - h.method(:except) - } end private diff --git a/test/ruby/test_regexp.rb b/test/ruby/test_regexp.rb index 194b8c355d..fe271dc3d7 100644 --- a/test/ruby/test_regexp.rb +++ b/test/ruby/test_regexp.rb @@ -5,6 +5,7 @@ require 'test/unit' class TestRegexp < Test::Unit::TestCase def setup @verbose = $VERBOSE + $VERBOSE = nil end def teardown @@ -42,14 +43,13 @@ class TestRegexp < Test::Unit::TestCase def test_yoshidam_net_20041111_1 s = "[\xC2\xA0-\xC3\xBE]" - r = assert_deprecated_warning(/ignored/) {Regexp.new(s, nil, "u")} - assert_match(r, "\xC3\xBE") + assert_match(Regexp.new(s, nil, "u"), "\xC3\xBE") end def test_yoshidam_net_20041111_2 assert_raise(RegexpError) do s = "[\xFF-\xFF]".force_encoding("utf-8") - assert_warning(/ignored/) {Regexp.new(s, nil, "u")} + Regexp.new(s, nil, "u") end end @@ -57,17 +57,6 @@ class TestRegexp < Test::Unit::TestCase assert_equal('Ruby', 'Ruby'.sub(/[^a-z]/i, '-')) end - def test_premature_end_char_property - ["\\p{", - "\\p{".dup.force_encoding("UTF-8"), - "\\p{".dup.force_encoding("US-ASCII") - ].each do |string| - assert_raise(RegexpError) do - Regexp.new(string) - end - end - end - def test_assert_normal_exit # moved from knownbug. It caused core. Regexp.union("a", "a") @@ -101,11 +90,6 @@ class TestRegexp < Test::Unit::TestCase rescue ArgumentError :ok end - re = Regexp.union(/\//, "") - re2 = eval(re.inspect) - assert_equal(re.to_s, re2.to_s) - assert_equal(re.source, re2.source) - assert_equal(re, re2) end def test_word_boundary @@ -231,12 +215,6 @@ class TestRegexp < Test::Unit::TestCase assert_not_include(local_variables, :nil, "[ruby-dev:32675]") end - def test_assign_named_capture_to_const - %W[C \u{1d402}].each do |name| - assert_equal(:ok, Class.new.class_eval("#{name} = :ok; /(?<#{name}>.*)/ =~ 'ng'; #{name}")) - end - end - def test_assign_named_capture_trace bug = '[ruby-core:79940] [Bug #13287]' assert_normal_exit("#{<<-"begin;"}\n#{<<-"end;"}", bug) @@ -469,7 +447,7 @@ class TestRegexp < Test::Unit::TestCase def test_initialize assert_raise(ArgumentError) { Regexp.new } - assert_equal(/foo/, assert_warning(/ignored/) {Regexp.new(/foo/, Regexp::IGNORECASE)}) + assert_equal(/foo/, Regexp.new(/foo/, Regexp::IGNORECASE)) assert_equal(Encoding.find("US-ASCII"), Regexp.new("b..", nil, "n").encoding) assert_equal("bar", "foobarbaz"[Regexp.new("b..", nil, "n")]) @@ -541,8 +519,6 @@ class TestRegexp < Test::Unit::TestCase s = ".........." 5.times { s.sub!(".", "") } assert_equal(".....", s) - - assert_equal("\\\u{3042}", Regexp.new("\\\u{3042}").source) end def test_equal @@ -561,10 +537,7 @@ class TestRegexp < Test::Unit::TestCase assert_equal("bc", /../.match('abc', -2)[0]) assert_nil(/../.match("abc", -4)) assert_nil(/../.match("abc", 4)) - - # use eval because only one warning is shown for the same regexp literal - pat = eval('/../n') - assert_equal('\x', assert_warning(/binary regexp/) {pat.match("\u3042" + '\x', 1)}[0]) + assert_equal('\x', /../n.match("\u3042" + '\x', 1)[0]) r = nil /.../.match("abc") {|m| r = m[0] } @@ -640,7 +613,7 @@ class TestRegexp < Test::Unit::TestCase def test_dup assert_equal(//, //.dup) - assert_raise(TypeError) { //.dup.instance_eval { initialize_copy(nil) } } + assert_raise(TypeError) { //.instance_eval { initialize_copy(nil) } } end def test_regsub @@ -664,10 +637,21 @@ class TestRegexp < Test::Unit::TestCase assert_equal('foobazquux/foobazquux', result, bug8856) end - def test_ignorecase - v = assert_deprecated_warning(/variable \$= is no longer effective/) { $= } - assert_equal(false, v) - assert_deprecated_warning(/variable \$= is no longer effective; ignored/) { $= = nil } + def test_KCODE + assert_nil($KCODE) + assert_nothing_raised { $KCODE = nil } + assert_equal(false, $=) + assert_nothing_raised { $= = nil } + end + + def test_KCODE_warning + assert_warning(/variable \$KCODE is no longer effective; ignored/) { $KCODE = nil } + assert_warning(/variable \$KCODE is no longer effective/) { $KCODE = nil } + end + + def test_ignorecase_warning + assert_warning(/variable \$= is no longer effective; ignored/) { $= = nil } + assert_warning(/variable \$= is no longer effective/) { $= } end def test_match_setter @@ -729,13 +713,11 @@ class TestRegexp < Test::Unit::TestCase end def test_rindex_regexp - # use eval because only one warning is shown for the same regexp literal - pat = eval('/b../n') - assert_equal(3, assert_warning(/binary regexp/) {"foobarbaz\u3042".rindex(pat, 5)}) + assert_equal(3, "foobarbaz\u3042".rindex(/b../n, 5)) end def assert_regexp(re, ss, fs = [], msg = nil) - re = EnvUtil.suppress_warning {Regexp.new(re)} unless re.is_a?(Regexp) + re = Regexp.new(re) unless re.is_a?(Regexp) ss = [ss] unless ss.is_a?(Array) ss.each do |e, s| s ||= e @@ -768,7 +750,7 @@ class TestRegexp < Test::Unit::TestCase check(/\A\80\z/, "80", ["\100", ""]) check(/\A\77\z/, "?") check(/\A\78\z/, "\7" + '8', ["\100", ""]) - check(assert_warning(/Unknown escape/) {eval('/\A\Qfoo\E\z/')}, "QfooE") + check(eval('/\A\Qfoo\E\z/'), "QfooE") check(/\Aa++\z/, "aaa") check('\Ax]\z', "x]") check(/x#foo/x, "x", "#foo") @@ -812,8 +794,8 @@ class TestRegexp < Test::Unit::TestCase check(/^(A+|B(?>\g<1>)*)[AC]$/, %w(AAAC BBBAAAAC), %w(BBBAAA)) check(/^()(?>\g<1>)*$/, "", "a") check(/^(?>(?=a)(#{ "a" * 1000 }|))++$/, ["a" * 1000, "a" * 2000, "a" * 3000], ["", "a" * 500, "b" * 1000]) - check(assert_warning(/nested repeat operator/) {eval('/^(?:a?)?$/')}, ["", "a"], ["aa"]) - check(assert_warning(/nested repeat operator/) {eval('/^(?:a+)?$/')}, ["", "a", "aa"], ["ab"]) + check(eval('/^(?:a?)?$/'), ["", "a"], ["aa"]) + check(eval('/^(?:a+)?$/'), ["", "a", "aa"], ["ab"]) check(/^(?:a?)+?$/, ["", "a", "aa"], ["ab"]) check(/^a??[ab]/, [["a", "a"], ["a", "aa"], ["b", "b"], ["a", "ab"]], ["c"]) check(/^(?:a*){3,5}$/, ["", "a", "aa", "aaa", "aaaa", "aaaaa", "aaaaaa"], ["b"]) @@ -942,13 +924,13 @@ class TestRegexp < Test::Unit::TestCase def test_posix_bracket check(/\A[[:alpha:]0]\z/, %w(0 a), %w(1 .)) - check(assert_warning(/duplicated range/) {eval('/\A[[:^alpha:]0]\z/')}, %w(0 1 .), "a") - check(assert_warning(/duplicated range/) {eval('/\A[[:alpha\:]]\z/')}, %w(a l p h a :), %w(b 0 1 .)) - check(assert_warning(/duplicated range/) {eval('/\A[[:alpha:foo]0]\z/')}, %w(0 a), %w(1 .)) + check(eval('/\A[[:^alpha:]0]\z/'), %w(0 1 .), "a") + check(eval('/\A[[:alpha\:]]\z/'), %w(a l p h a :), %w(b 0 1 .)) + check(eval('/\A[[:alpha:foo]0]\z/'), %w(0 a), %w(1 .)) check(/\A[[:xdigit:]&&[:alpha:]]\z/, "a", %w(g 0)) check('\A[[:abcdefghijklmnopqrstu:]]+\z', "[]") failcheck('[[:alpha') - assert_warning(/duplicated range/) {failcheck('[[:alpha:')} + failcheck('[[:alpha:') failcheck('[[:alp:]]') assert_match(/\A[[:digit:]]+\z/, "\uff10\uff11\uff12\uff13\uff14\uff15\uff16\uff17\uff18\uff19") @@ -959,29 +941,24 @@ class TestRegexp < Test::Unit::TestCase end def test_cclass_R - assert_match(/\A\R\z/, "\r") - assert_match(/\A\R\z/, "\n") - assert_match(/\A\R\z/, "\f") - assert_match(/\A\R\z/, "\v") - assert_match(/\A\R\z/, "\r\n") - assert_match(/\A\R\z/, "\u0085") - assert_match(/\A\R\z/, "\u2028") - assert_match(/\A\R\z/, "\u2029") + assert_match /\A\R\z/, "\r" + assert_match /\A\R\z/, "\n" + assert_match /\A\R\z/, "\r\n" end def test_cclass_X - assert_match(/\A\X\z/, "\u{20 200d}") - assert_match(/\A\X\z/, "\u{600 600}") - assert_match(/\A\X\z/, "\u{600 20}") - assert_match(/\A\X\z/, "\u{261d 1F3FB}") - assert_match(/\A\X\z/, "\u{1f600}") - assert_match(/\A\X\z/, "\u{20 324}") - assert_match(/\A\X\X\z/, "\u{a 324}") - assert_match(/\A\X\X\z/, "\u{d 324}") - assert_match(/\A\X\z/, "\u{1F477 1F3FF 200D 2640 FE0F}") - assert_match(/\A\X\z/, "\u{1F468 200D 1F393}") - assert_match(/\A\X\z/, "\u{1F46F 200D 2642 FE0F}") - assert_match(/\A\X\z/, "\u{1f469 200d 2764 fe0f 200d 1f469}") + assert_match /\A\X\z/, "\u{20 200d}" + assert_match /\A\X\z/, "\u{600 600}" + assert_match /\A\X\z/, "\u{600 20}" + assert_match /\A\X\z/, "\u{261d 1F3FB}" + assert_match /\A\X\z/, "\u{1f600}" + assert_match /\A\X\z/, "\u{20 308}" + assert_match /\A\X\X\z/, "\u{a 308}" + assert_match /\A\X\X\z/, "\u{d 308}" + assert_match /\A\X\z/, "\u{1F477 1F3FF 200D 2640 FE0F}" + assert_match /\A\X\z/, "\u{1F468 200D 1F393}" + assert_match /\A\X\z/, "\u{1F46F 200D 2642 FE0F}" + assert_match /\A\X\z/, "\u{1f469 200d 2764 fe0f 200d 1f469}" assert_warning('') {/\X/ =~ "\u{a0}"} end @@ -1011,8 +988,6 @@ class TestRegexp < Test::Unit::TestCase assert_raise(TypeError) { Regexp.allocate.names } assert_raise(TypeError) { Regexp.allocate.named_captures } - assert_not_respond_to(MatchData, :allocate) -=begin assert_raise(TypeError) { MatchData.allocate.hash } assert_raise(TypeError) { MatchData.allocate.regexp } assert_raise(TypeError) { MatchData.allocate.names } @@ -1035,7 +1010,6 @@ class TestRegexp < Test::Unit::TestCase assert_raise(TypeError) { $` } assert_raise(TypeError) { $' } assert_raise(TypeError) { $+ } -=end end def test_unicode @@ -1092,9 +1066,6 @@ class TestRegexp < Test::Unit::TestCase assert_no_match(/^\p{age=3.0}$/u, "\u2754") assert_no_match(/^\p{age=2.0}$/u, "\u2754") assert_no_match(/^\p{age=1.1}$/u, "\u2754") - - assert_no_match(/^\p{age=12.0}$/u, "\u32FF") - assert_match(/^\p{age=12.1}$/u, "\u32FF") end MatchData_A = eval("class MatchData_\u{3042} < MatchData; self; end") @@ -1105,9 +1076,7 @@ class TestRegexp < Test::Unit::TestCase assert_equal(a, b, '[ruby-core:24748]') h = {a => 42} assert_equal(42, h[b], '[ruby-core:24748]') -=begin assert_match(/#<TestRegexp::MatchData_\u{3042}:/, MatchData_A.allocate.inspect) -=end h = /^(?<@time>\d+): (?<body>.*)/.match("123456: hoge fuga") assert_equal("123456", h["@time"]) @@ -1115,17 +1084,13 @@ class TestRegexp < Test::Unit::TestCase end def test_regexp_popped - EnvUtil.suppress_warning do - assert_nothing_raised { eval("a = 1; /\#{ a }/; a") } - assert_nothing_raised { eval("a = 1; /\#{ a }/o; a") } - end + assert_nothing_raised { eval("a = 1; /\#{ a }/; a") } + assert_nothing_raised { eval("a = 1; /\#{ a }/o; a") } end def test_invalid_fragment bug2547 = '[ruby-core:27374]' - assert_raise(SyntaxError, bug2547) do - assert_warning(/ignored/) {eval('/#{"\\\\"}y/')} - end + assert_raise(SyntaxError, bug2547) {eval('/#{"\\\\"}y/')} end def test_dup_warn @@ -1147,8 +1112,6 @@ class TestRegexp < Test::Unit::TestCase bug8151 = '[ruby-core:53649]' assert_warning(/\A\z/, bug8151) { Regexp.new('(?:[\u{33}])').to_s } - - assert_warning(%r[/.*/\Z]) { Regexp.new("[\n\n]") } end def test_property_warn @@ -1165,8 +1128,7 @@ class TestRegexp < Test::Unit::TestCase def test_raw_hyphen_and_tk_char_type_after_range bug6853 = '[ruby-core:47115]' # use Regexp.new instead of literal to ignore a parser warning. - re = assert_warning(/without escape/) {Regexp.new('[0-1-\\s]')} - check(re, [' ', '-'], ['2', 'a'], bug6853) + check(Regexp.new('[0-1-\\s]'), [' ', '-'], ['2', 'a'], bug6853) end def test_error_message_on_failed_conversion @@ -1202,20 +1164,6 @@ class TestRegexp < Test::Unit::TestCase } end - def test_quantifier_reduction - assert_equal('aa', eval('/(a+?)*/').match('aa')[0]) - assert_equal('aa', eval('/(?:a+?)*/').match('aa')[0]) - - quantifiers = %w'? * + ?? *? +?' - quantifiers.product(quantifiers) do |q1, q2| - EnvUtil.suppress_warning do - r1 = eval("/(a#{q1})#{q2}/").match('aa')[0] - r2 = eval("/(?:a#{q1})#{q2}/").match('aa')[0] - assert_equal(r1, r2) - end - end - end - def test_once pr1 = proc{|i| /#{i}/o} assert_equal(/0/, pr1.call(0)) diff --git a/test/ruby/test_require.rb b/test/ruby/test_require.rb index 30c07b9e5c..28cf686a26 100644 --- a/test/ruby/test_require.rb +++ b/test/ruby/test_require.rb @@ -62,6 +62,12 @@ class TestRequire < Test::Unit::TestCase assert_require_nonascii_path(encoding, bug8165) end + def test_require_insecure_path + assert_require_insecure_path("foo") + encoding = 'filesystem' + assert_require_insecure_path(nil, encoding) + end + def test_require_nonascii_path_utf8 bug8676 = '[ruby-core:56136] [Bug #8676]' encoding = Encoding::UTF_8 @@ -69,6 +75,12 @@ class TestRequire < Test::Unit::TestCase assert_require_nonascii_path(encoding, bug8676) end + def test_require_insecure_path_utf8 + encoding = Encoding::UTF_8 + return if Encoding.find('filesystem') == encoding + assert_require_insecure_path(nil, encoding) + end + def test_require_nonascii_path_shift_jis bug8676 = '[ruby-core:56136] [Bug #8676]' encoding = Encoding::Shift_JIS @@ -76,6 +88,12 @@ class TestRequire < Test::Unit::TestCase assert_require_nonascii_path(encoding, bug8676) end + def test_require_insecure_path_shift_jis + encoding = Encoding::Shift_JIS + return if Encoding.find('filesystem') == encoding + assert_require_insecure_path(nil, encoding) + end + case RUBY_PLATFORM when /cygwin/, /mswin/, /mingw/, /darwin/ def self.ospath_encoding(path) @@ -87,8 +105,17 @@ class TestRequire < Test::Unit::TestCase end end + SECURITY_WARNING = + if /mswin|mingw/ =~ RUBY_PLATFORM + nil + else + proc do |require_path| + $SAFE = 1 + require(require_path) + end + end + def prepare_require_path(dir, encoding) - require 'enc/trans/single_byte' Dir.mktmpdir {|tmp| begin require_path = File.join(tmp, dir, 'foo.rb').encode(encoding) @@ -124,6 +151,31 @@ class TestRequire < Test::Unit::TestCase } end + def assert_require_insecure_path(dirname, encoding = nil) + return unless SECURITY_WARNING + dirname ||= "\u3042" * 5 + encoding ||= dirname.encoding + prepare_require_path(dirname, encoding) {|require_path| + require_path.untaint + require(require_path) + $".pop + File.chmod(0777, File.dirname(require_path)) + ospath = (require_path.encode('filesystem') rescue + require_path.encode(self.class.ospath_encoding(require_path))) + e = nil + stderr = EnvUtil.verbose_warning do + e = assert_raise(SecurityError) do + SECURITY_WARNING.call(require_path) + end + end + assert_include(e.message, "loading from unsafe path") + assert_include(stderr, "Insecure world writable dir") + require_path = require_path.encode(self.class.ospath_encoding(require_path)) + assert_include(e.message, require_path) + assert_include(stderr, File.dirname(require_path)) + } + end + def test_require_path_home_1 env_rubypath, env_home = ENV["RUBYPATH"], ENV["HOME"] pathname_too_long = /pathname too long \(ignored\).*\(LoadError\)/m @@ -200,30 +252,21 @@ class TestRequire < Test::Unit::TestCase end def assert_syntax_error_backtrace - loaded_features = $LOADED_FEATURES.dup Dir.mktmpdir do |tmp| req = File.join(tmp, "test.rb") - File.write(req, ",\n") - e = assert_raise_with_message(SyntaxError, /unexpected/) { + File.write(req, "'\n") + e = assert_raise_with_message(SyntaxError, /unterminated/) { yield req } - assert_not_nil(bt = e.backtrace, "no backtrace") - assert_not_empty(bt.find_all {|b| b.start_with? __FILE__}, proc {bt.inspect}) + assert_not_nil(bt = e.backtrace) + assert_not_empty(bt.find_all {|b| b.start_with? __FILE__}) end - $LOADED_FEATURES.replace loaded_features end def test_require_syntax_error assert_syntax_error_backtrace {|req| require req} end - def test_require_syntax_error_rescued - assert_syntax_error_backtrace do |req| - assert_raise_with_message(SyntaxError, /unexpected/) {require req} - require req - end - end - def test_load_syntax_error assert_syntax_error_backtrace {|req| load req} end @@ -339,19 +382,6 @@ class TestRequire < Test::Unit::TestCase } end - def test_require_in_wrapped_load - Dir.mktmpdir do |tmp| - File.write("#{tmp}/1.rb", "require_relative '2'\n") - File.write("#{tmp}/2.rb", "class Foo\n""end\n") - assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") - path = ""#{tmp.dump}"/1.rb" - begin; - load path, true - assert_instance_of(Class, Foo) - end; - end - end - def test_load_scope bug1982 = '[ruby-core:25039] [Bug #1982]' Tempfile.create(["test_ruby_test_require", ".rb"]) {|t| @@ -389,10 +419,40 @@ class TestRequire < Test::Unit::TestCase end end + def test_tainted_loadpath + Tempfile.create(["test_ruby_test_require", ".rb"]) {|t| + abs_dir, file = File.split(t.path) + abs_dir = File.expand_path(abs_dir).untaint + + assert_separately([], <<-INPUT) + abs_dir = "#{ abs_dir }" + $: << abs_dir + assert_nothing_raised {require "#{ file }"} + INPUT + + assert_separately([], <<-INPUT) + abs_dir = "#{ abs_dir }" + $: << abs_dir.taint + assert_nothing_raised {require "#{ file }"} + INPUT + + assert_separately([], <<-INPUT) + abs_dir = "#{ abs_dir }" + $: << abs_dir.taint + $SAFE = 1 + assert_raise(SecurityError) {require "#{ file }"} + INPUT + + assert_separately([], <<-INPUT) + abs_dir = "#{ abs_dir }" + $: << abs_dir << 'elsewhere'.taint + assert_nothing_raised {require "#{ file }"} + INPUT + } + end + def test_relative load_path = $:.dup - loaded_featrures = $LOADED_FEATURES.dup - $:.delete(".") Dir.mktmpdir do |tmp| Dir.chdir(tmp) do @@ -412,7 +472,6 @@ class TestRequire < Test::Unit::TestCase end ensure $:.replace(load_path) if load_path - $LOADED_FEATURES.replace loaded_featrures end def test_relative_symlink @@ -478,7 +537,7 @@ class TestRequire < Test::Unit::TestCase t1 = Thread.new do Thread.pass until start begin - Kernel.send(:require, path) + require(path) rescue RuntimeError end @@ -487,7 +546,7 @@ class TestRequire < Test::Unit::TestCase t2 = Thread.new do Thread.pass until scratch[0] - t2_res = Kernel.send(:require, path) + t2_res = require(path) end t1[:scratch] = t2[:scratch] = scratch @@ -770,8 +829,6 @@ class TestRequire < Test::Unit::TestCase end if File.respond_to?(:mkfifo) def test_loading_fifo_fd_leak - skip if RUBY_PLATFORM =~ /android/ # https://rubyci.org/logs/rubyci.s3.amazonaws.com/android29-x86_64/ruby-master/log/20200419T124100Z.fail.html.gz - Tempfile.create(%w'fifo .rb') {|f| f.close File.unlink(f.path) @@ -833,29 +890,9 @@ class TestRequire < Test::Unit::TestCase rescue NotImplementedError, Errno::EACCES skip "File.symlink is not implemented" end - File.write(File.join(tmp, "real/test_symlink_load_path.rb"), "print __FILE__") - result = IO.popen([EnvUtil.rubybin, "-I#{tmp}/symlink", "-e", "require 'test_symlink_load_path.rb'"], &:read) - assert_operator(result, :end_with?, "/real/test_symlink_load_path.rb") + File.write(File.join(tmp, "real/a.rb"), "print __FILE__") + result = IO.popen([EnvUtil.rubybin, "-I#{tmp}/symlink", "-e", "require 'a.rb'"], &:read) + assert_operator(result, :end_with?, "/real/a.rb") } end - - if defined?($LOAD_PATH.resolve_feature_path) - def test_resolve_feature_path - paths, loaded = $:.dup, $".dup - Dir.mktmpdir do |tmp| - Tempfile.create(%w[feature .rb], tmp) do |file| - file.close - path = File.realpath(file.path) - dir, base = File.split(path) - $:.unshift(dir) - assert_equal([:rb, path], $LOAD_PATH.resolve_feature_path(base)) - $".push(path) - assert_equal([:rb, path], $LOAD_PATH.resolve_feature_path(base)) - end - end - ensure - $:.replace(paths) - $".replace(loaded) - end - end end diff --git a/test/ruby/test_require_lib.rb b/test/ruby/test_require_lib.rb deleted file mode 100644 index 4af57173b8..0000000000 --- a/test/ruby/test_require_lib.rb +++ /dev/null @@ -1,28 +0,0 @@ -# frozen_string_literal: false -require 'test/unit' - -class TestRequireLib < Test::Unit::TestCase - TEST_RATIO = ENV["TEST_REQUIRE_THREAD_RATIO"]&.tap {|s|break s.to_f} || 0.05 # testing all files needs too long time... - - Dir.glob(File.expand_path('../../lib/**/*.rb', __dir__)).each do |lib| - # skip some problems - next if %r!/lib/(?:bundler|rubygems)\b! =~ lib - next if %r!/lib/(?:debug|mkmf)\.rb\z! =~ lib - # skip because "in `<module:Maker>': undefined method `add_maker' for RSS::Maker:Module (NoMethodError)" - next if %r!/lib/rss\b! =~ lib - # skip many files that almost use no threads - next if TEST_RATIO < rand(0.0..1.0) - define_method "test_thread_size:#{lib}" do - assert_separately(['--disable-gems', '-W0'], "#{<<~"begin;"}\n#{<<~"end;"}") - begin; - n = Thread.list.size - begin - require #{lib.dump} - rescue Exception - skip $! - end - assert_equal n, Thread.list.size - end; - end - end -end diff --git a/test/ruby/test_rubyoptions.rb b/test/ruby/test_rubyoptions.rb index 214b89c9b8..54213c4698 100644 --- a/test/ruby/test_rubyoptions.rb +++ b/test/ruby/test_rubyoptions.rb @@ -1,19 +1,10 @@ # -*- coding: us-ascii -*- require 'test/unit' -require 'timeout' require 'tmpdir' require 'tempfile' -require_relative '../lib/jit_support' class TestRubyOptions < Test::Unit::TestCase - NO_JIT_DESCRIPTION = - if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # checking -DMJIT_FORCE_ENABLE - RUBY_DESCRIPTION.sub(/\+JIT /, '') - else - RUBY_DESCRIPTION - end - def write_file(filename, content) File.open(filename, "w") {|f| f << content @@ -35,7 +26,7 @@ class TestRubyOptions < Test::Unit::TestCase def test_usage assert_in_out_err(%w(-h)) do |r, e| - assert_operator(r.size, :<=, 25) + assert_operator(r.size, :<=, 24) longer = r[1..-1].select {|x| x.size > 80} assert_equal([], longer) assert_equal([], e) @@ -72,23 +63,21 @@ class TestRubyOptions < Test::Unit::TestCase ENV['RUBYOPT'] = nil assert_in_out_err(%w(-W0 -e) + ['p $-W'], "", %w(0), []) assert_in_out_err(%w(-W1 -e) + ['p $-W'], "", %w(1), []) - assert_in_out_err(%w(-Wx -e) + ['p $-W'], "", %w(2), []) + assert_in_out_err(%w(-Wx -e) + ['p $-W'], "", %w(1), []) assert_in_out_err(%w(-W -e) + ['p $-W'], "", %w(2), []) - assert_in_out_err(%w(-We) + ['p $-W'], "", %w(2), []) assert_in_out_err(%w(-w -W0 -e) + ['p $-W'], "", %w(0), []) - assert_in_out_err(%w(-W:deprecated -e) + ['p Warning[:deprecated]'], "", %w(true), []) - assert_in_out_err(%w(-W:no-deprecated -e) + ['p Warning[:deprecated]'], "", %w(false), []) - assert_in_out_err(%w(-W:experimental -e) + ['p Warning[:experimental]'], "", %w(true), []) - assert_in_out_err(%w(-W:no-experimental -e) + ['p Warning[:experimental]'], "", %w(false), []) - assert_in_out_err(%w(-W:qux), "", [], /unknown warning category: `qux'/) - assert_in_out_err(%w(-w -e) + ['p Warning[:deprecated]'], "", %w(true), []) - assert_in_out_err(%w(-W -e) + ['p Warning[:deprecated]'], "", %w(true), []) - assert_in_out_err(%w(-We) + ['p Warning[:deprecated]'], "", %w(true), []) - assert_in_out_err(%w(-e) + ['p Warning[:deprecated]'], "", %w(false), []) ensure ENV['RUBYOPT'] = save_rubyopt end + def test_safe_level + assert_in_out_err(%w(-T -e) + [""], "", [], + /no -e allowed in tainted mode \(SecurityError\)/) + + assert_in_out_err(%w(-T4 -S foo.rb), "", [], + /no -S allowed in tainted mode \(SecurityError\)/) + end + def test_debug assert_in_out_err(["--disable-gems", "-de", "p $DEBUG"], "", %w(true), []) @@ -107,23 +96,10 @@ class TestRubyOptions < Test::Unit::TestCase end private_constant :VERSION_PATTERN - VERSION_PATTERN_WITH_JIT = - case RUBY_ENGINE - when 'ruby' - /^ruby #{q[RUBY_VERSION]}(?:[p ]|dev|rc).*? \+JIT \[#{q[RUBY_PLATFORM]}\]$/ - else - VERSION_PATTERN - end - private_constant :VERSION_PATTERN_WITH_JIT - def test_verbose assert_in_out_err(["-vve", ""]) do |r, e| assert_match(VERSION_PATTERN, r[0]) - if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? && !mjit_force_enabled? # checking -DMJIT_FORCE_ENABLE - assert_equal(NO_JIT_DESCRIPTION, r[0]) - else - assert_equal(RUBY_DESCRIPTION, r[0]) - end + assert_equal(RUBY_DESCRIPTION, r[0]) assert_equal([], e) end @@ -140,11 +116,9 @@ class TestRubyOptions < Test::Unit::TestCase end def test_enable - if JITSupport.supported? - assert_in_out_err(%w(--enable all -e) + [""], "", [], []) - assert_in_out_err(%w(--enable-all -e) + [""], "", [], []) - assert_in_out_err(%w(--enable=all -e) + [""], "", [], []) - end + assert_in_out_err(%w(--enable all -e) + [""], "", [], []) + assert_in_out_err(%w(--enable-all -e) + [""], "", [], []) + assert_in_out_err(%w(--enable=all -e) + [""], "", [], []) assert_in_out_err(%w(--enable foobarbazqux -e) + [""], "", [], /unknown argument for --enable: `foobarbazqux'/) assert_in_out_err(%w(--enable), "", [], /missing argument for --enable/) @@ -159,7 +133,6 @@ class TestRubyOptions < Test::Unit::TestCase assert_in_out_err(%w(--disable), "", [], /missing argument for --disable/) assert_in_out_err(%w(--disable-gems -e) + ['p defined? Gem'], "", ["nil"], []) assert_in_out_err(%w(--disable-did_you_mean -e) + ['p defined? DidYouMean'], "", ["nil"], []) - assert_in_out_err(%w(--disable-gems -e) + ['p defined? DidYouMean'], "", ["nil"], []) end def test_kanji @@ -182,45 +155,9 @@ class TestRubyOptions < Test::Unit::TestCase def test_version assert_in_out_err(%w(--version)) do |r, e| assert_match(VERSION_PATTERN, r[0]) - if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # checking -DMJIT_FORCE_ENABLE - assert_equal(EnvUtil.invoke_ruby(['-e', 'print RUBY_DESCRIPTION'], '', true).first, r[0]) - else - assert_equal(RUBY_DESCRIPTION, r[0]) - end + assert_equal(RUBY_DESCRIPTION, r[0]) assert_equal([], e) end - - return if RbConfig::CONFIG["MJIT_SUPPORT"] == 'no' - - [ - %w(--version --jit --disable=jit), - %w(--version --enable=jit --disable=jit), - %w(--version --enable-jit --disable-jit), - ].each do |args| - assert_in_out_err(args) do |r, e| - assert_match(VERSION_PATTERN, r[0]) - assert_match(NO_JIT_DESCRIPTION, r[0]) - assert_equal([], e) - end - end - - if JITSupport.supported? - [ - %w(--version --jit), - %w(--version --enable=jit), - %w(--version --enable-jit), - ].each do |args| - assert_in_out_err(args) do |r, e| - assert_match(VERSION_PATTERN_WITH_JIT, r[0]) - if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # checking -DMJIT_FORCE_ENABLE - assert_equal(RUBY_DESCRIPTION, r[0]) - else - assert_equal(EnvUtil.invoke_ruby(['--jit', '-e', 'print RUBY_DESCRIPTION'], '', true).first, r[0]) - end - assert_equal([], e) - end - end - end end def test_eval @@ -255,7 +192,7 @@ class TestRubyOptions < Test::Unit::TestCase end def test_autosplit - assert_in_out_err(%w(-W0 -an -F: -e) + ["p $F"], "foo:bar:baz\nqux:quux:quuux\n", + assert_in_out_err(%w(-an -F: -e) + ["p $F"], "foo:bar:baz\nqux:quux:quuux\n", ['["foo", "bar", "baz\n"]', '["qux", "quux", "quuux\n"]'], []) end @@ -289,8 +226,8 @@ class TestRubyOptions < Test::Unit::TestCase assert_in_out_err(%w(--encoding test_ruby_test_rubyoptions_foobarbazqux), "", [], /unknown encoding name - test_ruby_test_rubyoptions_foobarbazqux \(RuntimeError\)/) - if /mswin|mingw|aix|android/ =~ RUBY_PLATFORM && - (str = "\u3042".force_encoding(Encoding.find("external"))).valid_encoding? + if /mswin|mingw|aix/ =~ RUBY_PLATFORM && + (str = "\u3042".force_encoding(Encoding.find("locale"))).valid_encoding? # This result depends on locale because LANG=C doesn't affect locale # on Windows. # On AIX, the source encoding of stdin with LANG=C is ISO-8859-1, @@ -312,7 +249,7 @@ class TestRubyOptions < Test::Unit::TestCase assert_in_out_err(%W(-\r -e) + [""], "", [], []) - assert_in_out_err(%W(-\rx), "", [], /invalid option -\\r \(-h will show valid options\) \(RuntimeError\)/) + assert_in_out_err(%W(-\rx), "", [], /invalid option -\\x0D \(-h will show valid options\) \(RuntimeError\)/) assert_in_out_err(%W(-\x01), "", [], /invalid option -\\x01 \(-h will show valid options\) \(RuntimeError\)/) @@ -328,6 +265,12 @@ class TestRubyOptions < Test::Unit::TestCase ENV['RUBYOPT'] = '-e "p 1"' assert_in_out_err([], "", [], /invalid switch in RUBYOPT: -e \(RuntimeError\)/) + ENV['RUBYOPT'] = '-T1' + assert_in_out_err(["--disable-gems"], "", [], /no program input from stdin allowed in tainted mode \(SecurityError\)/) + + ENV['RUBYOPT'] = '-T4' + assert_in_out_err(["--disable-gems"], "", [], /no program input from stdin allowed in tainted mode \(SecurityError\)/) + ENV['RUBYOPT'] = '-Eus-ascii -KN' assert_in_out_err(%w(-Eutf-8 -KU), "p '\u3042'") do |r, e| assert_equal("\"\u3042\"", r.join.force_encoding(Encoding::UTF_8)) @@ -338,20 +281,6 @@ class TestRubyOptions < Test::Unit::TestCase assert_in_out_err(%w(), "p $VERBOSE", ["true"]) assert_in_out_err(%w(-W1), "p $VERBOSE", ["false"]) assert_in_out_err(%w(-W0), "p $VERBOSE", ["nil"]) - assert_in_out_err(%w(), "p Warning[:deprecated]", ["true"]) - assert_in_out_err(%w(-W0), "p Warning[:deprecated]", ["false"]) - assert_in_out_err(%w(-W1), "p Warning[:deprecated]", ["false"]) - assert_in_out_err(%w(-W2), "p Warning[:deprecated]", ["true"]) - ENV['RUBYOPT'] = '-W:deprecated' - assert_in_out_err(%w(), "p Warning[:deprecated]", ["true"]) - ENV['RUBYOPT'] = '-W:no-deprecated' - assert_in_out_err(%w(), "p Warning[:deprecated]", ["false"]) - ENV['RUBYOPT'] = '-W:experimental' - assert_in_out_err(%w(), "p Warning[:experimental]", ["true"]) - ENV['RUBYOPT'] = '-W:no-experimental' - assert_in_out_err(%w(), "p Warning[:experimental]", ["false"]) - ENV['RUBYOPT'] = '-W:qux' - assert_in_out_err(%w(), "", [], /unknown warning category: `qux'/) ensure if rubyopt_orig ENV['RUBYOPT'] = rubyopt_orig @@ -457,7 +386,7 @@ class TestRubyOptions < Test::Unit::TestCase t.puts " end" t.puts "end" t.flush - warning = ' warning: found `= literal\' in conditional, should be ==' + warning = ' warning: found = in conditional, should be ==' err = ["#{t.path}:1:#{warning}", "#{t.path}:4:#{warning}", ] @@ -494,27 +423,13 @@ class TestRubyOptions < Test::Unit::TestCase "begin", "if false", "for _ in []", "while false", "def foo", "class X", "module M", ["-> do", "end"], ["-> {", "}"], - ["if false;", "else ; end"], - ["if false;", "elsif false ; end"], - ["begin", "rescue ; end"], - ["begin rescue", "else ; end"], - ["begin", "ensure ; end"], - [" case nil", "when true; end"], - ["case nil; when true", "end"], - ["if false;", "end", "if true\nelse ", "end"], - ["else", " end", "_ = if true\n"], - ["begin\n def f() = nil", "end"], - ["begin\n def self.f() = nil", "end"], ].each do - |b, e = 'end', pre = nil, post = nil| - src = ["#{pre}#{b}\n", " #{e}\n#{post}"] - k = b[/\A\s*(\S+)/, 1] - e = e[/\A\s*(\S+)/, 1] - n = 1 + src[0].count("\n") - n1 = 1 + (pre ? pre.count("\n") : 0) - - a.for("no directives with #{src}") do - err = ["#{t.path}:#{n}: warning: mismatched indentations at '#{e}' with '#{k}' at #{n1}"] + |b, e = 'end'| + src = ["#{b}\n", " #{e}\n"] + k = b[/\A\S+/] + + a.for("no directives with #{b}") do + err = ["#{t.path}:2: warning: mismatched indentations at '#{e}' with '#{k}' at 1"] t.rewind t.truncate(0) t.puts src @@ -523,7 +438,7 @@ class TestRubyOptions < Test::Unit::TestCase assert_in_out_err(["-wr", t.path, "-e", ""], "", [], err) end - a.for("false directive with #{src}") do + a.for("false directive with #{b}") do t.rewind t.truncate(0) t.puts "# -*- warn-indent: false -*-" @@ -532,8 +447,8 @@ class TestRubyOptions < Test::Unit::TestCase assert_in_out_err(["-w", t.path], "", [], [], '[ruby-core:25442]') end - a.for("false and true directives with #{src}") do - err = ["#{t.path}:#{n+2}: warning: mismatched indentations at '#{e}' with '#{k}' at #{n1+2}"] + a.for("false and true directives with #{b}") do + err = ["#{t.path}:4: warning: mismatched indentations at '#{e}' with '#{k}' at 3"] t.rewind t.truncate(0) t.puts "# -*- warn-indent: false -*-" @@ -543,7 +458,7 @@ class TestRubyOptions < Test::Unit::TestCase assert_in_out_err(["-w", t.path], "", [], err, '[ruby-core:25442]') end - a.for("false directives after #{src}") do + a.for("false directives after #{b}") do t.rewind t.truncate(0) t.puts "# -*- warn-indent: true -*-" @@ -554,8 +469,8 @@ class TestRubyOptions < Test::Unit::TestCase assert_in_out_err(["-w", t.path], "", [], [], '[ruby-core:25442]') end - a.for("BOM with #{src}") do - err = ["#{t.path}:#{n}: warning: mismatched indentations at '#{e}' with '#{k}' at #{n1}"] + a.for("BOM with #{b}") do + err = ["#{t.path}:2: warning: mismatched indentations at '#{e}' with '#{k}' at 1"] t.rewind t.truncate(0) t.print "\u{feff}" @@ -627,7 +542,7 @@ class TestRubyOptions < Test::Unit::TestCase if /linux|freebsd|netbsd|openbsd|darwin/ =~ RUBY_PLATFORM PSCMD = EnvUtil.find_executable("ps", "-o", "command", "-p", $$.to_s) {|out| /ruby/=~out} - PSCMD&.pop + PSCMD.pop if PSCMD end def test_set_program_name @@ -638,18 +553,14 @@ class TestRubyOptions < Test::Unit::TestCase pid = spawn(EnvUtil.rubybin, "test-script") ps = nil - now = Process.clock_gettime(Process::CLOCK_MONOTONIC) - stop = now + 30 - begin + 10.times do sleep 0.1 ps = `#{PSCMD.join(' ')} #{pid}` break if /hello world/ =~ ps - now = Process.clock_gettime(Process::CLOCK_MONOTONIC) - end until Process.wait(pid, Process::WNOHANG) || now > stop + end assert_match(/hello world/, ps) - assert_operator now, :<, stop Process.kill :KILL, pid - EnvUtil.timeout(5) { Process.wait(pid) } + Process.wait(pid) end end @@ -668,25 +579,24 @@ class TestRubyOptions < Test::Unit::TestCase pid = spawn(EnvUtil.rubybin, "test-script") ps = nil - now = Process.clock_gettime(Process::CLOCK_MONOTONIC) - stop = now + 30 - begin + 10.times do sleep 0.1 ps = `#{PSCMD.join(' ')} #{pid}` break if /hello world/ =~ ps - now = Process.clock_gettime(Process::CLOCK_MONOTONIC) - end until Process.wait(pid, Process::WNOHANG) || now > stop + end assert_match(/hello world/, ps) - assert_operator now, :<, stop Process.kill :KILL, pid - Timeout.timeout(5) { Process.wait(pid) } + Process.wait(pid) end end module SEGVTest opts = {} - unless /mswin|mingw/ =~ RUBY_PLATFORM + if /mswin|mingw/ =~ RUBY_PLATFORM + additional = /[\s\w\.\']*/ + else opts[:rlimit_core] = 0 + additional = nil end ExecOptions = opts.freeze @@ -695,42 +605,45 @@ class TestRubyOptions < Test::Unit::TestCase -e:(?:1:)?\s\[BUG\]\sSegmentation\sfault.*\n )x, %r( - #{ Regexp.quote(NO_JIT_DESCRIPTION) }\n\n + #{ Regexp.quote(RUBY_DESCRIPTION) }\n\n )x, %r( (?:--\s(?:.+\n)*\n)? --\sControl\sframe\sinformation\s-+\n - (?:(?:c:.*\n)|(?:^\s+.+\n))* - \n + (?:c:.*\n)* )x, %r( (?: --\sRuby\slevel\sbacktrace\sinformation\s----------------------------------------\n - (?:-e:1:in\s\`(?:block\sin\s)?<main>\'\n)* + -e:1:in\s\`<main>\'\n -e:1:in\s\`kill\'\n - \n )? )x, %r( - (?:--\sMachine(?:.+\n)*\n)? - )x, - %r( (?: --\sC\slevel\sbacktrace\sinformation\s-------------------------------------------\n - (?:(?:.*\s)?\[0x\h+\].*\n|.*:\d+\n)*\n + (?:(?:.*\s)?\[0x\h+\]\n)*\n )? )x, + :*, %r( - (?:--\sOther\sruntime\sinformation\s-+\n - (?:.*\n)* + \[NOTE\]\n + You\smay\shave\sencountered\sa\sbug\sin\sthe\sRuby\sinterpreter\sor\sextension\slibraries.\n + Bug\sreports\sare\swelcome.\n + (?:.*\n)? + For\sdetails:\shttp:\/\/.*\.ruby-lang\.org/.*\n + \n + (?: + \[IMPORTANT\]\n + (?:.+\n)+ + \n )? )x, ] + ExpectedStderrList << additional if additional end def assert_segv(args, message=nil) - skip if ENV['RUBY_ON_BUG'] - test_stdin = "" opt = SEGVTest::ExecOptions.dup list = SEGVTest::ExpectedStderrList @@ -792,6 +705,20 @@ class TestRubyOptions < Test::Unit::TestCase assert_in_out_err(["-w", "-"], "eval('a=1')", [], [], feature7730) end + def test_shadowing_variable + bug4130 = '[ruby-dev:42718]' + assert_in_out_err(["-we", "def foo\n"" a=1\n"" 1.times do |a| end\n"" a\n""end"], + "", [], ["-e:3: warning: shadowing outer local variable - a"], bug4130) + assert_in_out_err(["-we", "def foo\n"" a=1\n"" 1.times do |a| end\n""end"], + "", [], + ["-e:3: warning: shadowing outer local variable - a", + "-e:2: warning: assigned but unused variable - a", + ], bug4130) + feature6693 = '[ruby-core:46160]' + assert_in_out_err(["-we", "def foo\n"" _a=1\n"" 1.times do |_a| end\n""end"], + "", [], [], feature6693) + end + def test_script_from_stdin begin require 'pty' @@ -809,7 +736,7 @@ class TestRubyOptions < Test::Unit::TestCase pid = spawn(EnvUtil.rubybin, :in => s, :out => w) w.close assert_nothing_raised('[ruby-dev:37798]') do - result = EnvUtil.timeout(3) {r.read} + result = Timeout.timeout(3) {r.read} end Process.wait pid } @@ -849,11 +776,11 @@ class TestRubyOptions < Test::Unit::TestCase def test_command_line_glob_nonascii bug10555 = '[ruby-dev:48752] [Bug #10555]' name = "\u{3042}.txt" - expected = name.encode("external") rescue "?.txt" + expected = name.encode("locale") rescue "?.txt" with_tmpchdir do |dir| open(name, "w") {} assert_in_out_err(["-e", "puts ARGV", "?.txt"], "", [expected], [], - bug10555, encoding: "external") + bug10555, encoding: "locale") end end @@ -888,7 +815,7 @@ class TestRubyOptions < Test::Unit::TestCase with_tmpchdir do |dir| Ougai.each {|f| open(f, "w") {}} assert_in_out_err(["-Eutf-8", "-e", "puts ARGV", "*"], "", Ougai, encoding: "utf-8") - ougai = Ougai.map {|f| f.encode("external", replace: "?")} + ougai = Ougai.map {|f| f.encode("locale", replace: "?")} assert_in_out_err(["-e", "puts ARGV", "*.txt"], "", ougai) end end @@ -986,10 +913,8 @@ class TestRubyOptions < Test::Unit::TestCase [["disable", "false"], ["enable", "true"]].each do |opt, exp| %W[frozen_string_literal frozen-string-literal].each do |arg| key = "#{opt}=#{arg}" - negopt = exp == "true" ? "disable" : "enable" - env = {"RUBYOPT"=>"--#{negopt}=#{arg}"} a.for(key) do - assert_in_out_err([env, "--disable=gems", "--#{key}"], 'p("foo".frozen?)', [exp]) + assert_in_out_err(["--disable=gems", "--#{key}"], 'p("foo".frozen?)', [exp]) end end end @@ -1006,7 +931,7 @@ class TestRubyOptions < Test::Unit::TestCase def test_frozen_string_literal_debug with_debug_pat = /created at/ - wo_debug_pat = /can\'t modify frozen String: "\w+" \(FrozenError\)\n\z/ + wo_debug_pat = /can\'t modify frozen String \(FrozenError\)\n\z/ frozen = [ ["--enable-frozen-string-literal", true], ["--disable-frozen-string-literal", false], @@ -1022,13 +947,9 @@ class TestRubyOptions < Test::Unit::TestCase frozen.product(debugs) do |(opt1, freeze), (opt2, debug)| opt = opts + [opt1, opt2].compact err = !freeze ? [] : debug ? with_debug_pat : wo_debug_pat - [ - ['"foo" << "bar"', err], - ['"foo#{123}bar" << "bar"', []], - ['+"foo#{123}bar" << "bar"', []], - ['-"foo#{123}bar" << "bar"', wo_debug_pat], - ].each do |code, expected| - assert_in_out_err(opt, code, [], expected, "#{opt} #{code}") + assert_in_out_err(opt, '"foo" << "bar"', [], err) + if freeze + assert_in_out_err(opt, '"foo#{123}bar" << "bar"', [], err) end end end @@ -1066,22 +987,10 @@ class TestRubyOptions < Test::Unit::TestCase end end - def test_null_script - skip "#{IO::NULL} is not a character device" unless File.chardev?(IO::NULL) - assert_in_out_err([IO::NULL], success: true) - end - - def test_jit_debug - # mswin uses prebuilt precompiled header. Thus it does not show a pch compilation log to check "-O0 -O1". - if JITSupport.supported? && !RUBY_PLATFORM.match?(/mswin/) - env = { 'MJIT_SEARCH_BUILD_DIR' => 'true' } - assert_in_out_err([env, "--jit-debug=-O0 -O1", "--jit-verbose=2", "" ], "", [], /-O0 -O1/) - end - end - - private - - def mjit_force_enabled? - "#{RbConfig::CONFIG['CFLAGS']} #{RbConfig::CONFIG['CPPFLAGS']}".match?(/(\A|\s)-D ?MJIT_FORCE_ENABLE\b/) + def test_argv_tainted + assert_separately(%w[- arg], "#{<<~"begin;"}\n#{<<~'end;'}") + begin; + assert_predicate(ARGV[0], :tainted?, '[ruby-dev:50596] [Bug #14941]') + end; end end diff --git a/test/ruby/test_rubyvm.rb b/test/ruby/test_rubyvm.rb index 67d46e27ad..7673d8dfbe 100644 --- a/test/ruby/test_rubyvm.rb +++ b/test/ruby/test_rubyvm.rb @@ -4,11 +4,11 @@ require 'test/unit' class TestRubyVM < Test::Unit::TestCase def test_stat assert_kind_of Hash, RubyVM.stat - assert_kind_of Integer, RubyVM.stat[:global_constant_state] + assert_kind_of Integer, RubyVM.stat[:global_method_state] RubyVM.stat(stat = {}) assert_not_empty stat - assert_equal stat[:global_constant_state], RubyVM.stat(:global_constant_state) + assert_equal stat[:global_method_state], RubyVM.stat(:global_method_state) end def test_stat_unknown diff --git a/test/ruby/test_rubyvm_mjit.rb b/test/ruby/test_rubyvm_mjit.rb deleted file mode 100644 index ef7475670c..0000000000 --- a/test/ruby/test_rubyvm_mjit.rb +++ /dev/null @@ -1,91 +0,0 @@ -# frozen_string_literal: true -require 'test/unit' -require_relative '../lib/jit_support' - -return if RbConfig::CONFIG["MJIT_SUPPORT"] == 'no' - -class TestRubyVMMJIT < Test::Unit::TestCase - include JITSupport - - def setup - unless JITSupport.supported? - skip 'JIT seems not supported on this platform' - end - end - - def test_pause - out, err = eval_with_jit(<<~'EOS', verbose: 1, min_calls: 1, wait: false) - i = 0 - while i < 5 - eval("def mjit#{i}; end; mjit#{i}") - i += 1 - end - print RubyVM::MJIT.pause - print RubyVM::MJIT.pause - while i < 10 - eval("def mjit#{i}; end; mjit#{i}") - i += 1 - end - print RubyVM::MJIT.pause # no JIT here - EOS - assert_equal('truefalsefalse', out) - assert_equal( - 5, err.scan(/#{JITSupport::JIT_SUCCESS_PREFIX}/).size, - "unexpected stdout:\n```\n#{out}```\n\nstderr:\n```\n#{err}```", - ) - end - - def test_pause_waits_until_compaction - out, err = eval_with_jit(<<~'EOS', verbose: 1, min_calls: 1, wait: false) - def a() end; a - def b() end; b - RubyVM::MJIT.pause - EOS - assert_equal( - 2, err.scan(/#{JITSupport::JIT_SUCCESS_PREFIX}/).size, - "unexpected stdout:\n```\n#{out}```\n\nstderr:\n```\n#{err}```", - ) - assert_equal( - 1, err.scan(/#{JITSupport::JIT_COMPACTION_PREFIX}/).size, - "unexpected stdout:\n```\n#{out}```\n\nstderr:\n```\n#{err}```", - ) unless RUBY_PLATFORM.match?(/mswin|mingw/) # compaction is not supported on Windows yet - end - - def test_pause_does_not_hang_on_full_units - out, _ = eval_with_jit(<<~'EOS', verbose: 1, min_calls: 1, max_cache: 10, wait: false) - i = 0 - while i < 11 - eval("def mjit#{i}; end; mjit#{i}") - i += 1 - end - print RubyVM::MJIT.pause - EOS - assert_equal('true', out) - end - - def test_pause_wait_false - out, err = eval_with_jit(<<~'EOS', verbose: 1, min_calls: 1, wait: false) - i = 0 - while i < 10 - eval("def mjit#{i}; end; mjit#{i}") - i += 1 - end - print RubyVM::MJIT.pause(wait: false) - print RubyVM::MJIT.pause(wait: false) - EOS - assert_equal('truefalse', out) - assert_equal(true, err.scan(/#{JITSupport::JIT_SUCCESS_PREFIX}/).size < 10) - end - - def test_resume - out, err = eval_with_jit(<<~'EOS', verbose: 1, min_calls: 1, wait: false) - print RubyVM::MJIT.resume - print RubyVM::MJIT.pause - print RubyVM::MJIT.resume - print RubyVM::MJIT.resume - print RubyVM::MJIT.pause - EOS - assert_equal('falsetruetruefalsetrue', out) - assert_equal(0, err.scan(/#{JITSupport::JIT_SUCCESS_PREFIX}/).size) - end -end diff --git a/test/ruby/test_settracefunc.rb b/test/ruby/test_settracefunc.rb index 7821a221dc..3085c0902a 100644 --- a/test/ruby/test_settracefunc.rb +++ b/test/ruby/test_settracefunc.rb @@ -3,21 +3,17 @@ require 'test/unit' class TestSetTraceFunc < Test::Unit::TestCase def setup - if defined?(RubyVM) - @original_compile_option = RubyVM::InstructionSequence.compile_option - RubyVM::InstructionSequence.compile_option = { - :trace_instruction => true, - :specialized_instruction => false - } - end + @original_compile_option = RubyVM::InstructionSequence.compile_option + RubyVM::InstructionSequence.compile_option = { + :trace_instruction => true, + :specialized_instruction => false + } @target_thread = Thread.current end def teardown set_trace_func(nil) - if defined?(RubyVM) - RubyVM::InstructionSequence.compile_option = @original_compile_option - end + RubyVM::InstructionSequence.compile_option = @original_compile_option @target_thread = nil end @@ -141,10 +137,6 @@ class TestSetTraceFunc < Test::Unit::TestCase assert_equal(["c-call", 9, :set_trace_func, Kernel], events.shift) assert_equal([], events) - - self.class.class_eval do - remove_const :Foo - end end def test_return # [ruby-dev:38701] @@ -370,11 +362,6 @@ class TestSetTraceFunc < Test::Unit::TestCase end assert_equal([], events[:set]) assert_equal([], events[:add]) - - # cleanup - self.class.class_eval do - remove_const :ThreadTraceInnerClass - end end def test_trace_defined_method @@ -481,10 +468,13 @@ class TestSetTraceFunc < Test::Unit::TestCase answer_events = [ # + [:c_return, 1, "xyzzy", TracePoint, :trace, TracePoint, :outer, trace], [:line, 4, 'xyzzy', self.class, method, self, :outer, :nothing], [:c_call, 4, 'xyzzy', Integer, :times, 1, :outer, :nothing], [:line, 4, 'xyzzy', self.class, method, self, nil, :nothing], [:line, 5, 'xyzzy', self.class, method, self, :inner, :nothing], + [:c_call, 5, 'xyzzy', Kernel, :tap, self, :inner, :nothing], + [:c_return, 5, "xyzzy", Kernel, :tap, self, :inner, self], [:c_return, 4, "xyzzy", Integer, :times, 1, :outer, 1], [:line, 7, 'xyzzy', self.class, method, self, :outer, :nothing], [:c_call, 7, "xyzzy", Class, :inherited, Object, :outer, :nothing], @@ -510,6 +500,8 @@ class TestSetTraceFunc < Test::Unit::TestCase [:call, 13, "xyzzy", xyzzy.class, :bar, xyzzy, nil, :nothing], [:line, 14, "xyzzy", xyzzy.class, :bar, xyzzy, nil, :nothing], [:line, 15, "xyzzy", xyzzy.class, :bar, xyzzy, :XYZZY_bar, :nothing], + [:c_call, 15, "xyzzy", Kernel, :tap, xyzzy, :XYZZY_bar, :nothing], + [:c_return,15, "xyzzy", Kernel, :tap, xyzzy, :XYZZY_bar, xyzzy], [:return, 16, "xyzzy", xyzzy.class, :bar, xyzzy, :XYZZY_bar, xyzzy], [:return, 12, "xyzzy", xyzzy.class, :foo, xyzzy, :XYZZY_foo, xyzzy], [:line, 20, "xyzzy", TestSetTraceFunc, method, self, :outer, :nothing], @@ -525,45 +517,12 @@ class TestSetTraceFunc < Test::Unit::TestCase [:c_call, 20, "xyzzy", Module, :===, RuntimeError,:outer, :nothing], [:c_return,20, "xyzzy", Module, :===, RuntimeError,:outer, true], [:line, 21, "xyzzy", TestSetTraceFunc, method, self, :outer, :nothing], + [:c_call, 21, "xyzzy", TracePoint, :disable, trace, :outer, :nothing], ] return events, answer_events end - def test_tracepoint - events1, answer_events = *trace_by_tracepoint(:line, :class, :end, :call, :return, :c_call, :c_return, :raise) - - ms = [events1, answer_events].map{|evs| - evs.map{|e| - "#{e[0]} - #{e[2]}:#{e[1]} id: #{e[4]}" - } - } - - if false # show all events - printf(" %-60s | %-60s\n", "actual", "expected") - ms[0].zip(ms[1]){|a, b| - printf("%s%-60s | %-60s\n", a==b ? ' ' : '!', a, b) - } - end - - mesg = ms[0].zip(ms[1]).map{|a, b| - if a != b - "actual: #{a} <-> expected: #{b}" - end - }.compact.join("\n") - - answer_events.zip(events1){|answer, event| - assert_equal answer, event, mesg - } - - [:line, :class, :end, :call, :return, :c_call, :c_return, :raise].each{|event| - events1, answer_events = *trace_by_tracepoint(event) - answer_events.find_all{|e| e[0] == event}.zip(events1){|answer_line, event_line| - assert_equal answer_line, event_line - } - } - end - def trace_by_set_trace_func events = [] trace = nil @@ -571,9 +530,6 @@ class TestSetTraceFunc < Test::Unit::TestCase xyzzy = nil xyzzy = xyzzy _local_var = :outer - method = :trace_by_set_trace_func - raised_exc = nil - eval <<-EOF.gsub(/^.*?: /, ""), nil, 'xyzzy' 1: set_trace_func(lambda{|event, file, line, id, binding, klass| 2: events << [event, line, file, klass, id, binding.eval('self'), binding.eval("_local_var")] if file == 'xyzzy' @@ -598,69 +554,44 @@ class TestSetTraceFunc < Test::Unit::TestCase 21: set_trace_func(nil) EOF self.class.class_eval{remove_const(:XYZZY)} - - answer_events = [ - # - [:c_return, 1, "xyzzy", TracePoint, :trace, TracePoint, :outer, trace], - [:line, 4, 'xyzzy', self.class, method, self, :outer, :nothing], - [:c_call, 4, 'xyzzy', Integer, :times, 1, :outer, :nothing], - [:line, 4, 'xyzzy', self.class, method, self, nil, :nothing], - [:line, 5, 'xyzzy', self.class, method, self, :inner, :nothing], - [:c_return, 4, "xyzzy", Integer, :times, 1, :outer, 1], - [:line, 7, 'xyzzy', self.class, method, self, :outer, :nothing], - [:c_call, 7, "xyzzy", Class, :inherited, Object, :outer, :nothing], - [:c_return, 7, "xyzzy", Class, :inherited, Object, :outer, nil], - [:class, 7, "xyzzy", nil, nil, xyzzy.class, nil, :nothing], - [:line, 8, "xyzzy", nil, nil, xyzzy.class, nil, :nothing], - [:line, 9, "xyzzy", nil, nil, xyzzy.class, :XYZZY_outer, :nothing], - [:c_call, 9, "xyzzy", Module, :method_added, xyzzy.class, :XYZZY_outer, :nothing], - [:c_return, 9, "xyzzy", Module, :method_added, xyzzy.class, :XYZZY_outer, nil], - [:line, 13, "xyzzy", nil, nil, xyzzy.class, :XYZZY_outer, :nothing], - [:c_call, 13, "xyzzy", Module, :method_added, xyzzy.class, :XYZZY_outer, :nothing], - [:c_return,13, "xyzzy", Module, :method_added, xyzzy.class, :XYZZY_outer, nil], - [:end, 17, "xyzzy", nil, nil, xyzzy.class, :XYZZY_outer, :nothing], - [:line, 18, "xyzzy", TestSetTraceFunc, method, self, :outer, :nothing], - [:c_call, 18, "xyzzy", Class, :new, xyzzy.class, :outer, :nothing], - [:c_call, 18, "xyzzy", BasicObject, :initialize, xyzzy, :outer, :nothing], - [:c_return,18, "xyzzy", BasicObject, :initialize, xyzzy, :outer, nil], - [:c_return,18, "xyzzy", Class, :new, xyzzy.class, :outer, xyzzy], - [:line, 19, "xyzzy", TestSetTraceFunc, method, self, :outer, :nothing], - [:call, 9, "xyzzy", xyzzy.class, :foo, xyzzy, nil, :nothing], - [:line, 10, "xyzzy", xyzzy.class, :foo, xyzzy, nil, :nothing], - [:line, 11, "xyzzy", xyzzy.class, :foo, xyzzy, :XYZZY_foo, :nothing], - [:call, 13, "xyzzy", xyzzy.class, :bar, xyzzy, nil, :nothing], - [:line, 14, "xyzzy", xyzzy.class, :bar, xyzzy, nil, :nothing], - [:line, 15, "xyzzy", xyzzy.class, :bar, xyzzy, :XYZZY_bar, :nothing], - [:return, 16, "xyzzy", xyzzy.class, :bar, xyzzy, :XYZZY_bar, xyzzy], - [:return, 12, "xyzzy", xyzzy.class, :foo, xyzzy, :XYZZY_foo, xyzzy], - [:line, 20, "xyzzy", TestSetTraceFunc, method, self, :outer, :nothing], - [:c_call, 20, "xyzzy", Kernel, :raise, self, :outer, :nothing], - [:c_call, 20, "xyzzy", Exception, :exception, RuntimeError, :outer, :nothing], - [:c_call, 20, "xyzzy", Exception, :initialize, raised_exc, :outer, :nothing], - [:c_return,20, "xyzzy", Exception, :initialize, raised_exc, :outer, raised_exc], - [:c_return,20, "xyzzy", Exception, :exception, RuntimeError, :outer, raised_exc], - [:c_return,20, "xyzzy", Kernel, :raise, self, :outer, nil], - [:c_call, 20, "xyzzy", Exception, :backtrace, raised_exc, :outer, :nothing], - [:c_return,20, "xyzzy", Exception, :backtrace, raised_exc, :outer, nil], - [:raise, 20, "xyzzy", TestSetTraceFunc, :trace_by_tracepoint, self, :outer, raised_exc], - [:c_call, 20, "xyzzy", Module, :===, RuntimeError,:outer, :nothing], - [:c_return,20, "xyzzy", Module, :===, RuntimeError,:outer, true], - [:line, 21, "xyzzy", TestSetTraceFunc, method, self, :outer, :nothing], - [:c_call, 21, "xyzzy", TracePoint, :disable, trace, :outer, :nothing], - ] - return events, answer_events + return events end - def test_set_trace_func - actual_events, expected_events = trace_by_set_trace_func - expected_events.zip(actual_events){|e, a| - a[0] = a[0].to_s.sub('-', '_').to_sym - assert_equal e[0..2], a[0..2], a.inspect + def test_tracepoint + events1, answer_events = *trace_by_tracepoint(:line, :class, :end, :call, :return, :c_call, :c_return, :raise) + + ms = [events1, answer_events].map{|evs| + evs.map{|e| + "#{e[0]} - #{e[2]}:#{e[1]} id: #{e[4]}" + } + } + + mesg = ms[0].zip(ms[1]).map{|a, b| + if a != b + "#{a} <-> #{b}" + end + }.compact.join("\n") + + answer_events.zip(events1){|answer, event| + assert_equal answer, event, mesg + } + + events2 = trace_by_set_trace_func + events1.zip(events2){|ev1, ev2| + ev2[0] = ev2[0].sub('-', '_').to_sym + assert_equal ev1[0..2], ev2[0..2], ev1.inspect # event, line, file, klass, id, binding.eval('self'), binding.eval("_local_var") - assert_equal e[3].nil?, a[3].nil? # klass - assert_equal e[4].nil?, a[4].nil? # id - assert_equal e[6], a[6] # _local_var + assert_equal ev1[3].nil?, ev2[3].nil? # klass + assert_equal ev1[4].nil?, ev2[4].nil? # id + assert_equal ev1[6], ev2[6] # _local_var + } + + [:line, :class, :end, :call, :return, :c_call, :c_return, :raise].each{|event| + events1, answer_events = *trace_by_tracepoint(event) + answer_events.find_all{|e| e[0] == event}.zip(events1){|answer_line, event_line| + assert_equal answer_line, event_line + } } end @@ -745,7 +676,7 @@ class TestSetTraceFunc < Test::Unit::TestCase } foo trace.disable - assert_equal([:foo, :disable, :foo, :disable], ary) + assert_equal([:foo, :foo], ary) assert_equal([], args) trace = TracePoint.new{} @@ -772,45 +703,6 @@ class TestSetTraceFunc < Test::Unit::TestCase assert_equal(false, trace.enabled?) end - def parameter_test(a, b, c) - yield - end - - def test_tracepoint_parameters - trace = TracePoint.new(:line, :class, :end, :call, :return, :b_call, :b_return, :c_call, :c_return, :raise){|tp| - next if !target_thread? - next if tp.path != __FILE__ - case tp.event - when :call, :return - assert_equal([[:req, :a], [:req, :b], [:req, :c]], tp.parameters) - when :b_call, :b_return - next if tp.parameters == [] - if tp.parameters.first == [:opt, :x] - assert_equal([[:opt, :x], [:opt, :y], [:opt, :z]], tp.parameters) - else - assert_equal([[:req, :p], [:req, :q], [:req, :r]], tp.parameters) - end - when :c_call, :c_return - assert_equal([[:req]], tp.parameters) if tp.method_id == :getbyte - when :line, :class, :end, :raise - assert_raise(RuntimeError) { tp.parameters } - end - } - obj = Object.new - trace.enable{ - parameter_test(1, 2, 3) {|x, y, z| - } - lambda {|p, q, r| }.call(4, 5, 6) - "".getbyte(0) - class << obj - end - begin - raise - rescue - end - } - end - def method_test_tracepoint_return_value obj obj end @@ -837,13 +729,13 @@ class TestSetTraceFunc < Test::Unit::TestCase end def test_tracepoint_raised_exception - trace = TracePoint.new(:call, :return, :raise){|tp| + trace = TracePoint.new(:call, :return){|tp| next if !target_thread? case tp.event when :call, :return assert_raise(RuntimeError) { tp.raised_exception } when :raise - assert_kind_of(XYZZYException, tp.raised_exception) + assert_equal(XYZZYError, tp.raised_exception) end } trace.enable{ @@ -920,16 +812,14 @@ class TestSetTraceFunc < Test::Unit::TestCase def test_tracepoint_inspect events = [] - th = nil trace = TracePoint.new{|tp| - next if !target_thread? && th != Thread.current + next if !target_thread? events << [tp.event, tp.inspect] } assert_equal("#<TracePoint:disabled>", trace.inspect) trace.enable{ assert_equal("#<TracePoint:enabled>", trace.inspect) - th = Thread.new{} - th.join + Thread.new{}.join } assert_equal("#<TracePoint:disabled>", trace.inspect) events.each{|(ev, str)| @@ -937,9 +827,9 @@ class TestSetTraceFunc < Test::Unit::TestCase when :line assert_match(/ in /, str) when :call, :c_call - assert_match(/call \`/, str) # #<TracePoint:c_call `inherited' ../trunk/test.rb:11> + assert_match(/call \`/, str) # #<TracePoint:c_call `inherited'@../trunk/test.rb:11> when :return, :c_return - assert_match(/return \`/, str) # #<TracePoint:return `m' ../trunk/test.rb:3> + assert_match(/return \`/, str) # #<TracePoint:return `m'@../trunk/test.rb:3> when /thread/ assert_match(/\#<Thread:/, str) # #<TracePoint:thread_end of #<Thread:0x87076c0>> else @@ -1136,7 +1026,7 @@ class TestSetTraceFunc < Test::Unit::TestCase }.enable{ 3.times{ next - } # 3 times b_return + } # 3 times b_retun } # 1 time b_return assert_equal 4, n @@ -1554,6 +1444,7 @@ class TestSetTraceFunc < Test::Unit::TestCase end def test_throwing_return_with_finish_frame + target_th = Thread.current evs = [] TracePoint.new(:call, :return){|tp| @@ -1677,7 +1568,7 @@ class TestSetTraceFunc < Test::Unit::TestCase TracePoint.new(:return, &capture_events).enable{ o.alias_m } - assert_equal [[:return, :tap, :tap], [:return, :m, :alias_m]], events + assert_equal [[:return, :m, :alias_m]], events events.clear o = Class.new{ @@ -1701,13 +1592,13 @@ class TestSetTraceFunc < Test::Unit::TestCase events.clear o = Class.new{ - alias alias_singleton_class singleton_class - define_method(:m){alias_singleton_class} + alias alias_tap tap + define_method(:m){alias_tap{return}} }.new TracePoint.new(:c_return, &capture_events).enable{ o.m } - assert_equal [[:c_return, :singleton_class, :alias_singleton_class]], events + assert_equal [[:c_return, :tap, :alias_tap]], events events.clear c = Class.new{ @@ -1740,25 +1631,6 @@ class TestSetTraceFunc < Test::Unit::TestCase ary end - def test_single_raise_inside_load - events = [] - tmpdir = Dir.mktmpdir - path = "#{tmpdir}/hola.rb" - File.open(path, "w") { |f| f.write("raise") } - tp = TracePoint.new(:raise) {|tp| events << [tp.event] if target_thread?} - tp.enable{ - load path rescue nil - } - assert_equal [[:raise]], events - events.clear - tp.enable{ - require path rescue nil - } - assert_equal [[:raise]], events - ensure - FileUtils.rmtree(tmpdir) - end - def f_raise raise rescue @@ -1896,6 +1768,7 @@ class TestSetTraceFunc < Test::Unit::TestCase define_method(:m) {} tp = TracePoint.new(:call) do + next unless target_thread? raise '' end @@ -1961,9 +1834,6 @@ class TestSetTraceFunc < Test::Unit::TestCase } # it is dirty hack. usually we shouldn't use such technique Thread.pass until t.status == 'sleep' - # When MJIT thread exists, t.status becomes 'sleep' even if it does not reach m2t_q.pop. - # This sleep forces it to reach m2t_q.pop for --jit-wait. - sleep 1 if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? t.add_trace_func proc{|ev, file, line, *args| if file == __FILE__ @@ -1988,340 +1858,4 @@ class TestSetTraceFunc < Test::Unit::TestCase assert_equal ["c-call", base_line + 35], events[9] # Thread#set_trace_func assert_equal nil, events[10] end - - def test_lineno_in_optimized_insn - assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") - begin; - $loc = nil - class String - undef -@ - def -@ - $loc = caller_locations(1, 1)[0].lineno - end - end - - assert_predicate(-"", :frozen?) - assert_equal(__LINE__-1, $loc, '[Bug #14809]') - end; - end - - def method_for_enable_target1 - a = 1 - b = 2 - 1.times{|i| - _x = i - } - _c = a + b - end - - def method_for_enable_target2 - a = 1 - b = 2 - 1.times{|i| - _x = i - } - _c = a + b - end - - def check_with_events *trace_events - all_events = [[:call, :method_for_enable_target1], - [:line, :method_for_enable_target1], - [:line, :method_for_enable_target1], - [:line, :method_for_enable_target1], - [:b_call, :method_for_enable_target1], - [:line, :method_for_enable_target1], - [:b_return, :method_for_enable_target1], - [:line, :method_for_enable_target1], - [:return, :method_for_enable_target1], - # repeat - [:call, :method_for_enable_target1], - [:line, :method_for_enable_target1], - [:line, :method_for_enable_target1], - [:line, :method_for_enable_target1], - [:b_call, :method_for_enable_target1], - [:line, :method_for_enable_target1], - [:b_return, :method_for_enable_target1], - [:line, :method_for_enable_target1], - [:return, :method_for_enable_target1], - ] - events = [] - TracePoint.new(*trace_events) do |tp| - next unless target_thread? - events << [tp.event, tp.method_id] - end.enable(target: method(:method_for_enable_target1)) do - method_for_enable_target1 - method_for_enable_target2 - method_for_enable_target1 - end - assert_equal all_events.find_all{|(ev)| trace_events.include? ev}, events - end - - def test_tracepoint_enable_target - check_with_events :line - check_with_events :call, :return - check_with_events :line, :call, :return - check_with_events :call, :return, :b_call, :b_return - check_with_events :line, :call, :return, :b_call, :b_return - end - - def test_tracepoint_nested_enabled_with_target - code1 = proc{ - _a = 1 - } - code2 = proc{ - _b = 2 - } - - ## error - - # targeted TP and targeted TP - ex = assert_raise(ArgumentError) do - tp = TracePoint.new(:line){} - tp.enable(target: code1){ - tp.enable(target: code2){} - } - end - assert_equal "can't nest-enable a targeting TracePoint", ex.message - - # global TP and targeted TP - ex = assert_raise(ArgumentError) do - tp = TracePoint.new(:line){} - tp.enable{ - tp.enable(target: code2){} - } - end - assert_equal "can't nest-enable a targeting TracePoint", ex.message - - # targeted TP and global TP - ex = assert_raise(ArgumentError) do - tp = TracePoint.new(:line){} - tp.enable(target: code1){ - tp.enable{} - } - end - assert_equal "can't nest-enable a targeting TracePoint", ex.message - - # targeted TP and disable - ex = assert_raise(ArgumentError) do - tp = TracePoint.new(:line){} - tp.enable(target: code1){ - tp.disable{} - } - end - assert_equal "can't disable a targeting TracePoint in a block", ex.message - - ## success with two nesting targeting tracepoints - events = [] - tp1 = TracePoint.new(:line){|tp| events << :tp1} - tp2 = TracePoint.new(:line){|tp| events << :tp2} - tp1.enable(target: code1) do - tp2.enable(target: code1) do - code1.call - events << :___ - end - end - assert_equal [:tp2, :tp1, :___], events - - # success with two tracepoints (global/targeting) - events = [] - tp1 = TracePoint.new(:line){|tp| events << :tp1} - tp2 = TracePoint.new(:line){|tp| events << :tp2} - tp1.enable do - tp2.enable(target: code1) do - code1.call - events << :___ - end - end - assert_equal [:tp1, :tp1, :tp1, :tp1, :tp2, :tp1, :___], events - - # success with two tracepoints (targeting/global) - events = [] - tp1 = TracePoint.new(:line){|tp| events << :tp1} - tp2 = TracePoint.new(:line){|tp| events << :tp2} - tp1.enable(target: code1) do - tp2.enable do - code1.call - events << :___ - end - end - assert_equal [:tp2, :tp2, :tp1, :tp2, :___], events - end - - def test_tracepoint_enable_with_target_line - events = [] - line_0 = __LINE__ - code1 = proc{ - events << 1 - events << 2 - events << 3 - } - tp = TracePoint.new(:line) do |tp| - events << :tp - end - tp.enable(target: code1, target_line: line_0 + 3) do - code1.call - end - assert_equal [1, :tp, 2, 3], events - - - e = assert_raise(ArgumentError) do - TracePoint.new(:line){}.enable(target_line: 10){} - end - assert_equal 'only target_line is specified', e.message - - e = assert_raise(ArgumentError) do - TracePoint.new(:call){}.enable(target: code1, target_line: 10){} - end - assert_equal 'target_line is specified, but line event is not specified', e.message - end - - def test_tracepoint_enable_with_target_line_two_times - events = [] - line_0 = __LINE__ - code1 = proc{ - events << 1 # tp1 - events << 2 - events << 3 # tp2 - } - - tp1 = TracePoint.new(:line) do |tp| - events << :tp1 - end - tp2 = TracePoint.new(:line) do |tp| - events << :tp2 - end - - tp1.enable(target: code1, target_line: line_0 + 2) do - tp2.enable(target: code1, target_line: line_0 + 4) do - # two hooks - code1.call - end - end - assert_equal [:tp1, 1, 2, :tp2, 3], events - end - - def test_script_compiled - events = [] - tp = TracePoint.new(:script_compiled){|tp| - next unless target_thread? - events << [tp.instruction_sequence.path, - tp.eval_script] - } - - eval_script = 'a = 1' - tp.enable{ - eval(eval_script, nil, __FILE__+"/eval") - nil.instance_eval(eval_script, __FILE__+"/instance_eval") - Object.class_eval(eval_script, __FILE__+"/class_eval") - } - assert_equal [[__FILE__+"/eval", eval_script], - [__FILE__+"/instance_eval", eval_script], - [__FILE__+"/class_eval", eval_script], - ], events - - events.clear - tp.enable{ - begin - eval('a=') - rescue SyntaxError - end - } - assert_equal [], events, 'script_compiled event should not be invoked on compile error' - - skip "TODO: test for requires" - - events.clear - tp.enable{ - require '' - require_relative '' - load '' - } - assert_equal [], events - end - - def test_enable_target_thread - events = [] - TracePoint.new(:line) do |tp| - events << Thread.current - end.enable(target_thread: Thread.current) do - _a = 1 - Thread.new{ - _b = 2 - _c = 3 - }.join - _d = 4 - end - assert_equal Array.new(3){Thread.current}, events - - events = [] - tp = TracePoint.new(:line) do |tp| - events << Thread.current - end - - q1 = Queue.new - q2 = Queue.new - - th = Thread.new{ - q1 << :ok; q2.pop - _t1 = 1 - _t2 = 2 - } - q1.pop - tp.enable(target_thread: th) do - q2 << 1 - _a = 1 - _b = 2 - th.join - end - - assert_equal Array.new(2){th}, events - end - - def test_return_event_with_rescue - obj = Object.new - def obj.example - 1 if 1 == 1 - rescue - end - ok = false - tp = TracePoint.new(:return) {ok = true} - tp.enable {obj.example} - assert ok, "return event should be emitted" - end - - def test_disable_local_tracepoint_in_trace - assert_normal_exit <<-EOS - def foo - trace = TracePoint.new(:b_return){|tp| - tp.disable - } - trace.enable(target: method(:bar)) - end - def bar - 100.times{|i| - foo; foo - } - end - bar - EOS - end - - def test_stat_exists - assert_instance_of Hash, TracePoint.stat - end - - def test_tracepoint_opt_invokebuiltin_delegate_leave - code = 'puts RubyVM::InstructionSequence.of("\x00".method(:unpack)).disasm' - out = EnvUtil.invoke_ruby(['-e', code], '', true).first - assert_match(/^0000 opt_invokebuiltin_delegate_leave /, out) - - event = eval(EnvUtil.invoke_ruby(['-e', <<~'EOS'], '', true).first) - TracePoint.new(:return) do |tp| - p [tp.event, tp.method_id] - end.enable do - "\x00".unpack("c") - end - EOS - assert_equal [:return, :unpack], event - end end diff --git a/test/ruby/test_signal.rb b/test/ruby/test_signal.rb index a62537d59d..2d98b0b564 100644 --- a/test/ruby/test_signal.rb +++ b/test/ruby/test_signal.rb @@ -28,8 +28,7 @@ class TestSignal < Test::Unit::TestCase def test_signal_process_group bug4362 = '[ruby-dev:43169]' assert_nothing_raised(bug4362) do - cmd = [ EnvUtil.rubybin, '--disable=gems' '-e', 'sleep 10' ] - pid = Process.spawn(*cmd, :pgroup => true) + pid = Process.spawn(EnvUtil.rubybin, '-e', 'sleep 10', :pgroup => true) Process.kill(:"-TERM", pid) Process.waitpid(pid) assert_equal(true, $?.signaled?) @@ -45,7 +44,7 @@ class TestSignal < Test::Unit::TestCase sig = "INT" term = :KILL end - IO.popen([EnvUtil.rubybin, '--disable=gems', '-e', <<-"End"], 'r+') do |io| + IO.popen([EnvUtil.rubybin, '-e', <<-"End"], 'r+') do |io| Signal.trap(:#{sig}, "EXIT") STDOUT.syswrite("a") Thread.start { sleep(2) } @@ -84,12 +83,10 @@ class TestSignal < Test::Unit::TestCase assert_raise_with_message(ArgumentError, /\u{30eb 30d3 30fc}/) { SignalException.new("\u{30eb 30d3 30fc}") } Signal.list.each do |signm, signo| next if signm == "EXIT" - assert_equal(signo, SignalException.new(signm).signo, signm) - assert_equal(signo, SignalException.new(signm.to_sym).signo, signm) - assert_equal(signo, SignalException.new(signo).signo, signo) + assert_equal(SignalException.new(signm).signo, signo) + assert_equal(SignalException.new(signm.to_sym).signo, signo) + assert_equal(SignalException.new(signo).signo, signo) end - e = assert_raise(ArgumentError) {SignalException.new("-SIGEXIT")} - assert_not_match(/SIG-SIG/, e.message) end def test_interrupt @@ -137,6 +134,11 @@ class TestSignal < Test::Unit::TestCase assert_raise(ArgumentError) { Signal.trap } + assert_raise(SecurityError) do + s = proc {}.taint + Signal.trap(:INT, s) + end + # FIXME! Signal.trap(:INT, nil) Signal.trap(:INT, "") @@ -162,8 +164,6 @@ class TestSignal < Test::Unit::TestCase assert_raise(ArgumentError) { Signal.trap("XXXXXXXXXX", "SIG_DFL") } assert_raise_with_message(ArgumentError, /\u{30eb 30d3 30fc}/) { Signal.trap("\u{30eb 30d3 30fc}", "SIG_DFL") } - - assert_raise(ArgumentError) { Signal.trap("EXIT\0") {} } ensure Signal.trap(:INT, oldtrap) if oldtrap end @@ -228,20 +228,20 @@ class TestSignal < Test::Unit::TestCase end def test_signame_delivered - args = [EnvUtil.rubybin, "--disable=gems", "-e", <<"", :err => File::NULL] - Signal.trap("INT") do |signo| - signame = Signal.signame(signo) - Marshal.dump(signame, STDOUT) - STDOUT.flush - exit 0 - end - Process.kill("INT", $$) - sleep 1 # wait signal deliver - 10.times do - IO.popen(args) do |child| + IO.popen([EnvUtil.rubybin, "-e", <<EOS, :err => File::NULL]) do |child| + Signal.trap("INT") do |signo| + signame = Signal.signame(signo) + Marshal.dump(signame, STDOUT) + STDOUT.flush + exit 0 + end + Process.kill("INT", $$) + sleep 1 # wait signal deliver +EOS + signame = Marshal.load(child) - assert_equal("INT", signame) + assert_equal(signame, "INT") end end end if Process.respond_to?(:kill) @@ -321,67 +321,4 @@ class TestSignal < Test::Unit::TestCase end end; end - - def test_sigchld_ignore - skip 'no SIGCHLD' unless Signal.list['CHLD'] - old = trap(:CHLD, 'IGNORE') - cmd = [ EnvUtil.rubybin, '--disable=gems', '-e' ] - assert(system(*cmd, 'exit!(0)'), 'no ECHILD') - IO.pipe do |r, w| - pid = spawn(*cmd, "STDIN.read", in: r) - nb = Process.wait(pid, Process::WNOHANG) - th = Thread.new(Thread.current) do |parent| - Thread.pass until parent.stop? # wait for parent to Process.wait - w.close - end - assert_raise(Errno::ECHILD) { Process.wait(pid) } - th.join - assert_nil nb - end - - IO.pipe do |r, w| - pids = 3.times.map { spawn(*cmd, 'exit!', out: w) } - w.close - zombies = pids.dup - assert_nil r.read(1), 'children dead' - - Timeout.timeout(10) do - zombies.delete_if do |pid| - begin - Process.kill(0, pid) - false - rescue Errno::ESRCH - true - end - end while zombies[0] - end - assert_predicate zombies, :empty?, 'zombies leftover' - - pids.each do |pid| - assert_raise(Errno::ECHILD) { Process.waitpid(pid) } - end - end - ensure - trap(:CHLD, old) if Signal.list['CHLD'] - end - - def test_sigwait_fd_unused - t = EnvUtil.apply_timeout_scale(0.1) - assert_separately([], <<-End) - tgt = $$ - trap(:TERM) { exit(0) } - e = "Process.daemon; sleep #{t * 2}; Process.kill(:TERM,\#{tgt})" - term = [ '#{EnvUtil.rubybin}', '--disable=gems', '-e', e ] - t2 = Thread.new { sleep } # grab sigwait_fd - Thread.pass until t2.stop? - Thread.new do - sleep #{t} - t2.kill - t2.join - end - Process.spawn(*term) - # last thread remaining, ensure it can react to SIGTERM - loop { sleep } - End - end if Process.respond_to?(:kill) && Process.respond_to?(:daemon) end diff --git a/test/ruby/test_sprintf.rb b/test/ruby/test_sprintf.rb index 7986e9d141..a07ac7908b 100644 --- a/test/ruby/test_sprintf.rb +++ b/test/ruby/test_sprintf.rb @@ -238,12 +238,6 @@ class TestSprintf < Test::Unit::TestCase assert_equal("with options {:capture=>/\\d+/}", sprintf("with options %p" % options)) end - def test_inspect - obj = Object.new - def obj.inspect; "TEST"; end - assert_equal("<TEST>", sprintf("<%p>", obj)) - end - def test_invalid # Star precision before star width: assert_raise(ArgumentError, "[ruby-core:11569]") {sprintf("%.**d", 5, 10, 1)} @@ -530,17 +524,12 @@ class TestSprintf < Test::Unit::TestCase end def test_no_hidden_garbage - skip unless Thread.list.size == 1 - fmt = [4, 2, 2].map { |x| "%0#{x}d" }.join('-') # defeats optimization ObjectSpace.count_objects(res = {}) # creates strings on first call - GC.disable before = ObjectSpace.count_objects(res)[:T_STRING] val = sprintf(fmt, 1970, 1, 1) after = ObjectSpace.count_objects(res)[:T_STRING] assert_equal before + 1, after, 'only new string is the created one' assert_equal '1970-01-01', val - ensure - GC.enable end end diff --git a/test/ruby/test_stack.rb b/test/ruby/test_stack.rb deleted file mode 100644 index 763aeb6bc2..0000000000 --- a/test/ruby/test_stack.rb +++ /dev/null @@ -1,82 +0,0 @@ -# frozen_string_literal: false -require 'test/unit' -require 'tmpdir' - -class TestStack < Test::Unit::TestCase - LARGE_VM_STACK_SIZE = 1024*1024*5 - LARGE_MACHINE_STACK_SIZE = 1024*1024*10 - - def initialize(*) - super - - @h_default = nil - @h_0 = nil - @h_large = nil - end - - def invoke_ruby script, vm_stack_size: nil, machine_stack_size: nil - env = {} - env['RUBY_FIBER_VM_STACK_SIZE'] = vm_stack_size.to_s if vm_stack_size - env['RUBY_FIBER_MACHINE_STACK_SIZE'] = machine_stack_size.to_s if machine_stack_size - env['ASAN_OPTIONS'] = ENV['ASAN_OPTIONS'] if ENV['ASAN_OPTIONS'] - - stdout, stderr, status = EnvUtil.invoke_ruby([env, '-e', script], '', true, true, timeout: 30) - assert(!status.signaled?, FailDesc[status, nil, stderr]) - - return stdout - end - - def h_default - @h_default ||= eval(invoke_ruby('p RubyVM::DEFAULT_PARAMS')) - end - - def h_0 - @h_0 ||= eval(invoke_ruby('p RubyVM::DEFAULT_PARAMS', - vm_stack_size: 0, - machine_stack_size: 0 - )) - end - - def h_large - @h_large ||= eval(invoke_ruby('p RubyVM::DEFAULT_PARAMS', - vm_stack_size: LARGE_VM_STACK_SIZE, - machine_stack_size: LARGE_MACHINE_STACK_SIZE - )) - end - - def test_relative_stack_sizes - assert_operator(h_default[:fiber_vm_stack_size], :>, h_0[:fiber_vm_stack_size]) - assert_operator(h_default[:fiber_vm_stack_size], :<, h_large[:fiber_vm_stack_size]) - assert_operator(h_default[:fiber_machine_stack_size], :>=, h_0[:fiber_machine_stack_size]) - assert_operator(h_default[:fiber_machine_stack_size], :<=, h_large[:fiber_machine_stack_size]) - end - - def test_vm_stack_size - script = '$stdout.sync=true; def rec; print "."; rec; end; Fiber.new{rec}.resume' - - size_default = invoke_ruby(script).bytesize - assert_operator(size_default, :>, 0) - - size_0 = invoke_ruby(script, vm_stack_size: 0).bytesize - assert_operator(size_default, :>, size_0) - - size_large = invoke_ruby(script, vm_stack_size: LARGE_VM_STACK_SIZE).bytesize - assert_operator(size_default, :<, size_large) - end - - # Depending on OS, machine stack size may not change size. - def test_machine_stack_size - return if /mswin|mingw/ =~ RUBY_PLATFORM - - script = '$stdout.sync=true; def rec; print "."; 1.times{1.times{1.times{rec}}}; end; Fiber.new{rec}.resume' - - vm_stack_size = 1024 * 1024 - size_default = invoke_ruby(script, vm_stack_size: vm_stack_size).bytesize - - size_0 = invoke_ruby(script, vm_stack_size: vm_stack_size, machine_stack_size: 0).bytesize - assert_operator(size_default, :>=, size_0) - - size_large = invoke_ruby(script, vm_stack_size: vm_stack_size, machine_stack_size: LARGE_MACHINE_STACK_SIZE).bytesize - assert_operator(size_default, :<=, size_large) - end -end diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb index 4814872789..9574ed31c9 100644 --- a/test/ruby/test_string.rb +++ b/test/ruby/test_string.rb @@ -2,10 +2,7 @@ require 'test/unit' class TestString < Test::Unit::TestCase - WIDE_ENCODINGS = [ - Encoding::UTF_16BE, Encoding::UTF_16LE, - Encoding::UTF_32BE, Encoding::UTF_32LE, - ] + ENUMERATOR_WANTARRAY = RUBY_VERSION >= "3.0.0" def initialize(*args) @cls = String @@ -15,8 +12,8 @@ class TestString < Test::Unit::TestCase super end - def S(*args, **kw) - @cls.new(*args, **kw) + def S(*args) + @cls.new(*args) end def test_s_new @@ -255,7 +252,6 @@ CODE assert_not_equal(S("CAT"), S('cat')) assert_not_equal(S("CaT"), S('cAt')) - assert_not_equal(S("cat\0""dog"), S("cat\0")) o = Object.new def o.to_str; end @@ -386,8 +382,6 @@ CODE end def test_chomp - verbose, $VERBOSE = $VERBOSE, nil - assert_equal(S("hello"), S("hello").chomp("\n")) assert_equal(S("hello"), S("hello\n").chomp("\n")) save = $/ @@ -453,12 +447,9 @@ CODE assert_equal("foo", s.chomp("\n")) ensure $/ = save - $VERBOSE = verbose end def test_chomp! - verbose, $VERBOSE = $VERBOSE, nil - a = S("hello") a.chomp!(S("\n")) @@ -515,7 +506,6 @@ CODE s = S("").freeze assert_raise_with_message(FrozenError, /frozen/) {s.chomp!} - $VERBOSE = nil # EnvUtil.suppress_warning resets $VERBOSE to the original state s = S("ax") o = Struct.new(:s).new(s) @@ -524,7 +514,6 @@ CODE "x" end assert_raise_with_message(FrozenError, /frozen/) {s.chomp!(o)} - $VERBOSE = nil # EnvUtil.suppress_warning resets $VERBOSE to the original state s = S("hello") assert_equal("hel", s.chomp!('lo')) @@ -575,7 +564,6 @@ CODE assert_equal("foo", s.chomp!("\n")) ensure $/ = save - $VERBOSE = verbose end def test_chop @@ -614,14 +602,18 @@ CODE end def test_clone - for frozen in [ false, true ] - a = S("Cool") - a.freeze if frozen - b = a.clone - - assert_equal(a, b) - assert_not_same(a, b) - assert_equal(a.frozen?, b.frozen?) + for taint in [ false, true ] + for frozen in [ false, true ] + a = S("Cool") + a.taint if taint + a.freeze if frozen + b = a.clone + + assert_equal(a, b) + assert_not_same(a, b) + assert_equal(a.frozen?, b.frozen?) + assert_equal(a.tainted?, b.tainted?) + end end assert_equal("", File.read(IO::NULL).clone, '[ruby-dev:32819] reported by Kazuhiro NISHIYAMA') @@ -668,35 +660,21 @@ CODE assert_raise(ArgumentError) { "foo".count } end - def crypt_supports_des_crypt? - /openbsd/ !~ RUBY_PLATFORM - end - def test_crypt - if crypt_supports_des_crypt? - pass = "aaGUC/JkO9/Sc" - good_salt = "aa" - bad_salt = "ab" - else - pass = "$2a$04$0WVaz0pV3jzfZ5G5tpmHWuBQGbkjzgtSc3gJbmdy0GAGMa45MFM2." - good_salt = "$2a$04$0WVaz0pV3jzfZ5G5tpmHWu" - bad_salt = "$2a$04$0WVaz0pV3jzfZ5G5tpmHXu" - end - assert_equal(S(pass), S("mypassword").crypt(S(good_salt))) - assert_not_equal(S(pass), S("mypassword").crypt(S(bad_salt))) + assert_equal(S('aaGUC/JkO9/Sc'), S("mypassword").crypt(S("aa"))) + assert_not_equal(S('aaGUC/JkO9/Sc'), S("mypassword").crypt(S("ab"))) assert_raise(ArgumentError) {S("mypassword").crypt(S(""))} assert_raise(ArgumentError) {S("mypassword").crypt(S("\0a"))} assert_raise(ArgumentError) {S("mypassword").crypt(S("a\0"))} assert_raise(ArgumentError) {S("poison\u0000null").crypt(S("aa"))} - WIDE_ENCODINGS.each do |enc| + [Encoding::UTF_16BE, Encoding::UTF_16LE, + Encoding::UTF_32BE, Encoding::UTF_32LE].each do |enc| assert_raise(ArgumentError) {S("mypassword").crypt(S("aa".encode(enc)))} assert_raise(ArgumentError) {S("mypassword".encode(enc)).crypt(S("aa"))} end - @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 } + @cls == String and assert_no_memory_leak([], 's = ""', <<~'end;') # do + 1000.times { s.crypt(-"..").clear } end; end @@ -758,7 +736,6 @@ CODE assert_equal(S("hello"), S("hello").downcase) assert_equal(S("hello"), S("HELLO").downcase) assert_equal(S("abc hello 123"), S("abc HELLO 123").downcase) - assert_equal(S("h\0""ello"), S("h\0""ELLO").downcase) end def test_downcase! @@ -771,12 +748,6 @@ CODE a=S("hello") assert_nil(a.downcase!) assert_equal(S("hello"), a) - - a = S("h\0""ELLO") - b = a.dup - assert_equal(S("h\0""ello"), a.downcase!) - assert_equal(S("h\0""ello"), a) - assert_equal(S("h\0""ELLO"), b) end def test_dump @@ -855,26 +826,25 @@ CODE assert_raise(RuntimeError) { S('"\xA"').undump } assert_raise(RuntimeError) { S('"\\"').undump } assert_raise(RuntimeError) { S(%("\0")).undump } - assert_raise_with_message(RuntimeError, /invalid/) { - '"\\u{007F}".xxxxxx'.undump - } end def test_dup - for frozen in [ false, true ] - a = S("hello") - a.freeze if frozen - b = a.dup - - assert_equal(a, b) - assert_not_same(a, b) - assert_not_predicate(b, :frozen?) + for taint in [ false, true ] + for frozen in [ false, true ] + a = S("hello") + a.taint if taint + a.freeze if frozen + b = a.dup + + assert_equal(a, b) + assert_not_same(a, b) + assert_not_predicate(b, :frozen?) + assert_equal(a.tainted?, b.tainted?) + end end end def test_each - verbose, $VERBOSE = $VERBOSE, nil - save = $/ $/ = "\n" res=[] @@ -894,7 +864,6 @@ CODE assert_equal(S("world"), res[1]) ensure $/ = save - $VERBOSE = verbose end def test_each_byte @@ -913,15 +882,26 @@ CODE s = S("ABC") assert_equal [65, 66, 67], s.bytes - res = [] - assert_equal s.object_id, s.bytes {|x| res << x }.object_id - assert_equal(65, res[0]) - assert_equal(66, res[1]) - assert_equal(67, res[2]) - s = S("ABC") - res = [] - assert_same s, s.bytes {|x| res << x } - assert_equal [65, 66, 67], res + if ENUMERATOR_WANTARRAY + assert_warn(/block not used/) { + assert_equal [65, 66, 67], s.bytes {} + } + else + warning = /passing a block to String#bytes is deprecated/ + assert_warning(warning) { + res = [] + assert_equal s.object_id, s.bytes {|x| res << x }.object_id + assert_equal(65, res[0]) + assert_equal(66, res[1]) + assert_equal(67, res[2]) + } + assert_warning(warning) { + s = S("ABC") + res = [] + assert_same s, s.bytes {|x| res << x } + assert_equal [65, 66, 67], res + } + end end def test_each_codepoint @@ -946,15 +926,26 @@ CODE s = S("\u3042\u3044\u3046") assert_equal [0x3042, 0x3044, 0x3046], s.codepoints - res = [] - assert_equal s.object_id, s.codepoints {|x| res << x }.object_id - assert_equal(0x3042, res[0]) - assert_equal(0x3044, res[1]) - assert_equal(0x3046, res[2]) - s = S("ABC") - res = [] - assert_same s, s.codepoints {|x| res << x } - assert_equal [65, 66, 67], res + if ENUMERATOR_WANTARRAY + assert_warn(/block not used/) { + assert_equal [0x3042, 0x3044, 0x3046], s.codepoints {} + } + else + warning = /passing a block to String#codepoints is deprecated/ + assert_warning(warning) { + res = [] + assert_equal s.object_id, s.codepoints {|x| res << x }.object_id + assert_equal(0x3042, res[0]) + assert_equal(0x3044, res[1]) + assert_equal(0x3046, res[2]) + } + assert_warning(warning) { + s = S("ABC") + res = [] + assert_same s, s.codepoints {|x| res << x } + assert_equal [65, 66, 67], res + } + end end def test_each_char @@ -973,11 +964,20 @@ CODE s = S("ABC") assert_equal ["A", "B", "C"], s.chars - res = [] - assert_equal s.object_id, s.chars {|x| res << x }.object_id - assert_equal("A", res[0]) - assert_equal("B", res[1]) - assert_equal("C", res[2]) + if ENUMERATOR_WANTARRAY + assert_warn(/block not used/) { + assert_equal ["A", "B", "C"], s.chars {} + } + else + warning = /passing a block to String#chars is deprecated/ + assert_warning(warning) { + res = [] + assert_equal s.object_id, s.chars {|x| res << x }.object_id + assert_equal("A", res[0]) + assert_equal("B", res[1]) + assert_equal("C", res[2]) + } + end end def test_each_grapheme_cluster @@ -999,8 +999,8 @@ CODE end [ - ["\u{a 324}", ["\u000A", "\u0324"]], - ["\u{d 324}", ["\u000D", "\u0324"]], + ["\u{a 308}", ["\u000A", "\u0308"]], + ["\u{d 308}", ["\u000D", "\u0308"]], ["abc", ["a", "b", "c"]], ].each do |str, grapheme_clusters| assert_equal grapheme_clusters, str.each_grapheme_cluster.to_a @@ -1023,33 +1023,32 @@ CODE "\u{1F468 200D 1F393}", "\u{1F46F 200D 2642 FE0F}", "\u{1f469 200d 2764 fe0f 200d 1f469}", - ].product([Encoding::UTF_8, *WIDE_ENCODINGS]) do |g, enc| - g = g.encode(enc) + ].each do |g| assert_equal [g], g.grapheme_clusters end - [ - "\u{a 324}", - "\u{d 324}", - "abc", - ].product([Encoding::UTF_8, *WIDE_ENCODINGS]) do |g, enc| - g = g.encode(enc) - assert_equal g.chars, g.grapheme_clusters - end + assert_equal ["\u000A", "\u0308"], "\u{a 308}".grapheme_clusters + assert_equal ["\u000D", "\u0308"], "\u{d 308}".grapheme_clusters assert_equal ["a", "b", "c"], "abc".b.grapheme_clusters - s = "ABC".b - res = [] - assert_same s, s.grapheme_clusters {|x| res << x } - assert_equal(3, res.size) - assert_equal("A", res[0]) - assert_equal("B", res[1]) - assert_equal("C", res[2]) + if ENUMERATOR_WANTARRAY + assert_warn(/block not used/) { + assert_equal ["A", "B", "C"], "ABC".grapheme_clusters {} + } + else + warning = /passing a block to String#grapheme_clusters is deprecated/ + assert_warning(warning) { + s = "ABC".b + res = [] + assert_same s, s.grapheme_clusters {|x| res << x } + assert_equal("A", res[0]) + assert_equal("B", res[1]) + assert_equal("C", res[2]) + } + end end def test_each_line - verbose, $VERBOSE = $VERBOSE, nil - save = $/ $/ = "\n" res=[] @@ -1096,7 +1095,6 @@ CODE end ensure $/ = save - $VERBOSE = verbose end def test_each_line_chomp @@ -1154,10 +1152,18 @@ CODE assert_equal ["hello\n", "world"], s.lines assert_equal ["hello\nworld"], s.lines(nil) - res = [] - assert_equal s.object_id, s.lines {|x| res << x }.object_id - assert_equal(S("hello\n"), res[0]) - assert_equal(S("world"), res[1]) + if ENUMERATOR_WANTARRAY + assert_warn(/block not used/) { + assert_equal ["hello\n", "world"], s.lines {} + } + else + assert_warning(/passing a block to String#lines is deprecated/) { + res = [] + assert_equal s.object_id, s.lines {|x| res << x }.object_id + assert_equal(S("hello\n"), res[0]) + assert_equal(S("world"), res[1]) + } + end end def test_empty? @@ -1189,6 +1195,10 @@ CODE S("hello").gsub(/(hell)(.)/) { |s| $1.upcase + S('-') + $2 }) assert_equal(S("<>h<>e<>l<>l<>o<>"), S("hello").gsub(S(''), S('<\0>'))) + a = S("hello") + a.taint + assert_predicate(a.gsub(/./, S('X')), :tainted?) + assert_equal("z", "abc".gsub(/./, "a" => "z"), "moved from btest/knownbug") assert_raise(ArgumentError) { "foo".gsub } @@ -1233,6 +1243,11 @@ CODE a.gsub!(/(hell)(.)/) { |s| $1.upcase + S('-') + $2 } assert_equal(S("HELL-o"), a) + r = S('X') + r.taint + a.gsub!(/./, r) + assert_predicate(a, :tainted?) + a = S("hello") assert_nil(a.sub!(S('X'), S('Y'))) end @@ -1321,8 +1336,6 @@ CODE assert_nil("foo".index(//, -100)) assert_nil($~) - - assert_equal(2, S("abcdbce").index(/b\Kc/)) end def test_insert @@ -1426,8 +1439,10 @@ CODE assert_equal(S("foobar"), a.replace(S("foobar"))) a = S("foo") + a.taint b = a.replace(S("xyz")) assert_equal(S("xyz"), b) + assert_predicate(b, :tainted?) s = "foo" * 100 s2 = ("bar" * 100).dup @@ -1495,8 +1510,6 @@ CODE assert_equal(3, "foo".rindex(//)) assert_equal([3, 3], $~.offset(0)) - - assert_equal(5, S("abcdbce").rindex(/b\Kc/)) end def test_rjust @@ -1524,6 +1537,12 @@ CODE a.scan(/(...)/) { |w| res << w } assert_equal([[S("cru")], [S("el ")], [S("wor")]],res) + a = S("hello") + a.taint + res = [] + a.scan(/./) { |w| res << w } + assert_predicate(res[0], :tainted?, '[ruby-core:33338] #4087') + /h/ =~ a a.scan(/x/) assert_nil($~) @@ -1532,6 +1551,8 @@ CODE a.scan('x') assert_nil($~) + assert_equal(3, S("hello hello hello").scan("hello".taint).count(&:tainted?)) + assert_equal(%w[1 2 3], S("a1 a2 a3").scan(/a\K./)) end @@ -1588,10 +1609,8 @@ CODE a = S("FooBar") if @aref_slicebang_silent assert_nil( a.slice!(6) ) - assert_nil( a.slice!(6r) ) else assert_raise(IndexError) { a.slice!(6) } - assert_raise(IndexError) { a.slice!(6r) } end assert_equal(S("FooBar"), a) @@ -1702,51 +1721,10 @@ CODE assert_equal([S("a"), S(""), S("b"), S("c"), S("")], S("a||b|c|").split(S('|'), -1)) assert_equal([], "".split(//, 1)) - ensure - EnvUtil.suppress_warning {$; = fs} - end - - def test_split_with_block - fs, $; = $;, nil - result = []; S(" a b\t c ").split {|s| result << s} - assert_equal([S("a"), S("b"), S("c")], result) - result = []; S(" a b\t c ").split(S(" ")) {|s| result << s} - assert_equal([S("a"), S("b"), S("c")], result) - - result = []; S(" a | b | c ").split(S("|")) {|s| result << s} - assert_equal([S(" a "), S(" b "), S(" c ")], result) - - result = []; S("aXXbXXcXX").split(/X./) {|s| result << s} - assert_equal([S("a"), S("b"), S("c")], result) - result = []; S("abc").split(//) {|s| result << s} - assert_equal([S("a"), S("b"), S("c")], result) - - result = []; S("a|b|c").split(S('|'), 1) {|s| result << s} - assert_equal([S("a|b|c")], result) - - result = []; S("a|b|c").split(S('|'), 2) {|s| result << s} - assert_equal([S("a"), S("b|c")], result) - result = []; S("a|b|c").split(S('|'), 3) {|s| result << s} - assert_equal([S("a"), S("b"), S("c")], result) - - result = []; S("a|b|c|").split(S('|'), -1) {|s| result << s} - assert_equal([S("a"), S("b"), S("c"), S("")], result) - result = []; S("a|b|c||").split(S('|'), -1) {|s| result << s} - assert_equal([S("a"), S("b"), S("c"), S(""), S("")], result) - - result = []; S("a||b|c|").split(S('|')) {|s| result << s} - assert_equal([S("a"), S(""), S("b"), S("c")], result) - result = []; S("a||b|c|").split(S('|'), -1) {|s| result << s} - assert_equal([S("a"), S(""), S("b"), S("c"), S("")], result) - - result = []; "".split(//, 1) {|s| result << s} - assert_equal([], result) - - result = []; "aaa,bbb,ccc,ddd".split(/,/) {|s| result << s.gsub(/./, "A")} - assert_equal(["AAA"]*4, result) + assert_equal("[2, 3]", [1,2,3].slice!(1,10000).inspect, "moved from btest/knownbug") ensure - EnvUtil.suppress_warning {$; = fs} + $; = fs end def test_fs @@ -1754,7 +1732,7 @@ CODE $; = [] } - assert_separately(%W[-W0], "#{<<~"begin;"}\n#{<<~'end;'}") + assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") bug = '[ruby-core:79582] $; must not be GCed' begin; $; = " " @@ -1777,7 +1755,10 @@ CODE def test_split_wchar bug8642 = '[ruby-core:56036] [Bug #8642]' - WIDE_ENCODINGS.each do |enc| + [ + Encoding::UTF_16BE, Encoding::UTF_16LE, + Encoding::UTF_32BE, Encoding::UTF_32LE, + ].each do |enc| s = S("abc,def".encode(enc)) assert_equal(["abc", "def"].map {|c| c.encode(enc)}, s.split(",".encode(enc)), @@ -1804,12 +1785,6 @@ CODE s.split("b", 1).map(&:upcase!) assert_equal("abc", s) end - - def test_split_lookbehind - assert_equal([S("ab"), S("d")], S("abcd").split(/(?<=b)c/)) - assert_equal([S("ab"), S("d")], S("abcd").split(/b\Kc/)) - end - def test_squeeze assert_equal(S("abc"), S("aaabbbbccc").squeeze) assert_equal(S("aa bb cc"), S("aa bb cc").squeeze(S(" "))) @@ -1915,6 +1890,11 @@ CODE assert_equal(S("a\\&aba"), S("ababa").sub(/b/, '\\\\&')) assert_equal(S("a\\baba"), S("ababa").sub(/b/, '\\\\\&')) + a = S("hello") + a.taint + x = a.sub(/./, S('X')) + assert_predicate(x, :tainted?) + o = Object.new def o.to_str; "bar"; end assert_equal("fooBARbaz", "foobarbaz".sub(o, "BAR")) @@ -1962,6 +1942,11 @@ CODE a=S("hello") assert_nil(a.sub!(/X/, S('Y'))) + r = S('X') + r.taint + a.sub!(/./, r) + assert_predicate(a, :tainted?) + bug16105 = '[Bug #16105] heap-use-after-free' a = S("ABCDEFGHIJKLMNOPQRSTUVWXYZ012345678") b = a.dup @@ -2089,8 +2074,6 @@ CODE def test_swapcase assert_equal(S("hi&LOW"), S("HI&low").swapcase) - s = S("") - assert_not_same(s, s.swapcase) end def test_swapcase! @@ -2326,7 +2309,6 @@ CODE assert_equal(S("HELLO"), S("hello").upcase) assert_equal(S("HELLO"), S("HELLO").upcase) assert_equal(S("ABC HELLO 123"), S("abc HELLO 123").upcase) - assert_equal(S("H\0""ELLO"), S("H\0""ello").upcase) end def test_upcase! @@ -2339,12 +2321,6 @@ CODE a = S("HELLO") assert_nil(a.upcase!) assert_equal(S("HELLO"), a) - - a = S("H\0""ello") - b = a.dup - assert_equal(S("H\0""ELLO"), a.upcase!) - assert_equal(S("H\0""ELLO"), a) - assert_equal(S("H\0""ello"), b) end def test_upto @@ -2570,10 +2546,6 @@ CODE hello = "hello" hello.partition("hi").map(&:upcase!) assert_equal("hello", hello, bug) - - assert_equal(["", "", "foo"], "foo".partition(/^=*/)) - - assert_equal([S("ab"), S("c"), S("dbce")], S("abcdbce").partition(/b\Kc/)) end def test_rpartition @@ -2598,8 +2570,6 @@ CODE hello = "hello" hello.rpartition("hi").map(&:upcase!) assert_equal("hello", hello, bug) - - assert_equal([S("abcdb"), S("c"), S("e")], S("abcdbce").rpartition(/b\Kc/)) end def test_setter @@ -2667,7 +2637,6 @@ CODE assert_equal(1, "FoO".casecmp("BaR")) assert_equal(-1, "baR".casecmp("FoO")) assert_equal(1, "\u3042B".casecmp("\u3042a")) - assert_equal(-1, "foo".casecmp("foo\0")) assert_nil("foo".casecmp(:foo)) assert_nil("foo".casecmp(Object.new)) @@ -2682,7 +2651,6 @@ CODE assert_equal(false, 'FoO'.casecmp?('BaR')) assert_equal(false, 'baR'.casecmp?('FoO')) assert_equal(true, 'äöü'.casecmp?('ÄÖÜ')) - assert_equal(false, "foo".casecmp?("foo\0")) assert_nil("foo".casecmp?(:foo)) assert_nil("foo".casecmp?(Object.new)) @@ -3005,7 +2973,8 @@ CODE def test_ascii_incomat_inspect bug4081 = '[ruby-core:33283]' - WIDE_ENCODINGS.each do |e| + [Encoding::UTF_16LE, Encoding::UTF_16BE, + Encoding::UTF_32LE, Encoding::UTF_32BE].each do |e| assert_equal('"abc"', "abc".encode(e).inspect) assert_equal('"\\u3042\\u3044\\u3046"', "\u3042\u3044\u3046".encode(e).inspect) assert_equal('"ab\\"c"', "ab\"c".encode(e).inspect, bug4081) @@ -3152,38 +3121,6 @@ CODE assert_same(str, -bar, "uminus deduplicates [Feature #13077]") end - def test_uminus_frozen - # embedded - str1 = ("foobar" * 3).freeze - str2 = ("foobar" * 3).freeze - assert_not_same str1, str2 - assert_same str1, -str1 - assert_same str1, -str2 - - # regular - str1 = ("foobar" * 4).freeze - str2 = ("foobar" * 4).freeze - assert_not_same str1, str2 - assert_same str1, -str1 - assert_same str1, -str2 - end - - def test_uminus_no_freeze_not_bare - str = @cls.new("foo") - assert_instance_of(@cls, -str) - assert_equal(false, str.frozen?) - - str = @cls.new("foo") - str.instance_variable_set(:@iv, 1) - assert_instance_of(@cls, -str) - assert_equal(false, str.frozen?) - assert_equal(1, str.instance_variable_get(:@iv)) - - str = @cls.new("foo") - assert_instance_of(@cls, -str) - assert_equal(false, str.frozen?) - end - def test_ord assert_equal(97, "a".ord) assert_equal(97, "abc".ord) diff --git a/test/ruby/test_struct.rb b/test/ruby/test_struct.rb index c313ab0dbe..af68346442 100644 --- a/test/ruby/test_struct.rb +++ b/test/ruby/test_struct.rb @@ -23,10 +23,6 @@ module TestStruct test.bar = 47 assert_equal(47, test.bar) - - @Struct.class_eval do - remove_const :Test - end end # [ruby-dev:26247] more than 10 struct members causes segmentation fault @@ -64,10 +60,6 @@ module TestStruct assert_equal(1, o.a) end - def test_attrset_id - assert_raise(ArgumentError) { Struct.new(:x=) } - end - def test_members klass = @Struct.new(:a) o = klass.new(1) @@ -109,7 +101,6 @@ module TestStruct @Struct.new("KeywordInitFalse", :a, :b, keyword_init: false) assert_raise(ArgumentError) { @Struct::KeywordInitTrue.new(1, 2) } - assert_raise(ArgumentError) { @Struct::KeywordInitTrue.new({a: 100}, 2) } assert_nothing_raised { @Struct::KeywordInitFalse.new(1, 2) } assert_nothing_raised { @Struct::KeywordInitTrue.new(a: 1, b: 2) } assert_raise(ArgumentError) { @Struct::KeywordInitTrue.new(1, b: 2) } @@ -117,10 +108,6 @@ module TestStruct assert_equal @Struct::KeywordInitTrue.new(a: 1, b: 2).values, @Struct::KeywordInitFalse.new(1, 2).values assert_equal "#{@Struct}::KeywordInitFalse", @Struct::KeywordInitFalse.inspect assert_equal "#{@Struct}::KeywordInitTrue(keyword_init: true)", @Struct::KeywordInitTrue.inspect - # eval is needed to prevent the warning duplication filter - k = Class.new(@Struct::KeywordInitTrue) {def initialize(b, options); super(a: options, b: b); end} - o = assert_warn('') { k.new(42, {foo: 1, bar: 2}) } - assert_equal(1, o.a[:foo]) @Struct.instance_eval do remove_const(:KeywordInitTrue) @@ -128,16 +115,6 @@ module TestStruct end end - def test_struct_new_with_keyword_init_and_block - struct = @Struct.new(:a, :b, keyword_init: true) do - def c - a + b - end - end - - assert_equal(3, struct.new(a: 1, b: 2).c) - end - def test_initialize klass = @Struct.new(:a) assert_raise(ArgumentError) { klass.new(1, 2) } @@ -149,17 +126,6 @@ module TestStruct assert_equal 3, klass.new(1,2).total end - def test_initialize_with_kw - klass = @Struct.new(:foo, :options) do - def initialize(foo, **options) - super(foo, options) - end - end - assert_equal({}, klass.new(42, **Hash.new).options) - x = assert_warn('') { klass.new(1, bar: 2) } - assert_equal 2, x.options[:bar] - end - def test_each klass = @Struct.new(:a, :b) o = klass.new(1, 2) @@ -250,13 +216,6 @@ module TestStruct assert_raise(ArgumentError) { o.select(1) } end - def test_filter - klass = @Struct.new(:a, :b, :c, :d, :e, :f) - o = klass.new(1, 2, 3, 4, 5, 6) - assert_equal([1, 3, 5], o.filter {|v| v % 2 != 0 }) - assert_raise(ArgumentError) { o.filter(1) } - end - def test_big_struct klass1 = @Struct.new(*('a'..'z').map(&:to_sym)) o = klass1.new @@ -313,7 +272,6 @@ module TestStruct klass = @Struct.new(:a) o = klass.new(1) assert_kind_of(Integer, o.hash) - assert_kind_of(String, o.hash.to_s) end def test_eql @@ -339,19 +297,15 @@ module TestStruct end def test_redefinition_warning - @Struct.new(name = "RedefinitionWarning") + @Struct.new("RedefinitionWarning") e = EnvUtil.verbose_warning do @Struct.new("RedefinitionWarning") end assert_match(/redefining constant #@Struct::RedefinitionWarning/, e) - - @Struct.class_eval do - remove_const name - end end def test_nonascii - struct_test = @Struct.new(name = "R\u{e9}sum\u{e9}", :"r\u{e9}sum\u{e9}") + struct_test = @Struct.new("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) assert_equal("#<struct #@Struct::R\u{e9}sum\u{e9} r\u{e9}sum\u{e9}=42>", a.inspect, '[ruby-core:24849]') @@ -361,10 +315,6 @@ module TestStruct assert_nothing_raised(Encoding::CompatibilityError) do assert_match(/redefining constant #@Struct::R\u{e9}sum\u{e9}/, e) end - - @Struct.class_eval do - remove_const name - end end def test_junk @@ -409,13 +359,6 @@ module TestStruct assert_equal({a:1, b:2, c:3, d:4, e:5, f:6}, o.to_h) end - def test_to_h_block - klass = @Struct.new(:a, :b, :c, :d, :e, :f) - o = klass.new(1, 2, 3, 4, 5, 6) - assert_equal({"a" => 1, "b" => 4, "c" => 9, "d" => 16, "e" => 25, "f" => 36}, - o.to_h {|k, v| [k.to_s, v*v]}) - end - def test_question_mark_in_member klass = @Struct.new(:a, :b?) x = Object.new @@ -447,25 +390,13 @@ module TestStruct assert_nil(o.dig(:b, 0)) end - def test_new_duplicate + def test_new_dupilicate bug12291 = '[ruby-core:74971] [Bug #12291]' assert_raise_with_message(ArgumentError, /duplicate member/, bug12291) { @Struct.new(:a, :a) } end - def test_deconstruct_keys - klass = @Struct.new(:a, :b) - o = klass.new(1, 2) - assert_equal({a: 1, b: 2}, o.deconstruct_keys(nil)) - assert_equal({a: 1, b: 2}, o.deconstruct_keys([:b, :a])) - assert_equal({a: 1}, o.deconstruct_keys([:a])) - assert_not_send([o.deconstruct_keys([:a, :c]), :key?, :c]) - assert_raise(TypeError) { - o.deconstruct_keys(0) - } - end - class TopStruct < Test::Unit::TestCase include TestStruct diff --git a/test/ruby/test_super.rb b/test/ruby/test_super.rb index d94f4679d3..cf7580ab00 100644 --- a/test/ruby/test_super.rb +++ b/test/ruby/test_super.rb @@ -102,11 +102,11 @@ class TestSuper < Test::Unit::TestCase def test_optional2 assert_raise(ArgumentError) do # call Base#optional with 2 arguments; the 2nd arg is supplied - Optional2.new.optional(9) + assert_equal(9, Optional2.new.optional(9)) end assert_raise(ArgumentError) do # call Base#optional with 2 arguments - Optional2.new.optional(9, 2) + assert_equal(9, Optional2.new.optional(9, 2)) end end def test_optional3 @@ -307,29 +307,6 @@ class TestSuper < Test::Unit::TestCase end end - def test_super_in_instance_eval_in_module - super_class = EnvUtil.labeled_class("Super\u{30af 30e9 30b9}") { - def foo - return [:super, self] - end - } - mod = EnvUtil.labeled_module("Mod\u{30af 30e9 30b9}") { - def foo - x = Object.new - x.instance_eval do - super() - end - end - } - sub_class = EnvUtil.labeled_class("Sub\u{30af 30e9 30b9}", super_class) { - include mod - } - obj = sub_class.new - assert_raise_with_message(TypeError, /Sub\u{30af 30e9 30b9}/) do - obj.foo - end - end - def test_super_in_orphan_block super_class = EnvUtil.labeled_class("Super\u{30af 30e9 30b9}") { def foo @@ -583,81 +560,4 @@ class TestSuper < Test::Unit::TestCase def test_super_with_modified_rest_parameter assert_equal [13], TestFor_super_with_modified_rest_parameter.new.foo end - - def test_super_with_define_method - superklass1 = Class.new do - def foo; :foo; end - def bar; :bar; end - def boo; :boo; end - end - superklass2 = Class.new(superklass1) do - alias baz boo - def boo; :boo2; end - end - subklass = Class.new(superklass2) - [:foo, :bar, :baz, :boo].each do |sym| - subklass.define_method(sym){ super() } - end - assert_equal :foo, subklass.new.foo - assert_equal :bar, subklass.new.bar - assert_equal :boo, subklass.new.baz - assert_equal :boo2, subklass.new.boo - end - - def test_super_attr_writer # [Bug #16785] - writer_class = Class.new do - attr_writer :test - end - superwriter_class = Class.new(writer_class) do - def initialize - @test = 1 # index: 1 - end - - def test=(test) - super(test) - end - end - inherited_class = Class.new(superwriter_class) do - def initialize - @a = nil - @test = 2 # index: 2 - end - end - - superwriter = superwriter_class.new - superwriter.test = 3 # set ic->index of superwriter_class#test= to 1 - - inherited = inherited_class.new - inherited.test = 4 # it may set 4 to index=1 while it should be index=2 - - assert_equal 3, superwriter.instance_variable_get(:@test) - assert_equal 4, inherited.instance_variable_get(:@test) - end - - def test_super_attr_reader - reader_class = Class.new do - attr_reader :test - end - superreader_class = Class.new(reader_class) do - def initialize - @test = 1 # index: 1 - end - - def test - super - end - end - inherited_class = Class.new(superreader_class) do - def initialize - @a = nil - @test = 2 # index: 2 - end - end - - superreader = superreader_class.new - assert_equal 1, superreader.test # set ic->index of superreader_class#test to 1 - - inherited = inherited_class.new - assert_equal 2, inherited.test # it may read index=1 while it should be index=2 - end end diff --git a/test/ruby/test_symbol.rb b/test/ruby/test_symbol.rb index f7f17b8d67..36cbf4a710 100644 --- a/test/ruby/test_symbol.rb +++ b/test/ruby/test_symbol.rb @@ -105,12 +105,6 @@ class TestSymbol < Test::Unit::TestCase end end - def test_name - assert_equal("foo", :foo.name) - assert_same(:foo.name, :foo.name) - assert_predicate(:foo.name, :frozen?) - end - def test_to_proc assert_equal %w(1 2 3), (1..3).map(&:to_s) [ @@ -159,14 +153,6 @@ class TestSymbol < Test::Unit::TestCase end; end - def test_to_proc_lambda? - assert_predicate(:itself.to_proc, :lambda?) - end - - def test_to_proc_arity - assert_equal(-2, :itself.to_proc.arity) - end - def test_to_proc_call_with_symbol_proc first = 1 bug11594 = "[ruby-core:71088] [Bug #11594] corrupted the first local variable" @@ -175,53 +161,6 @@ class TestSymbol < Test::Unit::TestCase assert_equal(1, first, bug11594) end - class TestToPRocArgWithRefinements; end - def _test_to_proc_arg_with_refinements_call(&block) - block.call TestToPRocArgWithRefinements.new - end - def _test_to_proc_with_refinements_call(&block) - block - end - using Module.new { - refine TestToPRocArgWithRefinements do - def hoge - :hoge - end - end - } - def test_to_proc_arg_with_refinements - assert_equal(:hoge, _test_to_proc_arg_with_refinements_call(&:hoge)) - end - - def test_to_proc_lambda_with_refinements - assert_predicate(_test_to_proc_with_refinements_call(&:hoge), :lambda?) - end - - def test_to_proc_arity_with_refinements - assert_equal(-2, _test_to_proc_with_refinements_call(&:hoge).arity) - end - - def self._test_to_proc_arg_with_refinements_call(&block) - block.call TestToPRocArgWithRefinements.new - end - _test_to_proc_arg_with_refinements_call(&:hoge) - using Module.new { - refine TestToPRocArgWithRefinements do - def hoge - :hogehoge - end - end - } - def test_to_proc_arg_with_refinements_override - assert_equal(:hogehoge, _test_to_proc_arg_with_refinements_call(&:hoge)) - end - - def test_to_proc_arg_with_refinements_undefined - assert_raise(NoMethodError) do - _test_to_proc_arg_with_refinements_call(&:foo) - end - end - private def return_from_proc Proc.new { return 1 }.tap(&:call) end @@ -244,11 +183,11 @@ class TestSymbol < Test::Unit::TestCase begin; bug11845 = '[ruby-core:72381] [Bug #11845]' assert_nil(:class.to_proc.source_location, bug11845) - assert_equal([[:req], [:rest]], :class.to_proc.parameters, bug11845) + assert_equal([[:rest]], :class.to_proc.parameters, bug11845) c = Class.new {define_method(:klass, :class.to_proc)} m = c.instance_method(:klass) assert_nil(m.source_location, bug11845) - assert_equal([[:req], [:rest]], m.parameters, bug11845) + assert_equal([[:rest]], m.parameters, bug11845) end; end @@ -529,14 +468,12 @@ class TestSymbol < Test::Unit::TestCase assert_nothing_raised(NoMethodError, bug10259) {obj.send("unagi=".intern, 1)} end - def test_symbol_fstr_memory_leak + def test_symbol_fstr_leak bug10686 = '[ruby-core:67268] [Bug #10686]' - assert_no_memory_leak([], "#{<<~"begin;"}\n#{<<~'else;'}", "#{<<~'end;'}", bug10686, limit: 1.71, rss: true, timeout: 20) + x = x = 0 + assert_no_memory_leak([], '200_000.times { |i| i.to_s.to_sym }; GC.start', "#{<<-"begin;"}\n#{<<-"end;"}", bug10686, limit: 1.71, rss: true, timeout: 20) begin; - n = 100_000 - n.times { |i| i.to_s.to_sym } - else; - (2 * n).times { |i| (i + n).to_s.to_sym } + 200_000.times { |i| (i + 200_000).to_s.to_sym } end; end @@ -560,6 +497,14 @@ class TestSymbol < Test::Unit::TestCase end; end + def test_not_freeze + bug11721 = '[ruby-core:71611] [Bug #11721]' + str = "\u{1f363}".taint + assert_not_predicate(str, :frozen?) + assert_equal str, str.to_sym.to_s + assert_not_predicate(str, :frozen?, bug11721) + end + def test_hash_nondeterministic ruby = EnvUtil.rubybin assert_not_equal :foo.hash, `#{ruby} -e 'puts :foo.hash'`.to_i, @@ -582,27 +527,4 @@ class TestSymbol < Test::Unit::TestCase puts :a == :a RUBY end - - def test_start_with? - assert_equal(true, :hello.start_with?("hel")) - assert_equal(false, :hello.start_with?("el")) - assert_equal(true, :hello.start_with?("el", "he")) - - bug5536 = '[ruby-core:40623]' - assert_raise(TypeError, bug5536) {:str.start_with? :not_convertible_to_string} - - assert_equal(true, :hello.start_with?(/hel/)) - assert_equal("hel", $&) - assert_equal(false, :hello.start_with?(/el/)) - assert_nil($&) - end - - def test_end_with? - assert_equal(true, :hello.end_with?("llo")) - assert_equal(false, :hello.end_with?("ll")) - assert_equal(true, :hello.end_with?("el", "lo")) - - bug5536 = '[ruby-core:40623]' - assert_raise(TypeError, bug5536) {:str.end_with? :not_convertible_to_string} - end end diff --git a/test/ruby/test_syntax.rb b/test/ruby/test_syntax.rb index e289eea2c2..f8d28a4f8e 100644 --- a/test/ruby/test_syntax.rb +++ b/test/ruby/test_syntax.rb @@ -46,7 +46,7 @@ class TestSyntax < Test::Unit::TestCase assert_raise(ArgumentError, enc.name) {load(f.path)} end ensure - f&.close! + f.close! if f end def test_script_lines @@ -63,7 +63,7 @@ class TestSyntax < Test::Unit::TestCase end end ensure - f&.close! + f.close! if f end def test_newline_in_block_parameters @@ -93,51 +93,6 @@ class TestSyntax < Test::Unit::TestCase assert_valid_syntax("tap (proc do end)", __FILE__, bug9726) end - def test_hash_kwsplat_hash - kw = {} - h = {a: 1} - assert_equal({}, {**{}}) - assert_equal({}, {**kw}) - assert_equal(h, {**h}) - assert_equal(false, {**{}}.frozen?) - assert_equal(false, {**kw}.equal?(kw)) - assert_equal(false, {**h}.equal?(h)) - end - - def test_array_kwsplat_hash - kw = {} - h = {a: 1} - assert_equal([], [**{}]) - assert_equal([], [**kw]) - assert_equal([h], [**h]) - assert_equal([{}], [{}]) - assert_equal([kw], [kw]) - assert_equal([h], [h]) - - assert_equal([1], [1, **{}]) - assert_equal([1], [1, **kw]) - assert_equal([1, h], [1, **h]) - assert_equal([1, {}], [1, {}]) - assert_equal([1, kw], [1, kw]) - assert_equal([1, h], [1, h]) - - assert_equal([], [**kw, **kw]) - assert_equal([], [**kw, **{}, **kw]) - assert_equal([1], [1, **kw, **{}, **kw]) - - assert_equal([{}], [{}, **kw, **kw]) - assert_equal([kw], [kw, **kw, **kw]) - assert_equal([h], [h, **kw, **kw]) - assert_equal([h, h], [h, **kw, **kw, **h]) - - assert_equal([h, {:a=>2}], [h, **{}, **h, a: 2]) - assert_equal([h, h], [h, **{}, a: 2, **h]) - assert_equal([h, h], [h, a: 2, **{}, **h]) - assert_equal([h, h], [h, a: 2, **h, **{}]) - assert_equal([h, {:a=>2}], [h, **h, a: 2, **{}]) - assert_equal([h, {:a=>2}], [h, **h, **{}, a: 2]) - end - def test_normal_argument assert_valid_syntax('def foo(x) end') assert_syntax_error('def foo(X) end', /constant/) @@ -193,7 +148,7 @@ class TestSyntax < Test::Unit::TestCase h = {k3: 31} assert_raise(ArgumentError) {o.kw(**h)} h = {"k1"=>11, k2: 12} - assert_raise(ArgumentError) {o.kw(**h)} + assert_raise(TypeError) {o.kw(**h)} end def test_keyword_duplicated @@ -208,7 +163,7 @@ class TestSyntax < Test::Unit::TestCase assert_equal([1, 2], a, bug10315) a.clear r = nil - assert_warn(/duplicated/) {r = eval("a.f(**{k: a.add(1), k: a.add(2)})")} + assert_warn(/duplicated/) {r = eval("a.f({k: a.add(1), k: a.add(2)})")} assert_equal(2, r) assert_equal([1, 2], a, bug10315) end @@ -232,25 +187,33 @@ class TestSyntax < Test::Unit::TestCase end def test_keyword_self_reference - message = /circular argument reference - var/ - assert_syntax_error("def foo(var: defined?(var)) var end", message) - assert_syntax_error("def foo(var: var) var end", message) - assert_syntax_error("def foo(var: bar(var)) var end", message) - assert_syntax_error("def foo(var: bar {var}) var end", message) + bug9593 = '[ruby-core:61299] [Bug #9593]' + o = Object.new + assert_warn(/circular argument reference - var/) do + o.instance_eval("def foo(var: defined?(var)) var end") + end + assert_equal(42, o.foo(var: 42)) + assert_equal("local-variable", o.foo, bug9593) o = Object.new - assert_warn("") do - o.instance_eval("def foo(var: bar {|var| var}) var end") + assert_warn(/circular argument reference - var/) do + o.instance_eval("def foo(var: var) var end") end + assert_nil(o.foo, bug9593) o = Object.new - assert_warn("") do - o.instance_eval("def foo(var: bar {| | var}) var end") + assert_warn(/circular argument reference - var/) do + o.instance_eval("def foo(var: bar(var)) var end") + end + + o = Object.new + assert_warn(/circular argument reference - var/) do + o.instance_eval("def foo(var: bar {var}) var end") end o = Object.new assert_warn("") do - o.instance_eval("def foo(var: bar {|| var}) var end") + o.instance_eval("def foo(var: bar {|var| var}) var end") end o = Object.new @@ -267,55 +230,56 @@ class TestSyntax < Test::Unit::TestCase def test_keyword_invalid_name bug11663 = '[ruby-core:71356] [Bug #11663]' - assert_syntax_error('def foo(arg1?:) end', /arg1\?/, bug11663) - assert_syntax_error('def foo(arg1?:, arg2:) end', /arg1\?/, bug11663) + o = o = Object.new + assert_syntax_error('def o.foo(arg1?:) end', /arg1\?/, bug11663) + assert_syntax_error('def o.foo(arg1?:, arg2:) end', /arg1\?/, bug11663) assert_syntax_error('proc {|arg1?:|}', /arg1\?/, bug11663) assert_syntax_error('proc {|arg1?:, arg2:|}', /arg1\?/, bug11663) bug10545 = '[ruby-dev:48742] [Bug #10545]' - assert_syntax_error('def foo(FOO: a) end', /constant/, bug10545) - assert_syntax_error('def foo(@foo: a) end', /instance variable/) - assert_syntax_error('def foo(@@foo: a) end', /class variable/) + assert_syntax_error('def o.foo(FOO: a) end', /constant/, bug10545) + assert_syntax_error('def o.foo(@foo: a) end', /instance variable/) + assert_syntax_error('def o.foo(@@foo: a) end', /class variable/) end - def test_keywords_specified_and_not_accepted - assert_syntax_error('def foo(a:, **nil) end', /unexpected/) - assert_syntax_error('def foo(a:, **nil, &b) end', /unexpected/) - assert_syntax_error('def foo(**a, **nil) end', /unexpected/) - assert_syntax_error('def foo(**a, **nil, &b) end', /unexpected/) - assert_syntax_error('def foo(**nil, **a) end', /unexpected/) - assert_syntax_error('def foo(**nil, **a, &b) end', /unexpected/) + def test_optional_self_reference + bug9593 = '[ruby-core:61299] [Bug #9593]' + o = Object.new + assert_warn(/circular argument reference - var/) do + o.instance_eval("def foo(var = defined?(var)) var end") + end + assert_equal(42, o.foo(42)) + assert_equal("local-variable", o.foo, bug9593) + + o = Object.new + assert_warn(/circular argument reference - var/) do + o.instance_eval("def foo(var = var) var end") + end + assert_nil(o.foo, bug9593) - assert_syntax_error('proc do |a:, **nil| end', /unexpected/) - assert_syntax_error('proc do |a:, **nil, &b| end', /unexpected/) - assert_syntax_error('proc do |**a, **nil| end', /unexpected/) - assert_syntax_error('proc do |**a, **nil, &b| end', /unexpected/) - assert_syntax_error('proc do |**nil, **a| end', /unexpected/) - assert_syntax_error('proc do |**nil, **a, &b| end', /unexpected/) - end + o = Object.new + assert_warn(/circular argument reference - var/) do + o.instance_eval("def foo(var = bar(var)) var end") + end - def test_optional_self_reference - message = /circular argument reference - var/ - assert_syntax_error("def foo(var = defined?(var)) var end", message) - assert_syntax_error("def foo(var = var) var end", message) - assert_syntax_error("def foo(var = bar(var)) var end", message) - assert_syntax_error("def foo(var = bar {var}) var end", message) - assert_syntax_error("def foo(var = (def bar;end; var)) var end", message) - assert_syntax_error("def foo(var = (def self.bar;end; var)) var end", message) + o = Object.new + assert_warn(/circular argument reference - var/) do + o.instance_eval("def foo(var = bar {var}) var end") + end o = Object.new - assert_warn("") do - o.instance_eval("def foo(var = bar {|var| var}) var end") + assert_warn(/circular argument reference - var/) do + o.instance_eval("def foo(var = (def bar;end; var)) var end") end o = Object.new - assert_warn("") do - o.instance_eval("def foo(var = bar {| | var}) var end") + assert_warn(/circular argument reference - var/) do + o.instance_eval("def foo(var = (def self.bar;end; var)) var end") end o = Object.new assert_warn("") do - o.instance_eval("def foo(var = bar {|| var}) var end") + o.instance_eval("def foo(var = bar {|var| var}) var end") end o = Object.new @@ -442,30 +406,21 @@ WARN def test_duplicated_arg assert_syntax_error("def foo(a, a) end", /duplicated argument name/) assert_valid_syntax("def foo(_, _) end") - (obj = Object.new).instance_eval("def foo(_, x, _) x end") - assert_equal(2, obj.foo(1, 2, 3)) end def test_duplicated_rest assert_syntax_error("def foo(a, *a) end", /duplicated argument name/) assert_valid_syntax("def foo(_, *_) end") - (obj = Object.new).instance_eval("def foo(_, x, *_) x end") - assert_equal(2, obj.foo(1, 2, 3)) end def test_duplicated_opt assert_syntax_error("def foo(a, a=1) end", /duplicated argument name/) assert_valid_syntax("def foo(_, _=1) end") - (obj = Object.new).instance_eval("def foo(_, x, _=42) x end") - assert_equal(2, obj.foo(1, 2)) end def test_duplicated_opt_rest assert_syntax_error("def foo(a=1, *a) end", /duplicated argument name/) assert_valid_syntax("def foo(_=1, *_) end") - (obj = Object.new).instance_eval("def foo(_, x=42, *_) x end") - assert_equal(42, obj.foo(1)) - assert_equal(2, obj.foo(1, 2)) end def test_duplicated_rest_opt @@ -474,85 +429,46 @@ WARN def test_duplicated_rest_post assert_syntax_error("def foo(*a, a) end", /duplicated argument name/) - assert_valid_syntax("def foo(*_, _) end") - (obj = Object.new).instance_eval("def foo(*_, x, _) x end") - assert_equal(2, obj.foo(1, 2, 3)) - assert_equal(2, obj.foo(2, 3)) - (obj = Object.new).instance_eval("def foo(*_, _, x) x end") - assert_equal(3, obj.foo(1, 2, 3)) - assert_equal(3, obj.foo(2, 3)) end def test_duplicated_opt_post assert_syntax_error("def foo(a=1, a) end", /duplicated argument name/) assert_valid_syntax("def foo(_=1, _) end") - (obj = Object.new).instance_eval("def foo(_=1, x, _) x end") - assert_equal(2, obj.foo(1, 2, 3)) - assert_equal(2, obj.foo(2, 3)) - (obj = Object.new).instance_eval("def foo(_=1, _, x) x end") - assert_equal(3, obj.foo(1, 2, 3)) - assert_equal(3, obj.foo(2, 3)) end def test_duplicated_kw assert_syntax_error("def foo(a, a: 1) end", /duplicated argument name/) assert_valid_syntax("def foo(_, _: 1) end") - (obj = Object.new).instance_eval("def foo(_, x, _: 1) x end") - assert_equal(3, obj.foo(2, 3)) - assert_equal(3, obj.foo(2, 3, _: 42)) - (obj = Object.new).instance_eval("def foo(x, _, _: 1) x end") - assert_equal(2, obj.foo(2, 3)) - assert_equal(2, obj.foo(2, 3, _: 42)) end def test_duplicated_rest_kw assert_syntax_error("def foo(*a, a: 1) end", /duplicated argument name/) assert_nothing_raised {def foo(*_, _: 1) end} - (obj = Object.new).instance_eval("def foo(*_, x: 42, _: 1) x end") - assert_equal(42, obj.foo(42)) - assert_equal(42, obj.foo(2, _: 0)) - assert_equal(2, obj.foo(x: 2, _: 0)) end def test_duplicated_opt_kw assert_syntax_error("def foo(a=1, a: 1) end", /duplicated argument name/) assert_valid_syntax("def foo(_=1, _: 1) end") - (obj = Object.new).instance_eval("def foo(_=42, x, _: 1) x end") - assert_equal(0, obj.foo(0)) - assert_equal(0, obj.foo(0, _: 3)) end def test_duplicated_kw_kwrest assert_syntax_error("def foo(a: 1, **a) end", /duplicated argument name/) assert_valid_syntax("def foo(_: 1, **_) end") - (obj = Object.new).instance_eval("def foo(_: 1, x: 42, **_) x end") - assert_equal(42, obj.foo()) - assert_equal(42, obj.foo(a: 0)) - assert_equal(42, obj.foo(_: 0, a: 0)) - assert_equal(1, obj.foo(_: 0, x: 1, a: 0)) end def test_duplicated_rest_kwrest assert_syntax_error("def foo(*a, **a) end", /duplicated argument name/) assert_valid_syntax("def foo(*_, **_) end") - (obj = Object.new).instance_eval("def foo(*_, x, **_) x end") - assert_equal(1, obj.foo(1)) - assert_equal(1, obj.foo(1, a: 0)) - assert_equal(2, obj.foo(1, 2, a: 0)) end def test_duplicated_opt_kwrest assert_syntax_error("def foo(a=1, **a) end", /duplicated argument name/) assert_valid_syntax("def foo(_=1, **_) end") - (obj = Object.new).instance_eval("def foo(_=42, x, **_) x end") - assert_equal(1, obj.foo(1)) - assert_equal(1, obj.foo(1, a: 0)) - assert_equal(1, obj.foo(0, 1, a: 0)) end def test_duplicated_when - w = 'warning: duplicated `when\' clause with line 3 is ignored' - assert_warning(/3: #{w}.+4: #{w}.+4: #{w}.+5: #{w}.+5: #{w}/m) { + w = 'warning: duplicated when clause is ignored' + assert_warning(/3: #{w}.+4: #{w}.+4: #{w}.+5: #{w}.+5: #{w}/m){ eval %q{ case 1 when 1, 1 @@ -561,7 +477,7 @@ WARN end } } - assert_warning(/#{w}/) {#/3: #{w}.+4: #{w}.+5: #{w}.+5: #{w}/m){ + assert_warning(/#{w}/){#/3: #{w}.+4: #{w}.+5: #{w}.+5: #{w}/m){ a = a = 1 eval %q{ case 1 @@ -573,17 +489,6 @@ WARN } end - def test_duplicated_when_check_option - w = /duplicated `when\' clause with line 3 is ignored/ - assert_in_out_err(%[-wc], "#{<<~"begin;"}\n#{<<~'end;'}", ["Syntax OK"], w) - begin; - case 1 - when 1 - when 1 - end - end; - end - def test_invalid_break assert_syntax_error("def m; break; end", /Invalid break/) assert_syntax_error('/#{break}/', /Invalid break/) @@ -619,11 +524,6 @@ WARN def test_do_block_after_lambda bug11380 = '[ruby-core:70067] [Bug #11380]' assert_valid_syntax('p -> { :hello }, a: 1 do end', bug11380) - - assert_valid_syntax('->(opt = (foo.[] bar)) {}') - assert_valid_syntax('->(opt = (foo.[]= bar)) {}') - assert_valid_syntax('->(opt = (foo.[] bar)) do end') - assert_valid_syntax('->(opt = (foo.[]= bar)) do end') end def test_reserved_method_no_args @@ -634,7 +534,7 @@ WARN def test_unassignable gvar = global_variables %w[self nil true false __FILE__ __LINE__ __ENCODING__].each do |kwd| - assert_syntax_error("#{kwd} = nil", /Can't .* #{kwd}$/) + assert_raise(SyntaxError) {eval("#{kwd} = nil")} assert_equal(gvar, global_variables) end end @@ -794,8 +694,6 @@ e" \ TEXT end; - - assert_equal(" TEXT\n", eval("<<~eos\n" " \\\n" "TEXT\n" "eos\n")) end def test_lineno_after_heredoc @@ -813,44 +711,33 @@ eom assert_syntax_error('<<~ "#{}"', /unexpected <</) end - def test_dedented_heredoc_concatenation - assert_equal("\n0\n1", eval("<<~0 '1'\n \n0\#{}\n0")) - end - def test_heredoc_mixed_encoding - e = assert_syntax_error(<<-'HEREDOC', 'UTF-8 mixed within Windows-31J source') + assert_syntax_error(<<-'HEREDOC', 'UTF-8 mixed within Windows-31J source') #encoding: cp932 <<-TEXT \xe9\x9d\u1234 TEXT HEREDOC - assert_not_match(/end-of-input/, e.message) - - e = assert_syntax_error(<<-'HEREDOC', 'UTF-8 mixed within Windows-31J source') + assert_syntax_error(<<-'HEREDOC', 'UTF-8 mixed within Windows-31J source') #encoding: cp932 <<-TEXT \xe9\x9d \u1234 TEXT HEREDOC - assert_not_match(/end-of-input/, e.message) - - e = assert_syntax_error(<<-'HEREDOC', 'UTF-8 mixed within Windows-31J source') + assert_syntax_error(<<-'HEREDOC', 'UTF-8 mixed within Windows-31J source') #encoding: cp932 <<-TEXT \u1234\xe9\x9d TEXT HEREDOC - assert_not_match(/end-of-input/, e.message) - - e = assert_syntax_error(<<-'HEREDOC', 'UTF-8 mixed within Windows-31J source') + assert_syntax_error(<<-'HEREDOC', 'UTF-8 mixed within Windows-31J source') #encoding: cp932 <<-TEXT \u1234 \xe9\x9d TEXT HEREDOC - assert_not_match(/end-of-input/, e.message) end def test_lineno_operation_brace_block @@ -942,20 +829,9 @@ eom assert_syntax_error("puts <<""EOS\n""ng\n""EOS\r""NO\n", /can't find string "EOS" anywhere before EOF/) end - def test_heredoc_no_terminator - assert_syntax_error("puts <<""A\n", /can't find string "A" anywhere before EOF/) - assert_syntax_error("puts <<""A + <<""B\n", /can't find string "A" anywhere before EOF/) - assert_syntax_error("puts <<""A + <<""B\n", /can't find string "B" anywhere before EOF/) - end - - def test_unterminated_heredoc - assert_syntax_error("<<\"EOS\n\nEOS\n", /unterminated/) - assert_syntax_error("<<\"EOS\n\"\nEOS\n", /unterminated/) - end - - def test_unterminated_heredoc_cr - %W[\r\n \n].each do |nl| - assert_syntax_error("<<\"\r\"#{nl}\r#{nl}", /unterminated/, nil, "CR with #{nl.inspect}") + def test_heredoc_newline + assert_warn(/ends with a newline/) do + eval("<<\"EOS\n\"\nEOS\n") end end @@ -965,14 +841,9 @@ eom def test_warning_for_cr feature8699 = '[ruby-core:56240] [Feature #8699]' - s = assert_warning(/encountered \\r/, feature8699) do - eval("'\r'\r") - end - assert_equal("\r", s) - s = assert_warning('') do - eval("'\r'\r\n") + assert_warning(/encountered \\r/, feature8699) do + eval("\r""__id__\r") end - assert_equal("\r", s) end def test_unexpected_fraction @@ -994,28 +865,8 @@ eom bug10957 = '[ruby-core:68477] [Bug #10957]' assert_ruby_status(['-c', '-e', 'p ()..0'], "", bug10957) assert_ruby_status(['-c', '-e', 'p ()...0'], "", bug10957) - assert_syntax_error('0..%q.', /unterminated string/, bug10957) - assert_syntax_error('0...%q.', /unterminated string/, bug10957) - end - - def test_range_at_eol - assert_warn(/\.\.\. at EOL/) {eval("1...\n2")} - assert_warn('') {eval("(1...)")} - assert_warn('') {eval("(1...\n2)")} - assert_warn('') {eval("{a: 1...\n2}")} - - assert_warn(/\.\.\. at EOL/) do - assert_valid_syntax('foo.[]= ...', verbose: true) - end - assert_warn(/\.\.\. at EOL/) do - assert_valid_syntax('foo.[] ...', verbose: true) - end - assert_warn(/\.\.\. at EOL/) do - assert_syntax_error('foo.[]= bar, ...', /unexpected/, verbose: true) - end - assert_warn(/\.\.\. at EOL/) do - assert_syntax_error('foo.[] bar, ...', /unexpected/, verbose: true) - end + assert_syntax_error('0..%w.', /unterminated string/, bug10957) + assert_syntax_error('0...%w.', /unterminated string/, bug10957) end def test_too_big_nth_ref @@ -1031,21 +882,9 @@ eom assert_syntax_error(":#\n foo", /unexpected ':'/) end - def test_invalid_literal_message - assert_syntax_error("def :foo", /unexpected symbol literal/) - assert_syntax_error("def 'foo'", /unexpected string literal/) - end - def test_fluent_dot assert_valid_syntax("a\n.foo") assert_valid_syntax("a\n&.foo") - assert_valid_syntax("a #\n#\n.foo\n") - assert_valid_syntax("a #\n#\n&.foo\n") - end - - def test_safe_call_in_massign_lhs - assert_syntax_error("*a&.x=0", /multiple assignment destination/) - assert_syntax_error("a&.x,=0", /multiple assignment destination/) end def test_no_warning_logop_literal @@ -1067,6 +906,9 @@ eom assert_warn(/literal in condition/) do eval('1 if //') end + assert_warn(/literal in condition/) do + eval('1 if true..false') + end assert_warning(/literal in condition/) do eval('1 if 1') end @@ -1097,27 +939,6 @@ eom end end - def test_warning_literal_in_flip_flop - assert_warn(/literal in flip-flop/) do - eval('1 if ""..false') - end - assert_warning(/literal in flip-flop/) do - eval('1 if :foo..false') - end - assert_warning(/literal in flip-flop/) do - eval('1 if :"#{"foo".upcase}"..false') - end - assert_warn(/literal in flip-flop/) do - eval('1 if ""...false') - end - assert_warning(/literal in flip-flop/) do - eval('1 if :foo...false') - end - assert_warning(/literal in flip-flop/) do - eval('1 if :"#{"foo".upcase}"...false') - end - end - def test_alias_symbol bug8851 = '[ruby-dev:47681] [Bug #8851]' formats = ['%s', ":'%s'", ':"%s"', '%%s(%s)'] @@ -1143,7 +964,7 @@ eom end def test_parenthesised_statement_argument - assert_syntax_error("foo(bar rescue nil)", /unexpected `rescue' modifier/) + assert_syntax_error("foo(bar rescue nil)", /unexpected modifier_rescue/) assert_valid_syntax("foo (bar rescue nil)") end @@ -1273,14 +1094,6 @@ eom end end - def test_return_toplevel_with_argument - assert_warn(/argument of top-level return is ignored/) {eval("return 1")} - end - - def test_return_in_proc_in_class - assert_in_out_err(['-e', 'class TestSyntax; proc{ return }.call; end'], "", [], /^-e:1:.*unexpected return \(LocalJumpError\)/) - end - def test_syntax_error_in_rescue bug12613 = '[ruby-core:76531] [Bug #12613]' assert_syntax_error("#{<<-"begin;"}\n#{<<-"end;"}", /Invalid retry/, bug12613) @@ -1298,12 +1111,6 @@ eom end; end - def test_syntax_error_at_newline - expected = "\n ^" - assert_syntax_error("%[abcdef", expected) - assert_syntax_error("%[abcdef\n", expected) - end - def test_invalid_jump assert_in_out_err(%w[-e redo], "", [], /^-e:1: /) end @@ -1379,24 +1186,6 @@ eom assert_equal(:begin, result) end - def test_rescue_do_end_ensure_in_lambda - result = [] - eval("#{<<-"begin;"}\n#{<<-"end;"}") - begin; - -> do - result << :begin - raise "An exception occurred!" - rescue - result << :rescue - else - result << :else - ensure - result << :ensure - end.call - end; - assert_equal([:begin, :rescue, :ensure], result) - end - def test_return_in_loop obj = Object.new def obj.test @@ -1406,330 +1195,6 @@ eom assert_nil obj.test end - def test_assignment_return_in_loop - obj = Object.new - def obj.test - x = nil - _y = (return until x unless x) - end - assert_nil obj.test, "[Bug #16695]" - end - - def test_method_call_location - line = __LINE__+5 - e = assert_raise(NoMethodError) do - 1.upto(0) do - end - . - foo( - 1, - 2, - ) - end - assert_equal(line, e.backtrace_locations[0].lineno) - - line = __LINE__+5 - e = assert_raise(NoMethodError) do - 1.upto 0 do - end - . - foo( - 1, - 2, - ) - end - assert_equal(line, e.backtrace_locations[0].lineno) - end - - def test_methoddef_endless - assert_valid_syntax('private def foo = 42') - assert_valid_syntax('private def foo() = 42') - assert_valid_syntax('private def inc(x) = x + 1') - assert_valid_syntax('private def obj.foo = 42') - assert_valid_syntax('private def obj.foo() = 42') - assert_valid_syntax('private def obj.inc(x) = x + 1') - k = Class.new do - class_eval('def rescued(x) = raise("to be caught") rescue "instance #{x}"') - class_eval('def self.rescued(x) = raise("to be caught") rescue "class #{x}"') - end - assert_equal("class ok", k.rescued("ok")) - assert_equal("instance ok", k.new.rescued("ok")) - - error = /setter method cannot be defined in an endless method definition/ - assert_syntax_error('def foo=() = 42', error) - assert_syntax_error('def obj.foo=() = 42', error) - assert_syntax_error('def foo=() = 42 rescue nil', error) - assert_syntax_error('def obj.foo=() = 42 rescue nil', error) - end - - def test_methoddef_in_cond - assert_valid_syntax('while def foo; tap do end; end; break; end') - assert_valid_syntax('while def foo a = tap do end; end; break; end') - end - - def test_classdef_in_cond - assert_valid_syntax('while class Foo; tap do end; end; break; end') - assert_valid_syntax('while class Foo a = tap do end; end; break; end') - end - - def test_command_with_cmd_brace_block - assert_valid_syntax('obj.foo (1) {}') - assert_valid_syntax('obj::foo (1) {}') - end - - def test_numbered_parameter - assert_valid_syntax('proc {_1}') - assert_equal(3, eval('[1,2].then {_1+_2}')) - assert_equal("12", eval('[1,2].then {"#{_1}#{_2}"}')) - assert_equal([1, 2], eval('[1,2].then {_1}')) - assert_equal(3, eval('->{_1+_2}.call(1,2)')) - assert_equal(4, eval('->(a=->{_1}){a}.call.call(4)')) - assert_equal(5, eval('-> a: ->{_1} {a}.call.call(5)')) - assert_syntax_error('proc {|| _1}', /ordinary parameter is defined/) - assert_syntax_error('proc {|;a| _1}', /ordinary parameter is defined/) - assert_syntax_error("proc {|\n| _1}", /ordinary parameter is defined/) - assert_syntax_error('proc {|x| _1}', /ordinary parameter is defined/) - assert_syntax_error('proc {_1; proc {_2}}', /numbered parameter is already used/) - assert_syntax_error('proc {proc {_1}; _2}', /numbered parameter is already used/) - assert_syntax_error('->(){_1}', /ordinary parameter is defined/) - assert_syntax_error('->(x){_1}', /ordinary parameter is defined/) - assert_syntax_error('->x{_1}', /ordinary parameter is defined/) - assert_syntax_error('->x:_2{}', /ordinary parameter is defined/) - assert_syntax_error('->x=_1{}', /ordinary parameter is defined/) - assert_syntax_error('-> {_1; -> {_2}}', /numbered parameter is already used/) - assert_syntax_error('-> {-> {_1}; _2}', /numbered parameter is already used/) - assert_syntax_error('proc {_1; _1 = nil}', /Can't assign to numbered parameter _1/) - assert_syntax_error('proc {_1 = nil}', /_1 is reserved for numbered parameter/) - assert_syntax_error('_2=1', /_2 is reserved for numbered parameter/) - assert_syntax_error('proc {|_3|}', /_3 is reserved for numbered parameter/) - assert_syntax_error('def x(_4) end', /_4 is reserved for numbered parameter/) - assert_syntax_error('def _5; end', /_5 is reserved for numbered parameter/) - assert_syntax_error('def self._6; end', /_6 is reserved for numbered parameter/) - assert_raise_with_message(NameError, /undefined local variable or method `_1'/) { - eval('_1') - } - ['class C', 'class << C', 'module M', 'def m', 'def o.m'].each do |c| - assert_valid_syntax("->{#{c};->{_1};end;_1}\n") - assert_valid_syntax("->{_1;#{c};->{_1};end}\n") - end - - 1.times { - [ - _1, - assert_equal([:a], eval("[:a].map{_1}")), - assert_raise(NameError) {eval("_1")}, - ] - } - end - - def test_value_expr_in_condition - mesg = /void value expression/ - assert_syntax_error("tap {a = (true ? next : break)}", mesg) - assert_valid_syntax("tap {a = (true ? true : break)}") - assert_valid_syntax("tap {a = (break if false)}") - assert_valid_syntax("tap {a = (break unless true)}") - end - - def test_tautological_condition - assert_valid_syntax("def f() return if false and invalid; nil end") - assert_valid_syntax("def f() return unless true or invalid; nil end") - end - - def test_argument_forwarding - assert_valid_syntax('def foo(...) bar(...) end') - assert_valid_syntax('def foo(...) end') - assert_valid_syntax('def ==(...) end') - assert_valid_syntax('def [](...) end') - assert_valid_syntax('def nil(...) end') - assert_valid_syntax('def true(...) end') - assert_valid_syntax('def false(...) end') - unexpected = /unexpected \.{3}/ - assert_syntax_error('iter do |...| end', /unexpected/) - assert_syntax_error('iter {|...|}', /unexpected/) - assert_syntax_error('->... {}', unexpected) - assert_syntax_error('->(...) {}', unexpected) - assert_syntax_error('def foo(x, y, z) bar(...); end', /unexpected/) - assert_syntax_error('def foo(x, y, z) super(...); end', /unexpected/) - assert_syntax_error('def foo(...) yield(...); end', /unexpected/) - assert_syntax_error('def foo(...) return(...); end', /unexpected/) - assert_syntax_error('def foo(...) a = (...); end', /unexpected/) - assert_syntax_error('def foo(...) [...]; end', /unexpected/) - assert_syntax_error('def foo(...) foo[...]; end', /unexpected/) - assert_syntax_error('def foo(...) foo[...] = x; end', /unexpected/) - assert_syntax_error('def foo(...) foo(...) { }; end', /both block arg and actual block given/) - assert_syntax_error('def foo(...) defined?(...); end', /unexpected/) - - obj1 = Object.new - def obj1.bar(*args, **kws, &block) - if block - block.call(args, kws) - else - [args, kws] - end - end - obj1.instance_eval('def foo(...) bar(...) end', __FILE__, __LINE__) - - klass = Class.new { - def foo(*args, **kws, &block) - if block - block.call(args, kws) - else - [args, kws] - end - end - } - obj2 = klass.new - obj2.instance_eval('def foo(...) super(...) end', __FILE__, __LINE__) - - obj3 = Object.new - def obj3.bar(*args, &block) - if kws = Hash.try_convert(args.last) - args.pop - else - kws = {} - end - if block - block.call(args, kws) - else - [args, kws] - end - end - obj3.instance_eval('def foo(...) bar(...) end', __FILE__, __LINE__) - - [obj1, obj2, obj3].each do |obj| - assert_warning('') { - assert_equal([[1, 2, 3], {k1: 4, k2: 5}], obj.foo(1, 2, 3, k1: 4, k2: 5) {|*x| x}) - } - assert_warning('') { - assert_equal([[1, 2, 3], {k1: 4, k2: 5}], obj.foo(1, 2, 3, k1: 4, k2: 5)) - } - array = obj == obj3 ? [] : [{}] - assert_warning('') { - assert_equal([array, {}], obj.foo({}) {|*x| x}) - } - assert_warning('') { - assert_equal([array, {}], obj.foo({})) - } - assert_equal(-1, obj.method(:foo).arity) - parameters = obj.method(:foo).parameters - assert_equal(:rest, parameters.dig(0, 0)) - assert_equal(:block, parameters.dig(1, 0)) - end - end - - def test_argument_forwarding_with_leading_arguments - obj = Object.new - def obj.bar(*args, **kws, &block) - if block - block.call(args, kws) - else - [args, kws] - end - end - obj.instance_eval('def foo(_a, ...) bar(...) end', __FILE__, __LINE__) - assert_equal [[], {}], obj.foo(1) - assert_equal [[2], {}], obj.foo(1, 2) - assert_equal [[2, 3], {}], obj.foo(1, 2, 3) - assert_equal [[], {a: 1}], obj.foo(1, a: 1) - assert_equal [[2], {a: 1}], obj.foo(1, 2, a: 1) - assert_equal [[2, 3], {a: 1}], obj.foo(1, 2, 3, a: 1) - assert_equal [[2, 3], {a: 1}], obj.foo(1, 2, 3, a: 1){|args, kws| [args, kws]} - - obj.singleton_class.send(:remove_method, :foo) - obj.instance_eval('def foo(...) bar(1, ...) end', __FILE__, __LINE__) - assert_equal [[1], {}], obj.foo - assert_equal [[1, 1], {}], obj.foo(1) - assert_equal [[1, 1, 2], {}], obj.foo(1, 2) - assert_equal [[1, 1, 2, 3], {}], obj.foo(1, 2, 3) - assert_equal [[1], {a: 1}], obj.foo(a: 1) - assert_equal [[1, 1], {a: 1}], obj.foo(1, a: 1) - assert_equal [[1, 1, 2], {a: 1}], obj.foo(1, 2, a: 1) - assert_equal [[1, 1, 2, 3], {a: 1}], obj.foo(1, 2, 3, a: 1) - assert_equal [[1, 1, 2, 3], {a: 1}], obj.foo(1, 2, 3, a: 1){|args, kws| [args, kws]} - - obj.singleton_class.send(:remove_method, :foo) - obj.instance_eval('def foo(a, ...) bar(a, ...) end', __FILE__, __LINE__) - assert_equal [[4], {}], obj.foo(4) - assert_equal [[4, 2], {}], obj.foo(4, 2) - assert_equal [[4, 2, 3], {}], obj.foo(4, 2, 3) - assert_equal [[4], {a: 1}], obj.foo(4, a: 1) - assert_equal [[4, 2], {a: 1}], obj.foo(4, 2, a: 1) - assert_equal [[4, 2, 3], {a: 1}], obj.foo(4, 2, 3, a: 1) - assert_equal [[4, 2, 3], {a: 1}], obj.foo(4, 2, 3, a: 1){|args, kws| [args, kws]} - - obj.singleton_class.send(:remove_method, :foo) - obj.instance_eval('def foo(_a, ...) bar(1, ...) end', __FILE__, __LINE__) - assert_equal [[1], {}], obj.foo(4) - assert_equal [[1, 2], {}], obj.foo(4, 2) - assert_equal [[1, 2, 3], {}], obj.foo(4, 2, 3) - assert_equal [[1], {a: 1}], obj.foo(4, a: 1) - assert_equal [[1, 2], {a: 1}], obj.foo(4, 2, a: 1) - assert_equal [[1, 2, 3], {a: 1}], obj.foo(4, 2, 3, a: 1) - assert_equal [[1, 2, 3], {a: 1}], obj.foo(4, 2, 3, a: 1){|args, kws| [args, kws]} - - obj.singleton_class.send(:remove_method, :foo) - obj.instance_eval('def foo(_a, _b, ...) bar(...) end', __FILE__, __LINE__) - assert_equal [[], {}], obj.foo(4, 5) - assert_equal [[2], {}], obj.foo(4, 5, 2) - assert_equal [[2, 3], {}], obj.foo(4, 5, 2, 3) - assert_equal [[], {a: 1}], obj.foo(4, 5, a: 1) - assert_equal [[2], {a: 1}], obj.foo(4, 5, 2, a: 1) - assert_equal [[2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1) - assert_equal [[2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1){|args, kws| [args, kws]} - - obj.singleton_class.send(:remove_method, :foo) - obj.instance_eval('def foo(_a, _b, ...) bar(1, ...) end', __FILE__, __LINE__) - assert_equal [[1], {}], obj.foo(4, 5) - assert_equal [[1, 2], {}], obj.foo(4, 5, 2) - assert_equal [[1, 2, 3], {}], obj.foo(4, 5, 2, 3) - assert_equal [[1], {a: 1}], obj.foo(4, 5, a: 1) - assert_equal [[1, 2], {a: 1}], obj.foo(4, 5, 2, a: 1) - assert_equal [[1, 2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1) - assert_equal [[1, 2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1){|args, kws| [args, kws]} - - obj.singleton_class.send(:remove_method, :foo) - obj.instance_eval('def foo(_a, ...) bar(1, 2, ...) end', __FILE__, __LINE__) - assert_equal [[1, 2], {}], obj.foo(5) - assert_equal [[1, 2, 5], {}], obj.foo(4, 5) - assert_equal [[1, 2, 5, 2], {}], obj.foo(4, 5, 2) - assert_equal [[1, 2, 5, 2, 3], {}], obj.foo(4, 5, 2, 3) - assert_equal [[1, 2, 5], {a: 1}], obj.foo(4, 5, a: 1) - assert_equal [[1, 2, 5, 2], {a: 1}], obj.foo(4, 5, 2, a: 1) - assert_equal [[1, 2, 5, 2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1) - assert_equal [[1, 2, 5, 2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1){|args, kws| [args, kws]} - - obj.singleton_class.send(:remove_method, :foo) - obj.instance_eval('def foo(a, b, ...) bar(b, a, ...) end', __FILE__, __LINE__) - assert_equal [[5, 4], {}], obj.foo(4, 5) - assert_equal [[5, 4, 2], {}], obj.foo(4, 5, 2) - assert_equal [[5, 4, 2, 3], {}], obj.foo(4, 5, 2, 3) - assert_equal [[5, 4], {a: 1}], obj.foo(4, 5, a: 1) - assert_equal [[5, 4, 2], {a: 1}], obj.foo(4, 5, 2, a: 1) - assert_equal [[5, 4, 2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1) - assert_equal [[5, 4, 2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1){|args, kws| [args, kws]} - - obj.singleton_class.send(:remove_method, :foo) - obj.instance_eval('def foo(a, _b, ...) bar(a, ...) end', __FILE__, __LINE__) - assert_equal [[4], {}], obj.foo(4, 5) - assert_equal [[4, 2], {}], obj.foo(4, 5, 2) - assert_equal [[4, 2, 3], {}], obj.foo(4, 5, 2, 3) - assert_equal [[4], {a: 1}], obj.foo(4, 5, a: 1) - assert_equal [[4, 2], {a: 1}], obj.foo(4, 5, 2, a: 1) - assert_equal [[4, 2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1) - assert_equal [[4, 2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1){|args, kws| [args, kws]} - - obj.singleton_class.send(:remove_method, :foo) - obj.instance_eval('def foo(a, ...) bar(a, 1, ...) end', __FILE__, __LINE__) - assert_equal [[4, 1], {}], obj.foo(4) - assert_equal [[4, 1, 5], {}], obj.foo(4, 5) - assert_equal [[4, 1, 5, 2], {}], obj.foo(4, 5, 2) - assert_equal [[4, 1, 5, 2, 3], {}], obj.foo(4, 5, 2, 3) - assert_equal [[4, 1, 5], {a: 1}], obj.foo(4, 5, a: 1) - assert_equal [[4, 1, 5, 2], {a: 1}], obj.foo(4, 5, 2, a: 1) - assert_equal [[4, 1, 5, 2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1) - assert_equal [[4, 1, 5, 2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1){|args, kws| [args, kws]} - end - private def not_label(x) @result = x; @not_label ||= nil end diff --git a/test/ruby/test_system.rb b/test/ruby/test_system.rb index 31c9cd7654..60037ab044 100644 --- a/test/ruby/test_system.rb +++ b/test/ruby/test_system.rb @@ -160,45 +160,4 @@ class TestSystem < Test::Unit::TestCase assert_equal(true, system(tmpfilename), '[ruby-core:32745]') } end if File.executable?("/bin/sh") - - def test_system_exception - ruby = EnvUtil.rubybin - assert_nothing_raised do - system('feature_14235', exception: false) - end - assert_nothing_raised do - system(ruby, "-e", "abort", exception: false) - end - assert_nothing_raised do - system("'#{ruby}' -e abort", exception: false) - end - assert_raise(Errno::ENOENT) do - system('feature_14235', exception: true) - end - assert_raise_with_message(RuntimeError, /\ACommand failed with exit /) do - system(ruby, "-e", "abort", exception: true) - end - assert_raise_with_message(RuntimeError, /\ACommand failed with exit /) do - system("'#{ruby}' -e abort", exception: true) - end - end - - def test_system_exception_nonascii - Dir.mktmpdir("ruby_script_tmp") do |tmpdir| - name = "\u{30c6 30b9 30c8}" - tmpfilename = "#{tmpdir}/#{name}.cmd" - message = /#{name}\.cmd/ - assert_raise_with_message(Errno::ENOENT, message) do - system(tmpfilename, exception: true) - end - open(tmpfilename, "w") {|f| - f.print "@" if /mingw|mswin/ =~ RUBY_PLATFORM - f.puts "exit 127" - f.chmod(0755) - } - assert_raise_with_message(RuntimeError, message) do - system(tmpfilename, exception: true) - end - end - end end diff --git a/test/ruby/test_thread.rb b/test/ruby/test_thread.rb index 3852cb7020..135d17237e 100644 --- a/test/ruby/test_thread.rb +++ b/test/ruby/test_thread.rb @@ -1,8 +1,6 @@ # -*- coding: us-ascii -*- # frozen_string_literal: false require 'test/unit' -require "rbconfig/sizeof" -require "timeout" class TestThread < Test::Unit::TestCase class Thread < ::Thread @@ -29,12 +27,8 @@ class TestThread < Test::Unit::TestCase end def test_inspect - line = __LINE__+1 th = Module.new {break module_eval("class C\u{30b9 30ec 30c3 30c9} < Thread; self; end")}.start{} - s = th.inspect - assert_include(s, "::C\u{30b9 30ec 30c3 30c9}:") - assert_include(s, " #{__FILE__}:#{line} ") - assert_equal(s, th.to_s) + assert_match(/::C\u{30b9 30ec 30c3 30c9}:/, th.inspect) ensure th.join end @@ -172,8 +166,6 @@ class TestThread < Test::Unit::TestCase t1.kill t2.kill assert_operator(c1, :>, c2, "[ruby-dev:33124]") # not guaranteed - t1.join - t2.join end def test_new @@ -192,8 +184,8 @@ class TestThread < Test::Unit::TestCase end ensure - t1&.kill&.join - t2&.kill&.join + t1.kill if t1 + t2.kill if t2 end def test_new_symbol_proc @@ -209,7 +201,7 @@ class TestThread < Test::Unit::TestCase assert_nil(t.join(0.05)) ensure - t&.kill&.join + t.kill if t end def test_join2 @@ -230,39 +222,9 @@ class TestThread < Test::Unit::TestCase assert_equal(t1, t3.value) ensure - t1&.kill&.join - t2&.kill&.join - t3&.kill&.join - end - - { 'FIXNUM_MAX' => RbConfig::LIMITS['FIXNUM_MAX'], - 'UINT64_MAX' => RbConfig::LIMITS['UINT64_MAX'], - '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 - end - - { 'minus_1' => -1, - 'minus_0_1' => -0.1, - 'FIXNUM_MIN' => RbConfig::LIMITS['FIXNUM_MIN'], - 'INT64_MIN' => RbConfig::LIMITS['INT64_MIN'], - 'minus_INFINITY' => -Float::INFINITY - }.each do |name, limit| - define_method("test_join_limit_negative_#{name}") do - t = Thread.new { sleep } - begin - assert_nothing_raised(Timeout::Error) do - Timeout.timeout(30) do - assert_nil t.join(limit), "limit=#{limit.inspect}" - end - end - ensure - t.kill - end - end + t1.kill if t1 + t2.kill if t2 + t3.kill if t3 end def test_kill_main_thread @@ -309,14 +271,14 @@ class TestThread < Test::Unit::TestCase s += 1 end Thread.pass until t.stop? - sleep 1 if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # t.stop? behaves unexpectedly with --jit-wait assert_equal(1, s) t.wakeup Thread.pass while t.alive? assert_equal(2, s) assert_raise(ThreadError) { t.wakeup } + ensure - t&.kill&.join + t.kill if t end def test_stop @@ -437,7 +399,6 @@ class TestThread < Test::Unit::TestCase } assert_equal(false, q1.pop) Thread.pass while th.alive? - assert_raise(RuntimeError) { th.join } } assert_warn(/report 2/, "exception should be reported when true") { @@ -447,7 +408,6 @@ class TestThread < Test::Unit::TestCase } assert_equal(true, q1.pop) Thread.pass while th.alive? - assert_raise(RuntimeError) { th.join } } assert_warn("", "the global flag should not affect already started threads") { @@ -460,7 +420,6 @@ class TestThread < Test::Unit::TestCase q2.push(Thread.report_on_exception = true) assert_equal(false, q1.pop) Thread.pass while th.alive? - assert_raise(RuntimeError) { th.join } } assert_warn(/report 4/, "should defaults to the global flag at the start") { @@ -471,7 +430,6 @@ class TestThread < Test::Unit::TestCase } assert_equal(true, q1.pop) Thread.pass while th.alive? - assert_raise(RuntimeError) { th.join } } assert_warn(/report 5/, "should first report and then raise with report_on_exception + abort_on_exception") { @@ -485,24 +443,10 @@ class TestThread < Test::Unit::TestCase q2.push(true) Thread.pass while th.alive? } - assert_raise(RuntimeError) { th.join } } end; end - def test_ignore_deadlock - if /mswin|mingw/ =~ RUBY_PLATFORM - skip "can't trap a signal from another process on Windows" - end - assert_in_out_err([], <<-INPUT, %w(false :sig), [], :signal=>:INT, timeout: 1, timeout_error: nil) - p Thread.ignore_deadlock - q = Queue.new - trap(:INT){q.push :sig} - Thread.ignore_deadlock = true - p q.pop - INPUT - end - def test_status_and_stop_p a = ::Thread.new { Thread.current.report_on_exception = false @@ -526,10 +470,11 @@ class TestThread < Test::Unit::TestCase es1 = e.status es2 = e.stop? assert_equal(["run", false], [es1, es2]) - assert_raise(RuntimeError) { a.join } + ensure - b&.kill&.join - c&.join + a.kill if a + b.kill if b + c.kill if c end def test_switch_while_busy_loop @@ -547,7 +492,24 @@ class TestThread < Test::Unit::TestCase end assert(!flag, bug1402) ensure - waiter&.kill&.join + waiter.kill.join + end + + def test_safe_level + ok = false + t = Thread.new do + EnvUtil.suppress_warning do + $SAFE = 1 + end + ok = true + sleep + end + Thread.pass until ok + assert_equal(0, Thread.current.safe_level) + assert_equal(1, t.safe_level) + + ensure + t.kill if t end def test_thread_local @@ -567,7 +529,7 @@ class TestThread < Test::Unit::TestCase assert_equal([:foo, :bar, :baz].sort, t.keys.sort) ensure - t&.kill&.join + t.kill if t end def test_thread_local_fetch @@ -599,7 +561,7 @@ class TestThread < Test::Unit::TestCase assert_equal(:qux, e.key) assert_equal(t, e.receiver) ensure - t&.kill&.join + t.kill if t end def test_thread_local_security @@ -629,8 +591,7 @@ class TestThread < Test::Unit::TestCase end Thread.pass until t.stop? assert_predicate(t, :alive?) - ensure - t&.kill&.join + t.kill end def test_mutex_deadlock @@ -808,15 +769,14 @@ class TestThread < Test::Unit::TestCase end def test_handle_interrupt_blocking - r = nil - q = Queue.new - e = Class.new(Exception) + r=:ng + e=Class.new(Exception) th_s = Thread.current - th = Thread.start { + th = Thread.start{ assert_raise(RuntimeError) { Thread.handle_interrupt(Object => :on_blocking){ begin - q.pop + Thread.pass until r == :wait Thread.current.raise RuntimeError, "will raise in sleep" r = :ok sleep @@ -826,26 +786,25 @@ class TestThread < Test::Unit::TestCase } } } - assert_raise(e) {q << true; th.join} - assert_equal(:ok, r) + assert_raise(e) {r = :wait; sleep 0.2} + th.join + assert_equal(:ok,r) end def test_handle_interrupt_and_io assert_in_out_err([], <<-INPUT, %w(ok), []) th_waiting = true - q = Queue.new t = Thread.new { Thread.current.report_on_exception = false Thread.handle_interrupt(RuntimeError => :on_blocking) { - q << true nil while th_waiting # async interrupt should be raised _before_ writing puts arguments puts "ng" } } - q.pop + Thread.pass while t.stop? t.raise RuntimeError th_waiting = false t.join rescue nil @@ -884,15 +843,15 @@ class TestThread < Test::Unit::TestCase begin begin Thread.pass until done - rescue + rescue => e q.push :ng1 end begin Thread.handle_interrupt(Object => :immediate){} if Thread.pending_interrupt? - rescue RuntimeError + rescue RuntimeError => e q.push :ok end - rescue + rescue => e q.push :ng2 ensure q.push :ng3 @@ -960,21 +919,15 @@ _eom def test_thread_timer_and_interrupt bug5757 = '[ruby-dev:44985]' pid = nil - cmd = 'Signal.trap(:INT, "DEFAULT"); pipe=IO.pipe; Thread.start {Thread.pass until Thread.main.stop?; puts; STDOUT.flush}; pipe[0].read' + cmd = 'Signal.trap(:INT, "DEFAULT"); r,=IO.pipe; Thread.start {Thread.pass until Thread.main.stop?; puts; STDOUT.flush}; r.read' opt = {} opt[:new_pgroup] = true if /mswin|mingw/ =~ RUBY_PLATFORM - s, t, _err = EnvUtil.invoke_ruby(['-e', cmd], "", true, true, **opt) do |in_p, out_p, err_p, cpid| - assert IO.select([out_p], nil, nil, 10), 'subprocess not ready' + s, t, _err = EnvUtil.invoke_ruby(['-e', cmd], "", true, true, opt) do |in_p, out_p, err_p, cpid| out_p.gets pid = cpid t0 = Time.now.to_f Process.kill(:SIGINT, pid) - begin - Timeout.timeout(10) { Process.wait(pid) } - rescue Timeout::Error - EnvUtil.terminate(pid) - raise - end + Process.wait(pid) t1 = Time.now.to_f [$?, t1 - t0, err_p.read] end @@ -1119,7 +1072,7 @@ q.pop Thread.pass until mutex.locked? assert_equal(mutex.owned?, false) ensure - th&.kill&.join + th.kill if th end end @@ -1163,7 +1116,6 @@ q.pop "0 thread_machine_stack_size") assert_operator(h_default[:thread_machine_stack_size], :<=, h_large[:thread_machine_stack_size], "large thread_machine_stack_size") - assert_equal("ok", invoke_rec('print :ok', 1024 * 1024 * 100, nil, false)) end def test_vm_machine_stack_size @@ -1192,10 +1144,12 @@ q.pop bug8433 = '[ruby-core:55102] [Bug #8433]' mutex = Thread::Mutex.new + flag = false mutex.lock th = Thread.new do mutex.synchronize do + flag = true sleep end end @@ -1245,42 +1199,6 @@ q.pop end end if Process.respond_to?(:fork) - def test_fork_while_parent_locked - skip 'needs fork' unless Process.respond_to?(:fork) - m = Thread::Mutex.new - nr = 1 - thrs = [] - m.synchronize do - thrs = nr.times.map { Thread.new { m.synchronize {} } } - thrs.each { Thread.pass } - pid = fork do - m.locked? or exit!(2) - thrs = nr.times.map { Thread.new { m.synchronize {} } } - m.unlock - thrs.each { |t| t.join(1) == t or exit!(1) } - exit!(0) - end - _, st = Process.waitpid2(pid) - assert_predicate st, :success?, '[ruby-core:90312] [Bug #15383]' - end - thrs.each { |t| assert_same t, t.join(1) } - end - - def test_fork_while_mutex_locked_by_forker - skip 'needs fork' unless Process.respond_to?(:fork) - m = Mutex.new - m.synchronize do - pid = fork do - exit!(2) unless m.locked? - m.unlock rescue exit!(3) - m.synchronize {} rescue exit!(4) - exit!(0) - end - _, st = Timeout.timeout(30) { Process.waitpid2(pid) } - assert_predicate st, :success?, '[ruby-core:90595] [Bug #15430]' - end - end - def test_subclass_no_initialize t = Module.new do break eval("class C\u{30b9 30ec 30c3 30c9} < Thread; self; end") @@ -1335,18 +1253,12 @@ q.pop end def test_thread_interrupt_for_killed_thread - opts = { timeout: 5, timeout_error: nil } - - # prevent SIGABRT from slow shutdown with MJIT - opts[:reprieve] = 3 if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? - - assert_normal_exit(<<-_end, '[Bug #8996]', **opts) + assert_normal_exit(<<-_end, '[Bug #8996]', timeout: 5, timeout_error: nil) Thread.report_on_exception = false trap(:TERM){exit} while true t = Thread.new{sleep 0} t.raise Interrupt - Thread.pass # allow t to finish end _end end @@ -1356,7 +1268,7 @@ q.pop skip "can't trap a signal from another process on Windows" # opt = {new_pgroup: true} end - assert_separately([], "#{<<~"{#"}\n#{<<~'};'}", timeout: 120) + assert_separately([], "#{<<~"{#"}\n#{<<~'};'}") {# n = 1000 sig = :INT diff --git a/test/ruby/test_thread_cv.rb b/test/ruby/test_thread_cv.rb deleted file mode 100644 index 38bcc3b8fa..0000000000 --- a/test/ruby/test_thread_cv.rb +++ /dev/null @@ -1,245 +0,0 @@ -# frozen_string_literal: false -require 'test/unit' -require 'tmpdir' - -class TestThreadConditionVariable < Test::Unit::TestCase - ConditionVariable = Thread::ConditionVariable - Mutex = Thread::Mutex - - def test_initialized - assert_raise(TypeError) { - ConditionVariable.allocate.wait(nil) - } - end - - def test_condvar_signal_and_wait - mutex = Mutex.new - condvar = ConditionVariable.new - result = [] - mutex.synchronize do - t = Thread.new do - mutex.synchronize do - result << 1 - condvar.signal - end - end - - result << 0 - condvar.wait(mutex) - result << 2 - t.join - end - assert_equal([0, 1, 2], result) - end - - def test_condvar_wait_exception_handling - # Calling wait in the only thread running should raise a ThreadError of - # 'stopping only thread' - mutex = Mutex.new - condvar = ConditionVariable.new - - locked = false - thread = Thread.new do - Thread.current.abort_on_exception = false - mutex.synchronize do - assert_raise(Interrupt) { - condvar.wait(mutex) - } - locked = mutex.locked? - end - end - - until thread.stop? - sleep(0.1) - end - - thread.raise Interrupt, "interrupt a dead condition variable" - thread.join - assert(locked) - end - - def test_condvar_wait_and_broadcast - nr_threads = 3 - threads = Array.new - mutex = Mutex.new - condvar = ConditionVariable.new - result = [] - - nr_threads.times do |i| - threads[i] = Thread.new do - mutex.synchronize do - result << "C1" - condvar.wait mutex - result << "C2" - end - end - end - sleep 0.1 - mutex.synchronize do - result << "P1" - condvar.broadcast - result << "P2" - end - Timeout.timeout(5) do - nr_threads.times do |i| - threads[i].join - end - end - - assert_equal ["C1", "C1", "C1", "P1", "P2", "C2", "C2", "C2"], result - end - - def test_condvar_wait_deadlock - assert_in_out_err([], <<-INPUT, /\Afatal\nNo live threads left\. Deadlock/, []) - mutex = Mutex.new - cv = ConditionVariable.new - - klass = nil - mesg = nil - begin - mutex.lock - cv.wait mutex - mutex.unlock - rescue Exception => e - klass = e.class - mesg = e.message - end - puts klass - print mesg -INPUT - end - - def test_condvar_wait_deadlock_2 - nr_threads = 3 - threads = Array.new - mutex = Mutex.new - condvar = ConditionVariable.new - - nr_threads.times do |i| - if (i != 0) - mutex.unlock - end - threads[i] = Thread.new do - mutex.synchronize do - condvar.wait mutex - end - end - mutex.lock - end - - assert_raise(Timeout::Error) do - Timeout.timeout(0.1) { condvar.wait mutex } - end - mutex.unlock - threads.each(&:kill) - threads.each(&:join) - end - - def test_condvar_timed_wait - mutex = Mutex.new - condvar = ConditionVariable.new - timeout = 0.3 - locked = false - - t0 = Time.now - mutex.synchronize do - begin - condvar.wait(mutex, timeout) - ensure - locked = mutex.locked? - end - end - t1 = Time.now - t = t1-t0 - - assert_operator(timeout*0.9, :<, t) - assert(locked) - end - - def test_condvar_nolock - mutex = Mutex.new - condvar = ConditionVariable.new - - assert_raise(ThreadError) {condvar.wait(mutex)} - end - - def test_condvar_nolock_2 - mutex = Mutex.new - condvar = ConditionVariable.new - - Thread.new do - assert_raise(ThreadError) {condvar.wait(mutex)} - end.join - end - - def test_condvar_nolock_3 - mutex = Mutex.new - condvar = ConditionVariable.new - - Thread.new do - assert_raise(ThreadError) {condvar.wait(mutex, 0.1)} - end.join - end - - def test_condvar_empty_signal - mutex = Mutex.new - condvar = ConditionVariable.new - - assert_nothing_raised(Exception) { mutex.synchronize {condvar.signal} } - end - - def test_condvar_empty_broadcast - mutex = Mutex.new - condvar = ConditionVariable.new - - assert_nothing_raised(Exception) { mutex.synchronize {condvar.broadcast} } - end - - def test_dup - bug9440 = '[ruby-core:59961] [Bug #9440]' - condvar = ConditionVariable.new - assert_raise(NoMethodError, bug9440) do - condvar.dup - end - end - - (DumpableCV = ConditionVariable.dup).class_eval {remove_method :marshal_dump} - - def test_dump - bug9674 = '[ruby-core:61677] [Bug #9674]' - condvar = ConditionVariable.new - assert_raise_with_message(TypeError, /#{ConditionVariable}/, bug9674) do - Marshal.dump(condvar) - end - - condvar = DumpableCV.new - assert_raise(TypeError, bug9674) do - Marshal.dump(condvar) - end - end - - def test_condvar_fork - mutex = Mutex.new - condvar = ConditionVariable.new - thrs = (1..10).map do - Thread.new { mutex.synchronize { condvar.wait(mutex) } } - end - thrs.each { 3.times { Thread.pass } } - pid = fork do - th = Thread.new do - mutex.synchronize { condvar.wait(mutex) } - :ok - end - until th.join(0.01) - mutex.synchronize { condvar.broadcast } - end - exit!(th.value == :ok ? 0 : 1) - end - _, s = Process.waitpid2(pid) - assert_predicate s, :success?, 'no segfault [ruby-core:86316] [Bug #14634]' - until thrs.empty? - mutex.synchronize { condvar.broadcast } - thrs.delete_if { |t| t.join(0.01) } - end - end if Process.respond_to?(:fork) -end diff --git a/test/ruby/test_thread_queue.rb b/test/ruby/test_thread_queue.rb deleted file mode 100644 index b0fa878814..0000000000 --- a/test/ruby/test_thread_queue.rb +++ /dev/null @@ -1,631 +0,0 @@ -# frozen_string_literal: false -require 'test/unit' -require 'tmpdir' -require 'timeout' - -class TestThreadQueue < Test::Unit::TestCase - Queue = Thread::Queue - SizedQueue = Thread::SizedQueue - - def test_queue_initialized - assert_raise(TypeError) { - Queue.allocate.push(nil) - } - end - - def test_sized_queue_initialized - assert_raise(TypeError) { - SizedQueue.allocate.push(nil) - } - end - - def test_queue - grind(5, 1000, 15, Queue) - end - - def test_sized_queue - grind(5, 1000, 15, SizedQueue, 1000) - end - - def grind(num_threads, num_objects, num_iterations, klass, *args) - from_workers = klass.new(*args) - to_workers = klass.new(*args) - - workers = (1..num_threads).map { - Thread.new { - while object = to_workers.pop - from_workers.push object - end - } - } - - Thread.new { - num_iterations.times { - num_objects.times { to_workers.push 99 } - num_objects.times { from_workers.pop } - } - }.join - - # close the queue the old way to test for backwards-compatibility - num_threads.times { to_workers.push nil } - workers.each { |t| t.join } - - assert_equal 0, from_workers.size - assert_equal 0, to_workers.size - end - - def test_sized_queue_initialize - q = SizedQueue.new(1) - assert_equal 1, q.max - assert_raise(ArgumentError) { SizedQueue.new(0) } - assert_raise(ArgumentError) { SizedQueue.new(-1) } - end - - def test_sized_queue_assign_max - q = SizedQueue.new(2) - assert_equal(2, q.max) - q.max = 1 - assert_equal(1, q.max) - assert_raise(ArgumentError) { q.max = 0 } - assert_equal(1, q.max) - assert_raise(ArgumentError) { q.max = -1 } - assert_equal(1, q.max) - - before = q.max - q.max.times { q << 1 } - t1 = Thread.new { q << 1 } - sleep 0.01 until t1.stop? - q.max = q.max + 1 - assert_equal before + 1, q.max - ensure - t1.join if t1 - end - - def test_queue_pop_interrupt - q = Queue.new - t1 = Thread.new { q.pop } - sleep 0.01 until t1.stop? - t1.kill.join - assert_equal(0, q.num_waiting) - end - - def test_queue_pop_non_block - q = Queue.new - assert_raise_with_message(ThreadError, /empty/) do - q.pop(true) - end - end - - def test_sized_queue_pop_interrupt - q = SizedQueue.new(1) - t1 = Thread.new { q.pop } - sleep 0.01 until t1.stop? - t1.kill.join - assert_equal(0, q.num_waiting) - end - - def test_sized_queue_pop_non_block - q = SizedQueue.new(1) - assert_raise_with_message(ThreadError, /empty/) do - q.pop(true) - end - end - - def test_sized_queue_push_interrupt - q = SizedQueue.new(1) - q.push(1) - assert_raise_with_message(ThreadError, /full/) do - q.push(2, true) - end - end - - def test_sized_queue_push_non_block - q = SizedQueue.new(1) - q.push(1) - t1 = Thread.new { q.push(2) } - sleep 0.01 until t1.stop? - t1.kill.join - assert_equal(0, q.num_waiting) - end - - def test_thr_kill - bug5343 = '[ruby-core:39634]' - Dir.mktmpdir {|d| - timeout = EnvUtil.apply_timeout_scale(60) - total_count = 250 - begin - assert_normal_exit(<<-"_eom", bug5343, **{:timeout => timeout, :chdir=>d}) - #{total_count}.times do |i| - open("test_thr_kill_count", "w") {|f| f.puts i } - queue = Queue.new - r, w = IO.pipe - th = Thread.start { - queue.push(nil) - r.read 1 - } - queue.pop - th.kill - th.join - end - _eom - rescue Timeout::Error - count = File.read("#{d}/test_thr_kill_count").to_i - flunk "only #{count}/#{total_count} done in #{timeout} seconds." - end - } - end - - def test_queue_push_return_value - q = Queue.new - retval = q.push(1) - assert_same q, retval - end - - def test_queue_clear_return_value - q = Queue.new - retval = q.clear - assert_same q, retval - end - - def test_sized_queue_clear - # Fill queue, then test that SizedQueue#clear wakes up all waiting threads - sq = SizedQueue.new(2) - 2.times { sq << 1 } - - t1 = Thread.new do - sq << 1 - end - - t2 = Thread.new do - sq << 1 - end - - t3 = Thread.new do - Thread.pass - sq.clear - end - - [t3, t2, t1].each(&:join) - assert_equal sq.length, 2 - end - - def test_sized_queue_push_return_value - q = SizedQueue.new(1) - retval = q.push(1) - assert_same q, retval - end - - def test_sized_queue_clear_return_value - q = SizedQueue.new(1) - retval = q.clear - assert_same q, retval - end - - def test_sized_queue_throttle - q = SizedQueue.new(1) - i = 0 - consumer = Thread.new do - while q.pop - i += 1 - Thread.pass - end - end - nprod = 4 - npush = 100 - - producer = nprod.times.map do - Thread.new do - npush.times { q.push(true) } - end - end - producer.each(&:join) - q.push(nil) - consumer.join - assert_equal(nprod * npush, i) - end - - def test_queue_thread_raise - q = Queue.new - th1 = Thread.new do - begin - q.pop - rescue RuntimeError - sleep - end - end - th2 = Thread.new do - sleep 0.1 - q.pop - end - sleep 0.1 - th1.raise - sleep 0.1 - q << :s - assert_nothing_raised(Timeout::Error) do - Timeout.timeout(1) { th2.join } - end - ensure - [th1, th2].each do |th| - if th and th.alive? - th.wakeup - th.join - end - end - end - - def test_dup - bug9440 = '[ruby-core:59961] [Bug #9440]' - q = Queue.new - assert_raise(NoMethodError, bug9440) do - q.dup - end - end - - (DumpableQueue = Queue.dup).class_eval {remove_method :marshal_dump} - - def test_dump - bug9674 = '[ruby-core:61677] [Bug #9674]' - q = Queue.new - assert_raise_with_message(TypeError, /#{Queue}/, bug9674) do - Marshal.dump(q) - end - - sq = SizedQueue.new(1) - assert_raise_with_message(TypeError, /#{SizedQueue}/, bug9674) do - Marshal.dump(sq) - end - - q = DumpableQueue.new - assert_raise(TypeError, bug9674) do - Marshal.dump(q) - end - end - - def test_close - [->{Queue.new}, ->{SizedQueue.new 3}].each do |qcreate| - q = qcreate.call - assert_equal false, q.closed? - q << :something - assert_equal q, q.close - assert q.closed? - assert_raise_with_message(ClosedQueueError, /closed/){q << :nothing} - assert_equal q.pop, :something - assert_nil q.pop - assert_nil q.pop - # non-blocking - assert_raise_with_message(ThreadError, /queue empty/){q.pop(non_block=true)} - end - end - - # test that waiting producers are woken up on close - def close_wakeup( num_items, num_threads, &qcreate ) - raise "This test won't work with num_items(#{num_items}) >= num_threads(#{num_threads})" if num_items >= num_threads - - # create the Queue - q = yield - threads = num_threads.times.map{Thread.new{q.pop}} - num_items.times{|i| q << i} - - # wait until queue empty - (Thread.pass; sleep 0.01) until q.size == 0 - - # close the queue so remaining threads will wake up - q.close - - # wait for them to go away - Thread.pass until threads.all?{|thr| thr.status == false} - - # check that they've gone away. Convert nil to -1 so we can sort and do the comparison - expected_values = [-1] * (num_threads - num_items) + num_items.times.to_a - assert_equal expected_values, threads.map{|thr| thr.value || -1 }.sort - end - - def test_queue_close_wakeup - close_wakeup(15, 18){Queue.new} - end - - def test_size_queue_close_wakeup - close_wakeup(5, 8){SizedQueue.new 9} - end - - def test_sized_queue_one_closed_interrupt - q = SizedQueue.new 1 - q << :one - t1 = Thread.new { - Thread.current.report_on_exception = false - q << :two - } - sleep 0.01 until t1.stop? - q.close - assert_raise(ClosedQueueError) {t1.join} - - assert_equal 1, q.size - assert_equal :one, q.pop - assert q.empty?, "queue not empty" - end - - # make sure that shutdown state is handled properly by empty? for the non-blocking case - def test_empty_non_blocking - q = SizedQueue.new 3 - 3.times{|i| q << i} - - # these all block cos the queue is full - prod_threads = 4.times.map {|i| - Thread.new { - Thread.current.report_on_exception = false - q << 3+i - } - } - sleep 0.01 until prod_threads.all?{|thr| thr.stop?} - - items = [] - # sometimes empty? is false but pop will raise ThreadError('empty'), - # meaning a value is not immediately available but will be soon. - while prod_threads.any?(&:alive?) or !q.empty? - items << q.pop(true) rescue nil - end - assert_join_threads(prod_threads) - items.compact! - - assert_equal 7.times.to_a, items.sort - assert q.empty? - end - - def test_sized_queue_closed_push_non_blocking - q = SizedQueue.new 7 - q.close - assert_raise_with_message(ClosedQueueError, /queue closed/){q.push(non_block=true)} - end - - def test_blocked_pushers - q = SizedQueue.new 3 - prod_threads = 6.times.map do |i| - thr = Thread.new{ - Thread.current.report_on_exception = false - q << i - } - thr[:pc] = i - thr - end - - # wait until some producer threads have finished, and the other 3 are blocked - sleep 0.01 while prod_threads.reject{|t| t.status}.count < 3 - # this would ensure that all producer threads call push before close - # sleep 0.01 while prod_threads.select{|t| t.status == 'sleep'}.count < 3 - q.close - - # more than prod_threads - cons_threads = 10.times.map do |i| - thr = Thread.new{q.pop}; thr[:pc] = i; thr - end - - # values that came from the queue - popped_values = cons_threads.map &:value - - # wait untl all threads have finished - sleep 0.01 until prod_threads.find_all{|t| t.status}.count == 0 - - # pick only the producer threads that got in before close - successful_prod_threads = prod_threads.reject{|thr| thr.status == nil} - assert_nothing_raised{ successful_prod_threads.map(&:value) } - - # the producer threads that tried to push after q.close should all fail - unsuccessful_prod_threads = prod_threads - successful_prod_threads - unsuccessful_prod_threads.each do |thr| - assert_raise(ClosedQueueError){ thr.value } - end - - assert_equal cons_threads.size, popped_values.size - assert_equal 0, q.size - - # check that consumer threads with values match producers that called push before close - assert_equal successful_prod_threads.map{|thr| thr[:pc]}, popped_values.compact.sort - assert_nil q.pop - end - - def test_deny_pushers - [->{Queue.new}, ->{SizedQueue.new 3}].each do |qcreate| - q = qcreate[] - synq = Queue.new - prod_threads = 20.times.map do |i| - Thread.new { - synq.pop - assert_raise(ClosedQueueError) { - q << i - } - } - end - q.close - synq.close # start producer threads - - prod_threads.each(&:join) - end - end - - # size should account for waiting pushers during shutdown - def sized_queue_size_close - q = SizedQueue.new 4 - 4.times{|i| q << i} - Thread.new{ q << 5 } - Thread.new{ q << 6 } - assert_equal 4, q.size - assert_equal 4, q.items - q.close - assert_equal 6, q.size - assert_equal 4, q.items - end - - def test_blocked_pushers_empty - q = SizedQueue.new 3 - prod_threads = 6.times.map do |i| - Thread.new{ - Thread.current.report_on_exception = false - q << i - } - end - - # this ensures that all producer threads call push before close - sleep 0.01 while prod_threads.select{|t| t.status == 'sleep'}.count < 3 - q.close - - ary = [] - until q.empty? - ary << q.pop - end - assert_equal 0, q.size - - assert_equal 3, ary.size - ary.each{|e| assert [0,1,2,3,4,5].include?(e)} - assert_nil q.pop - - prod_threads.each{|t| - begin - t.join - rescue - end - } - end - - # test thread wakeup on one-element SizedQueue with close - def test_one_element_sized_queue - q = SizedQueue.new 1 - t = Thread.new{ q.pop } - q.close - assert_nil t.value - end - - def test_close_twice - [->{Queue.new}, ->{SizedQueue.new 3}].each do |qcreate| - q = qcreate[] - q.close - assert_nothing_raised(ClosedQueueError){q.close} - end - end - - def test_queue_close_multi_multi - q = SizedQueue.new rand(800..1200) - - count_items = rand(3000..5000) - count_producers = rand(10..20) - - producers = count_producers.times.map do - Thread.new do - sleep(rand / 100) - count_items.times{|i| q << [i,"#{i} for #{Thread.current.inspect}"]} - end - end - - consumers = rand(7..12).times.map do - Thread.new do - count = 0 - while e = q.pop - i, st = e - count += 1 if i.is_a?(Integer) && st.is_a?(String) - end - count - end - end - - # No dead or finished threads, give up to 10 seconds to start running - t = Time.now - Thread.pass until Time.now - t > 10 || (consumers + producers).all?{|thr| thr.status =~ /\A(?:run|sleep)\z/} - - assert (consumers + producers).all?{|thr| thr.status =~ /\A(?:run|sleep)\z/}, 'no threads running' - - # just exercising the concurrency of the support methods. - counter = Thread.new do - until q.closed? && q.empty? - raise if q.size > q.max - # otherwise this exercise causes too much contention on the lock - sleep 0.01 - end - end - - producers.each &:join - q.close - - # results not randomly distributed. Not sure why. - # consumers.map{|thr| thr.value}.each do |x| - # assert_not_equal 0, x - # end - - all_items_count = consumers.map{|thr| thr.value}.inject(:+) - assert_equal count_items * count_producers, all_items_count - - # don't leak this thread - assert_nothing_raised{counter.join} - end - - def test_queue_with_trap - if ENV['APPVEYOR'] == 'True' && RUBY_PLATFORM.match?(/mswin/) - skip 'This test fails too often on AppVeyor vs140' - end - if RUBY_PLATFORM.match?(/mingw/) - skip 'This test fails too often on MinGW' - end - - assert_in_out_err([], <<-INPUT, %w(INT INT exit), []) - q = Queue.new - trap(:INT){ - q.push 'INT' - } - Thread.new{ - loop{ - Process.kill :INT, $$ - sleep 0.1 - } - } - puts q.pop - puts q.pop - puts 'exit' - INPUT - end - - def test_fork_while_queue_waiting - q = Queue.new - sq = SizedQueue.new(1) - thq = Thread.new { q.pop } - thsq = Thread.new { sq.pop } - Thread.pass until thq.stop? && thsq.stop? - - pid = fork do - exit!(1) if q.num_waiting != 0 - exit!(2) if sq.num_waiting != 0 - exit!(6) unless q.empty? - exit!(7) unless sq.empty? - q.push :child_q - sq.push :child_sq - exit!(3) if q.pop != :child_q - exit!(4) if sq.pop != :child_sq - exit!(0) - end - _, s = Process.waitpid2(pid) - assert_predicate s, :success?, 'no segfault [ruby-core:86316] [Bug #14634]' - - q.push :thq - sq.push :thsq - assert_equal :thq, thq.value - assert_equal :thsq, thsq.value - - sq.push(1) - th = Thread.new { q.pop; sq.pop } - thsq = Thread.new { sq.push(2) } - Thread.pass until th.stop? && thsq.stop? - pid = fork do - exit!(1) if q.num_waiting != 0 - exit!(2) if sq.num_waiting != 0 - exit!(3) unless q.empty? - exit!(4) if sq.empty? - exit!(5) if sq.pop != 1 - exit!(0) - end - _, s = Process.waitpid2(pid) - assert_predicate s, :success?, 'no segfault [ruby-core:86316] [Bug #14634]' - - assert_predicate thsq, :stop? - assert_equal 1, sq.pop - assert_same sq, thsq.value - q.push('restart th') - assert_equal 2, th.value - end if Process.respond_to?(:fork) -end diff --git a/test/ruby/test_time.rb b/test/ruby/test_time.rb index 4c24c28c97..5ddcc9dcfe 100644 --- a/test/ruby/test_time.rb +++ b/test/ruby/test_time.rb @@ -7,6 +7,7 @@ require 'delegate' class TestTime < Test::Unit::TestCase def setup @verbose = $VERBOSE + $VERBOSE = nil end def teardown @@ -107,10 +108,6 @@ class TestTime < Test::Unit::TestCase assert_equal(78796800, Time.utc(1972, 7, 1, 0, 0, 0).tv_sec) assert_equal(78796801, Time.utc(1972, 7, 1, 0, 0, 1).tv_sec) assert_equal(946684800, Time.utc(2000, 1, 1, 0, 0, 0).tv_sec) - - # Giveup to try 2nd test because some state is changed. - skip if Minitest::Unit.current_repeat_count > 0 - assert_equal(0x7fffffff, Time.utc(2038, 1, 19, 3, 14, 7).tv_sec) assert_equal(0x80000000, Time.utc(2038, 1, 19, 3, 14, 8).tv_sec) else @@ -176,7 +173,7 @@ class TestTime < Test::Unit::TestCase assert_equal(10000, Time.at(0.00001).nsec) assert_equal(3000, Time.at(0.000003).nsec) assert_equal(200, Time.at(0.0000002r).nsec) - assert_in_delta(200, Time.at(0.0000002).nsec, 1, "should be within FP error") + assert_equal(199, Time.at(0.0000002).nsec) assert_equal(10, Time.at(0.00000001).nsec) assert_equal(1, Time.at(0.000000001).nsec) @@ -378,16 +375,6 @@ class TestTime < Test::Unit::TestCase end end - def test_marshal_distant_past - assert_marshal_roundtrip(Time.utc(1890, 1, 1)) - assert_marshal_roundtrip(Time.utc(-4.5e9, 1, 1)) - end - - def test_marshal_distant_future - assert_marshal_roundtrip(Time.utc(30000, 1, 1)) - assert_marshal_roundtrip(Time.utc(5.67e9, 4, 8)) - end - def test_at3 t2000 = get_t2000 assert_equal(t2000, Time.at(t2000)) @@ -420,10 +407,8 @@ class TestTime < Test::Unit::TestCase def o.to_int; 0; end def o.to_r; nil; end assert_raise(TypeError) { Time.gm(2000, 1, 1, 0, 0, o, :foo, :foo) } - class << o; remove_method(:to_r); end def o.to_r; ""; end assert_raise(TypeError) { Time.gm(2000, 1, 1, 0, 0, o, :foo, :foo) } - class << o; remove_method(:to_r); end def o.to_r; Rational(11); end assert_equal(11, Time.gm(2000, 1, 1, 0, 0, o).sec) o = Object.new @@ -436,10 +421,6 @@ class TestTime < Test::Unit::TestCase assert_equal(-4427700000, Time.utc(-4427700000,12,1).year) assert_equal(-2**30+10, Time.utc(-2**30+10,1,1).year) - - assert_raise(ArgumentError) { Time.gm(2000, 1, -1) } - assert_raise(ArgumentError) { Time.gm(2000, 1, 2**30 + 1) } - assert_raise(ArgumentError) { Time.gm(2000, 1, -2**30 + 1) } end def test_time_interval @@ -562,30 +543,6 @@ class TestTime < Test::Unit::TestCase assert_equal(Time.at(946684800).getlocal.to_s, Time.at(946684800).to_s) end - def test_inspect - t2000 = get_t2000 - assert_equal("2000-01-01 00:00:00 UTC", t2000.inspect) - assert_equal(Encoding::US_ASCII, t2000.inspect.encoding) - assert_kind_of(String, Time.at(946684800).getlocal.inspect) - assert_equal(Time.at(946684800).getlocal.inspect, Time.at(946684800).inspect) - - t2000 = get_t2000 + 1/10r - assert_equal("2000-01-01 00:00:00.1 UTC", t2000.inspect) - t2000 = get_t2000 + 1/1000000000r - assert_equal("2000-01-01 00:00:00.000000001 UTC", t2000.inspect) - t2000 = get_t2000 + 1/10000000000r - assert_equal("2000-01-01 00:00:00 1/10000000000 UTC", t2000.inspect) - t2000 = get_t2000 + 0.1 - assert_equal("2000-01-01 00:00:00 3602879701896397/36028797018963968 UTC", t2000.inspect) - - t2000 = get_t2000 - t2000 = t2000.localtime(9*3600) - assert_equal("2000-01-01 09:00:00 +0900", t2000.inspect) - - t2000 = get_t2000.localtime(9*3600) + 1/10r - assert_equal("2000-01-01 09:00:00.1 +0900", t2000.inspect) - end - def assert_zone_encoding(time) zone = time.zone assert_predicate(zone, :valid_encoding?) @@ -599,18 +556,15 @@ class TestTime < Test::Unit::TestCase def test_zone assert_zone_encoding Time.now - t = Time.now.utc - assert_equal("UTC", t.zone) - assert_nil(t.getlocal(0).zone) - assert_nil(t.getlocal("+02:00").zone) end - def test_plus_minus + def test_plus_minus_succ t2000 = get_t2000 # assert_raise(RangeError) { t2000 + 10000000000 } # assert_raise(RangeError) t2000 - 3094168449 } # assert_raise(RangeError) { t2000 + 1200798848 } assert_raise(TypeError) { t2000 + Time.now } + assert_equal(t2000 + 1, t2000.succ) end def test_plus_type @@ -713,9 +667,7 @@ class TestTime < Test::Unit::TestCase assert_equal("12:00:00 AM", t2000.strftime("%r")) assert_equal("Sat 2000-01-01T00:00:00", t2000.strftime("%3a %FT%T")) - assert_warning(/strftime called with empty format string/) do - assert_equal("", t2000.strftime("")) - end + assert_equal("", t2000.strftime("")) assert_equal("foo\0bar\x0000\x0000\x0000", t2000.strftime("foo\0bar\0%H\0%M\0%S")) assert_equal("foo" * 1000, t2000.strftime("foo" * 1000)) @@ -895,13 +847,6 @@ class TestTime < Test::Unit::TestCase assert_equal(8192, Time.now.strftime('%8192z').size) end - def test_strftime_wide_precision - t2000 = get_t2000 - s = t2000.strftime("%28c") - assert_equal(28, s.size) - assert_equal(t2000.strftime("%c"), s.strip) - end - def test_strfimte_zoneoffset t2000 = get_t2000 t = t2000.getlocal("+09:00:00") @@ -1021,63 +966,6 @@ class TestTime < Test::Unit::TestCase } end - def test_floor - t = Time.utc(1999,12,31, 23,59,59) - t2 = (t+0.4).floor - assert_equal([59,59,23, 31,12,1999, 5,365,false,"UTC"], t2.to_a) - assert_equal(0, t2.subsec) - t2 = (t+0.49).floor - assert_equal([59,59,23, 31,12,1999, 5,365,false,"UTC"], t2.to_a) - assert_equal(0, t2.subsec) - t2 = (t+0.5).floor - assert_equal([59,59,23, 31,12,1999, 5,365,false,"UTC"], t2.to_a) - assert_equal(0, t2.subsec) - t2 = (t+1.4).floor - assert_equal([0,0,0, 1,1,2000, 6,1,false,"UTC"], t2.to_a) - assert_equal(0, t2.subsec) - t2 = (t+1.49).floor - assert_equal([0,0,0, 1,1,2000, 6,1,false,"UTC"], t2.to_a) - assert_equal(0, t2.subsec) - t2 = (t+1.5).floor - assert_equal([0,0,0, 1,1,2000, 6,1,false,"UTC"], t2.to_a) - assert_equal(0, t2.subsec) - - t2 = (t+0.123456789).floor(4) - assert_equal([59,59,23, 31,12,1999, 5,365,false,"UTC"], t2.to_a) - assert_equal(Rational(1234,10000), t2.subsec) - end - - def test_ceil - t = Time.utc(1999,12,31, 23,59,59) - t2 = (t+0.4).ceil - assert_equal([0,0,0, 1,1,2000, 6,1,false,"UTC"], t2.to_a) - assert_equal(0, t2.subsec) - t2 = (t+0.49).ceil - assert_equal([0,0,0, 1,1,2000, 6,1,false,"UTC"], t2.to_a) - assert_equal(0, t2.subsec) - t2 = (t+0.5).ceil - assert_equal([0,0,0, 1,1,2000, 6,1,false,"UTC"], t2.to_a) - assert_equal(0, t2.subsec) - t2 = (t+1.4).ceil - assert_equal([1,0,0, 1,1,2000, 6,1,false,"UTC"], t2.to_a) - assert_equal(0, t2.subsec) - t2 = (t+1.49).ceil - assert_equal([1,0,0, 1,1,2000, 6,1,false,"UTC"], t2.to_a) - assert_equal(0, t2.subsec) - t2 = (t+1.5).ceil - assert_equal([1,0,0, 1,1,2000, 6,1,false,"UTC"], t2.to_a) - assert_equal(0, t2.subsec) - - t2 = (t+0.123456789).ceil(4) - assert_equal([59,59,23, 31,12,1999, 5,365,false,"UTC"], t2.to_a) - assert_equal(Rational(1235,10000), t2.subsec) - - time = Time.utc(2016, 4, 23, 0, 0, 0.123456789r) - assert_equal(time, time.ceil(9)) - assert_equal(time, time.ceil(10)) - assert_equal(time, time.ceil(11)) - end - def test_getlocal_dont_share_eigenclass bug5012 = "[ruby-dev:44071]" @@ -1151,9 +1039,6 @@ class TestTime < Test::Unit::TestCase end def test_2038 - # Giveup to try 2nd test because some state is changed. - skip if Minitest::Unit.current_repeat_count > 0 - if no_leap_seconds? assert_equal(0x80000000, Time.utc(2038, 1, 19, 3, 14, 8).tv_sec) end @@ -1242,19 +1127,14 @@ class TestTime < Test::Unit::TestCase end def test_strftime_no_hidden_garbage - skip unless Thread.list.size == 1 - fmt = %w(Y m d).map { |x| "%#{x}" }.join('-') # defeats optimization t = Time.at(0).getutc ObjectSpace.count_objects(res = {}) # creates strings on first call - GC.disable before = ObjectSpace.count_objects(res)[:T_STRING] val = t.strftime(fmt) after = ObjectSpace.count_objects(res)[:T_STRING] assert_equal before + 1, after, 'only new string is the created one' assert_equal '1970-01-01', val - ensure - GC.enable end def test_num_exact_error @@ -1270,15 +1150,12 @@ class TestTime < Test::Unit::TestCase def test_memsize # Time objects are common in some code, try to keep them small skip "Time object size test" if /^(?:i.?86|x86_64)-linux/ !~ RUBY_PLATFORM - skip "GC is in debug" if GC::INTERNAL_CONSTANTS[:DEBUG] require 'objspace' t = Time.at(0) size = GC::INTERNAL_CONSTANTS[:RVALUE_SIZE] case size when 20 then expect = 50 - when 24 then expect = 54 when 40 then expect = 86 - when 48 then expect = 94 else flunk "Unsupported RVALUE_SIZE=#{size}, update test_memsize" end diff --git a/test/ruby/test_time_tz.rb b/test/ruby/test_time_tz.rb index dade0bff16..bfe9b4eef3 100644 --- a/test/ruby/test_time_tz.rb +++ b/test/ruby/test_time_tz.rb @@ -1,6 +1,5 @@ # frozen_string_literal: false require 'test/unit' -require '-test-/time' class TestTimeTZ < Test::Unit::TestCase has_right_tz = true @@ -9,7 +8,7 @@ class TestTimeTZ < Test::Unit::TestCase case RUBY_PLATFORM when /linux/ force_tz_test = true - when /darwin|freebsd|openbsd/ + when /darwin|freebsd/ has_lisbon_tz = false force_tz_test = true end @@ -226,29 +225,6 @@ class TestTimeTZ < Test::Unit::TestCase } end if has_right_tz - def test_right_utc_switching - with_tz("UTC") { # ensure no leap second timezone - assert_equal(4102444800, Time.utc(2100,1,1,0,0,0).to_i) - with_tz(tz="right/UTC") { - assert_time_constructor(tz, "2008-12-31 23:59:59 UTC", :utc, [2008,12,31,23,59,59]) - assert_time_constructor(tz, "2008-12-31 23:59:60 UTC", :utc, [2008,12,31,23,59,60]) - assert_time_constructor(tz, "2009-01-01 00:00:00 UTC", :utc, [2008,12,31,24,0,0]) - assert_time_constructor(tz, "2009-01-01 00:00:00 UTC", :utc, [2009,1,1,0,0,0]) - assert_not_equal(4102444800, Time.utc(2100,1,1,0,0,0).to_i) - } - } - with_tz("right/UTC") { - assert_not_equal(4102444800, Time.utc(2100,1,1,0,0,0).to_i) - with_tz(tz="UTC") { - assert_time_constructor(tz, "2008-12-31 23:59:59 UTC", :utc, [2008,12,31,23,59,59]) - assert_time_constructor(tz, "2009-01-01 00:00:00 UTC", :utc, [2008,12,31,23,59,60]) - assert_time_constructor(tz, "2009-01-01 00:00:00 UTC", :utc, [2008,12,31,24,0,0]) - assert_time_constructor(tz, "2009-01-01 00:00:00 UTC", :utc, [2009,1,1,0,0,0]) - assert_equal(4102444800, Time.utc(2100,1,1,0,0,0).to_i) - } - } - end if has_right_tz - def test_right_america_los_angeles with_tz(tz="right/America/Los_Angeles") { assert_time_constructor(tz, "2008-12-31 15:59:59 -0800", :local, [2008,12,31,15,59,59]) @@ -257,66 +233,6 @@ class TestTimeTZ < Test::Unit::TestCase } end if has_right_tz - def test_utc_names - assert_predicate(Time.new(2019, 1, 1, 0, 0, 0, "UTC"), :utc?) - assert_predicate(Time.new(2019, 1, 1, 0, 0, 0, "utc"), :utc?) - assert_predicate(Time.new(2019, 1, 1, 0, 0, 0, "Z"), :utc?) - end - - def test_military_names - assert_equal( +1*3600, Time.new(2019, 1, 1, 0, 0, 0, "A").gmtoff) - assert_equal( +2*3600, Time.new(2019, 1, 1, 0, 0, 0, "B").gmtoff) - assert_equal( +3*3600, Time.new(2019, 1, 1, 0, 0, 0, "C").gmtoff) - assert_equal( +4*3600, Time.new(2019, 1, 1, 0, 0, 0, "D").gmtoff) - assert_equal( +5*3600, Time.new(2019, 1, 1, 0, 0, 0, "E").gmtoff) - assert_equal( +6*3600, Time.new(2019, 1, 1, 0, 0, 0, "F").gmtoff) - assert_equal( +7*3600, Time.new(2019, 1, 1, 0, 0, 0, "G").gmtoff) - assert_equal( +8*3600, Time.new(2019, 1, 1, 0, 0, 0, "H").gmtoff) - assert_equal( +9*3600, Time.new(2019, 1, 1, 0, 0, 0, "I").gmtoff) - assert_equal(+10*3600, Time.new(2019, 1, 1, 0, 0, 0, "K").gmtoff) - assert_equal(+11*3600, Time.new(2019, 1, 1, 0, 0, 0, "L").gmtoff) - assert_equal(+12*3600, Time.new(2019, 1, 1, 0, 0, 0, "M").gmtoff) - assert_equal( -1*3600, Time.new(2019, 1, 1, 0, 0, 0, "N").gmtoff) - assert_equal( -2*3600, Time.new(2019, 1, 1, 0, 0, 0, "O").gmtoff) - assert_equal( -3*3600, Time.new(2019, 1, 1, 0, 0, 0, "P").gmtoff) - assert_equal( -4*3600, Time.new(2019, 1, 1, 0, 0, 0, "Q").gmtoff) - assert_equal( -5*3600, Time.new(2019, 1, 1, 0, 0, 0, "R").gmtoff) - assert_equal( -6*3600, Time.new(2019, 1, 1, 0, 0, 0, "S").gmtoff) - assert_equal( -7*3600, Time.new(2019, 1, 1, 0, 0, 0, "T").gmtoff) - assert_equal( -8*3600, Time.new(2019, 1, 1, 0, 0, 0, "U").gmtoff) - assert_equal( -9*3600, Time.new(2019, 1, 1, 0, 0, 0, "V").gmtoff) - assert_equal(-10*3600, Time.new(2019, 1, 1, 0, 0, 0, "W").gmtoff) - assert_equal(-11*3600, Time.new(2019, 1, 1, 0, 0, 0, "X").gmtoff) - assert_equal(-12*3600, Time.new(2019, 1, 1, 0, 0, 0, "Y").gmtoff) - assert_equal( 0, Time.new(2019, 1, 1, 0, 0, 0, "Z").gmtoff) - - assert_equal( +1*3600, Time.at(0, in: "A").gmtoff) - assert_equal( +2*3600, Time.at(0, in: "B").gmtoff) - assert_equal( +3*3600, Time.at(0, in: "C").gmtoff) - assert_equal( +4*3600, Time.at(0, in: "D").gmtoff) - assert_equal( +5*3600, Time.at(0, in: "E").gmtoff) - assert_equal( +6*3600, Time.at(0, in: "F").gmtoff) - assert_equal( +7*3600, Time.at(0, in: "G").gmtoff) - assert_equal( +8*3600, Time.at(0, in: "H").gmtoff) - assert_equal( +9*3600, Time.at(0, in: "I").gmtoff) - assert_equal(+10*3600, Time.at(0, in: "K").gmtoff) - assert_equal(+11*3600, Time.at(0, in: "L").gmtoff) - assert_equal(+12*3600, Time.at(0, in: "M").gmtoff) - assert_equal( -1*3600, Time.at(0, in: "N").gmtoff) - assert_equal( -2*3600, Time.at(0, in: "O").gmtoff) - assert_equal( -3*3600, Time.at(0, in: "P").gmtoff) - assert_equal( -4*3600, Time.at(0, in: "Q").gmtoff) - assert_equal( -5*3600, Time.at(0, in: "R").gmtoff) - assert_equal( -6*3600, Time.at(0, in: "S").gmtoff) - assert_equal( -7*3600, Time.at(0, in: "T").gmtoff) - assert_equal( -8*3600, Time.at(0, in: "U").gmtoff) - assert_equal( -9*3600, Time.at(0, in: "V").gmtoff) - assert_equal(-10*3600, Time.at(0, in: "W").gmtoff) - assert_equal(-11*3600, Time.at(0, in: "X").gmtoff) - assert_equal(-12*3600, Time.at(0, in: "Y").gmtoff) - assert_equal( 0, Time.at(0, in: "Z").gmtoff) - end - MON2NUM = { "Jan" => 1, "Feb" => 2, "Mar" => 3, "Apr" => 4, "May" => 5, "Jun" => 6, "Jul" => 7, "Aug" => 8, "Sep" => 9, "Oct" => 10, "Nov" => 11, "Dec" => 12 @@ -544,260 +460,4 @@ Europe/Lisbon Mon Jan 1 00:36:31 1912 UTC = Sun Dec 31 23:59:59 1911 LMT isdst 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 - - class TZ - attr_reader :name - - def initialize(name, abbr, offset, abbr2 = nil, offset2 = nil) - @name = name - @abbr = abbr - @offset = offset - @abbr2 = abbr2 - @offset2 = offset2 - end - - def dst?(t) - return false unless @offset2 - case t when Integer - return nil - end - case t.mon - when 4..9 - true - else - false - end - end - - def offset(t) - (dst?(t) ? @offset2 : @offset) - end - - def local_to_utc(t) - t - offset(t) - end - - def utc_to_local(t) - t + offset(t) - end - - def abbr(t) - dst?(t) ? @abbr2 : @abbr - end - - def ==(other) - @name == other.name and abbr(0) == other.abbr(0) and offset(0) == other.offset(0) - end - - def inspect - "#<TZ: #@name #@abbr #@offset>" - end - end -end - -module TestTimeTZ::WithTZ - def subtest_new(time_class, tz, tzarg, tzname, abbr, utc_offset) - abbr, abbr2 = *abbr - utc_offset, utc_offset2 = *utc_offset - t = time_class.new(2018, 9, 1, 12, 0, 0, tzarg) - utc_offset, abbr = utc_offset2, abbr2 if tz.dst?(t) - assert_equal([2018, 9, 1, 12, 0, 0, tz], [t.year, t.mon, t.mday, t.hour, t.min, t.sec, t.zone]) - h, m = (-utc_offset / 60).divmod(60) - assert_equal(time_class.utc(2018, 9, 1, 12+h, m, 0).to_i, t.to_i) - assert_equal(6, t.wday) - assert_equal(244, t.yday) - end - - def subtest_now(time_class, tz, tzarg, tzname, abbr, utc_offset) - t = time_class.now(in: tzarg) - assert_equal(tz, t.zone) - end - - def subtest_getlocal(time_class, tz, tzarg, tzname, abbr, utc_offset) - abbr, abbr2 = *abbr - utc_offset, utc_offset2 = *utc_offset - utc = time_class.utc(2018, 9, 1, 12, 0, 0) - utc_offset, abbr = utc_offset2, abbr2 if tz.dst?(utc) - t = utc.getlocal(tzarg) - h, m = (utc_offset / 60).divmod(60) - assert_equal([2018, 9, 1, 12+h, m, 0, tz], [t.year, t.mon, t.mday, t.hour, t.min, t.sec, t.zone]) - assert_equal(time_class.utc(2018, 9, 1, 12, 0, 0), t) - end - - def subtest_strftime(time_class, tz, tzarg, tzname, abbr, utc_offset) - abbr, abbr2 = *abbr - utc_offset, utc_offset2 = *utc_offset - t = time_class.new(2018, 9, 1, 12, 0, 0, tzarg) - utc_offset, abbr = utc_offset2, abbr2 if tz.dst?(t) - h, m = (utc_offset.abs / 60).divmod(60) - h = -h if utc_offset < 0 - assert_equal("%+.2d%.2d %s" % [h, m, abbr], t.strftime("%z %Z")) - assert_equal("34 35 35", t.strftime("%U %V %W")) - end - - def subtest_plus(time_class, tz, tzarg, tzname, abbr, utc_offset) - abbr, abbr2 = *abbr - utc_offset, utc_offset2 = *utc_offset - t = time_class.new(2018, 9, 1, 12, 0, 0, tzarg) + 4000 - utc_offset, abbr = utc_offset2, abbr2 if tz.dst?(t) - assert_equal([2018, 9, 1, 13, 6, 40, tz], [t.year, t.mon, t.mday, t.hour, t.min, t.sec, t.zone]) - m, s = (4000-utc_offset).divmod(60) - h, m = m.divmod(60) - assert_equal(time_class.utc(2018, 9, 1, 12+h, m, s), t) - end - - def subtest_at(time_class, tz, tzarg, tzname, abbr, utc_offset) - abbr, abbr2 = *abbr - utc_offset, utc_offset2 = *utc_offset - utc = time_class.utc(2018, 9, 1, 12, 0, 0) - utc_offset, abbr = utc_offset2, abbr2 if tz.dst?(utc) - h, m = (utc_offset / 60).divmod(60) - t = time_class.at(utc, in: tzarg) - assert_equal([2018, 9, 1, 12+h, m, 0, tz], [t.year, t.mon, t.mday, t.hour, t.min, t.sec, t.zone]) - assert_equal(utc.to_i, t.to_i) - utc = utc.to_i - t = time_class.at(utc, in: tzarg) - assert_equal([2018, 9, 1, 12+h, m, 0, tz], [t.year, t.mon, t.mday, t.hour, t.min, t.sec, t.zone]) - assert_equal(utc, t.to_i) - end - - def subtest_to_a(time_class, tz, tzarg, tzname, abbr, utc_offset) - t = time_class.new(2018, 9, 1, 12, 0, 0, tzarg) - ary = t.to_a - assert_equal(ary, [t.sec, t.min, t.hour, t.mday, t.mon, t.year, t.wday, t.yday, t.isdst, t.zone]) - end - - def subtest_marshal(time_class, tz, tzarg, tzname, abbr, utc_offset) - t = time_class.new(2018, 9, 1, 12, 0, 0, tzarg) - t2 = Marshal.load(Marshal.dump(t)) - assert_equal(t, t2) - assert_equal(t.utc_offset, t2.utc_offset) - assert_equal(t.utc_offset, (t2+1).utc_offset) - assert_instance_of(t.zone.class, t2.zone) - assert_equal(t.dst?, t2.dst?) - end - - def test_invalid_zone - make_timezone("INVALID", "INV", 0) - rescue => e - assert_kind_of(StandardError, e) - else - assert false, "ArgumentError expected but nothing was raised." - end - - def nametest_marshal_compatibility(time_class, tzname, abbr, utc_offset) - data = [ - "\x04\x08Iu:".b, Marshal.dump(time_class)[3..-1], - "\x0d""\xEF\xA7\x1D\x80\x00\x00\x00\x00".b, - Marshal.dump({offset: utc_offset, zone: abbr})[3..-1], - ].join('') - t = Marshal.load(data) - assert_equal(utc_offset, t.utc_offset) - assert_equal(utc_offset, (t+1).utc_offset) - # t.zone may be a mere String or timezone object. - end - - ZONES = { - "Asia/Tokyo" => ["JST", +9*3600], - "America/Los_Angeles" => ["PST", -8*3600, "PDT", -7*3600], - "Africa/Ndjamena" => ["WAT", +1*3600], - } - - def make_timezone(tzname, abbr, utc_offset, abbr2 = nil, utc_offset2 = nil) - self.class::TIME_CLASS.find_timezone(tzname) - end - - def subtest_dst?(time_class, tz, tzarg, tzname, abbr, utc_offset) - t = time_class.new(2018, 6, 22, 12, 0, 0, tzarg) - return unless tz.dst?(t) - assert_predicate t, :dst? - t = time_class.new(2018, 12, 22, 12, 0, 0, tzarg) - assert_not_predicate t, :dst? - end - - 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 - 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 - end - end - - instance_methods(false).grep(/\Aname(?=test_)/) do |subtest| - test = $' - ZONES.each_pair do |tzname, (abbr, utc_offset)| - define_method("#{test}@#{tzname}") do - time_class = self.class::TIME_CLASS - __send__(subtest, time_class, tzname, abbr, utc_offset) - end - end - end -end - -class TestTimeTZ::DummyTZ < Test::Unit::TestCase - include TestTimeTZ::WithTZ - - class TIME_CLASS < ::Time - ZONES = TestTimeTZ::WithTZ::ZONES - def self.find_timezone(tzname) - tz = ZONES[tzname] or raise ArgumentError, "Unknown timezone: #{name}" - TestTimeTZ::TZ.new(tzname, *tz) - end - end - - def self.make_timezone(tzname, abbr, utc_offset, abbr2 = nil, utc_offset2 = nil) - TestTimeTZ::TZ.new(tzname, abbr, utc_offset, abbr2, utc_offset2) - end - - def test_fractional_second - x = Object.new - def x.local_to_utc(t); t + 8*3600; end - def x.utc_to_local(t); t - 8*3600; end - - t1 = Time.new(2020,11,11,12,13,14.124r, '-08:00') - t2 = Time.new(2020,11,11,12,13,14.124r, x) - assert_equal(t1, t2) - end -end - -begin - require "tzinfo" -rescue LoadError -else - class TestTimeTZ::GemTZInfo < Test::Unit::TestCase - include TestTimeTZ::WithTZ - - class TIME_CLASS < ::Time - def self.find_timezone(tzname) - TZInfo::Timezone.get(tzname) - end - end - - def tz - @tz ||= TZInfo::Timezone.get(tzname) - end - end -end - -begin - require "timezone" -rescue LoadError -else - class TestTimeTZ::GemTimezone < Test::Unit::TestCase - include TestTimeTZ::WithTZ - - class TIME_CLASS < ::Time - def self.find_timezone(name) - Timezone.fetch(name) - end - end - - def tz - @tz ||= Timezone[tzname] - end - end end diff --git a/test/ruby/test_trace.rb b/test/ruby/test_trace.rb index 5842f11aee..77be94e9be 100644 --- a/test/ruby/test_trace.rb +++ b/test/ruby/test_trace.rb @@ -20,6 +20,17 @@ class TestTrace < Test::Unit::TestCase untrace_var :$x end + def test_trace_tainted_proc + $x = 1234 + s = proc { $y = :foo } + trace_var :$x, s + s.taint + $x = 42 + assert_equal(:foo, $y) + ensure + untrace_var :$x + end + def test_trace_proc_that_raises_exception $x = 1234 trace_var :$x, proc { raise } diff --git a/test/ruby/test_transcode.rb b/test/ruby/test_transcode.rb index 04c8248697..44d238ffd2 100644 --- a/test/ruby/test_transcode.rb +++ b/test/ruby/test_transcode.rb @@ -469,25 +469,6 @@ class TestTranscode < Test::Unit::TestCase check_both_ways("\u00A0", "\xFF", 'IBM437') # non-breaking space end - def test_IBM720 - assert_raise(Encoding::UndefinedConversionError) { "\x80".encode("utf-8", 'IBM720') } - assert_raise(Encoding::UndefinedConversionError) { "\x8F".encode("utf-8", 'IBM720') } - assert_raise(Encoding::UndefinedConversionError) { "\x90".encode("utf-8", 'IBM720') } - check_both_ways("\u0627", "\x9F", 'IBM720') # ا - check_both_ways("\u0628", "\xA0", 'IBM720') # ب - check_both_ways("\u00BB", "\xAF", 'IBM720') # » - check_both_ways("\u2591", "\xB0", 'IBM720') # ░ - check_both_ways("\u2510", "\xBF", 'IBM720') # ┐ - check_both_ways("\u2514", "\xC0", 'IBM720') # └ - check_both_ways("\u2567", "\xCF", 'IBM720') # ╧ - check_both_ways("\u2568", "\xD0", 'IBM720') # ╨ - check_both_ways("\u2580", "\xDF", 'IBM720') # ▀ - check_both_ways("\u0636", "\xE0", 'IBM720') # ض - check_both_ways("\u064A", "\xEF", 'IBM720') # ي - check_both_ways("\u2261", "\xF0", 'IBM720') # ≡ - check_both_ways("\u00A0", "\xFF", 'IBM720') # non-breaking space - end - def test_IBM775 check_both_ways("\u0106", "\x80", 'IBM775') # Ć check_both_ways("\u00C5", "\x8F", 'IBM775') # Å @@ -2135,28 +2116,6 @@ class TestTranscode < Test::Unit::TestCase check_both_ways("D\u00FCrst", "\xC4\xDC\x99\xA2\xA3", 'IBM037') # Dürst end - def test_CESU_8 - check_both_ways("aijrszAIJRSZ09", "aijrszAIJRSZ09", 'CESU-8') # single bytes - - # check NULL explicitly - # this is different in CESU-8 and in Java modified UTF-8 strings - check_both_ways("\0", "\0", 'CESU-8') - - # U+0080 U+00FC U+00FF U+0100 U+0400 U+0700 U+07FF - two_byte_chars = "\xC2\x80\x20\xC3\xBC\x20\xC3\xBF\x20\xC4\x80\x20\xD0\x80\x20\xDC\x80\x20\xDF\xBF" - check_both_ways(two_byte_chars, two_byte_chars, 'CESU-8') - - # U+0800 U+2200 U+4E00 U+D7FF U+E000 U+FFFF - three_byte_chars = "\xE0\xA0\x80\x20\xE2\x88\x80\x20\xE4\xB8\x80\x20\xED\x9F\xBF\x20\xEE\x80\x80\x20\xEF\xBF\xBF" - check_both_ways(three_byte_chars, three_byte_chars, 'CESU-8') - - # characters outside BMP (double surrogates in CESU-8) - # U+10000 U+20000 U+50000 U+10FFFF - utf8 = "\xF0\x90\x80\x80 \xF0\xA0\x80\x80 \xF1\x90\x80\x80 \xF4\x8F\xBF\xBF" - cesu = "\xED\xA0\x80\xED\xB0\x80 \xED\xA1\x80\xED\xB0\x80 \xED\xA4\x80\xED\xB0\x80 \xED\xAF\xBF\xED\xBF\xBF" - check_both_ways(utf8, cesu, 'CESU-8') - end - def test_nothing_changed a = "James".force_encoding("US-ASCII") b = a.encode("Shift_JIS") @@ -2202,14 +2161,6 @@ class TestTranscode < Test::Unit::TestCase assert_equal("U+3042", "\u{3042}".encode("US-ASCII", fallback: fallback.method(:escape))) end - def test_fallback_aref - fallback = Object.new - def fallback.[](x) - "U+%.4X" % x.unpack("U") - end - assert_equal("U+3042", "\u{3042}".encode("US-ASCII", fallback: fallback)) - end - bug8940 = '[ruby-core:57318] [Bug #8940]' %w[UTF-32 UTF-16].each do |enc| define_method("test_pseudo_encoding_inspect(#{enc})") do @@ -2269,19 +2220,12 @@ class TestTranscode < Test::Unit::TestCase "#{bug} coderange should not have side effects") end - def test_newline_options + def test_universal_newline bug11324 = '[ruby-core:69841] [Bug #11324]' usascii = Encoding::US_ASCII s = "A\nB\r\nC".force_encoding(usascii) assert_equal("A\nB\nC", s.encode(usascii, universal_newline: true), bug11324) assert_equal("A\nB\nC", s.encode(usascii, universal_newline: true, undef: :replace), bug11324) assert_equal("A\nB\nC", s.encode(usascii, universal_newline: true, undef: :replace, replace: ''), bug11324) - assert_equal("A\nB\nC", s.encode(usascii, newline: :universal)) - assert_equal("A\nB\nC", s.encode(usascii, newline: :universal, undef: :replace)) - assert_equal("A\nB\nC", s.encode(usascii, newline: :universal, undef: :replace, replace: '')) - assert_equal("A\rB\r\rC", s.encode(usascii, cr_newline: true)) - assert_equal("A\rB\r\rC", s.encode(usascii, newline: :cr)) - assert_equal("A\r\nB\r\r\nC", s.encode(usascii, crlf_newline: true)) - assert_equal("A\r\nB\r\r\nC", s.encode(usascii, newline: :crlf)) end end diff --git a/test/ruby/test_undef.rb b/test/ruby/test_undef.rb index e0add7c3ab..6d513a238f 100644 --- a/test/ruby/test_undef.rb +++ b/test/ruby/test_undef.rb @@ -25,7 +25,7 @@ class TestUndef < Test::Unit::TestCase y = Undef1.new assert_equal "bar", y.bar z = Undef2.new - assert_raise(NoMethodError) { z.bar } + assert_raise(NoMethodError) { z.foo } end def test_special_const_undef diff --git a/test/ruby/test_variable.rb b/test/ruby/test_variable.rb index 9795223fda..a9b1fd50ff 100644 --- a/test/ruby/test_variable.rb +++ b/test/ruby/test_variable.rb @@ -29,68 +29,9 @@ class TestVariable < Test::Unit::TestCase @@rule = "Cronus" # modifies @@rule in Gods include Olympians def ruler4 - @@rule - end - end - - def test_setting_class_variable_on_module_through_inheritance - mod = Module.new - mod.class_variable_set(:@@foo, 1) - mod.freeze - c = Class.new { include(mod) } - assert_raise(FrozenError) { c.class_variable_set(:@@foo, 2) } - assert_raise(FrozenError) { c.class_eval("@@foo = 2") } - assert_equal(1, c.class_variable_get(:@@foo)) - end - - def test_singleton_class_included_class_variable - c = Class.new - c.extend(Olympians) - assert_empty(c.singleton_class.class_variables) - assert_raise(NameError){ c.singleton_class.class_variable_get(:@@rule) } - c.class_variable_set(:@@foo, 1) - assert_equal([:@@foo], c.singleton_class.class_variables) - assert_equal(1, c.singleton_class.class_variable_get(:@@foo)) - - c = Class.new - c.extend(Olympians) - sc = Class.new(c) - assert_empty(sc.singleton_class.class_variables) - assert_raise(NameError){ sc.singleton_class.class_variable_get(:@@rule) } - c.class_variable_set(:@@foo, 1) - assert_equal([:@@foo], sc.singleton_class.class_variables) - assert_equal(1, sc.singleton_class.class_variable_get(:@@foo)) - - c = Class.new - o = c.new - o.extend(Olympians) - assert_equal([:@@rule], o.singleton_class.class_variables) - assert_equal("Zeus", o.singleton_class.class_variable_get(:@@rule)) - c.class_variable_set(:@@foo, 1) - assert_equal([:@@foo, :@@rule], o.singleton_class.class_variables.sort) - assert_equal(1, o.singleton_class.class_variable_get(:@@foo)) - end - - class IncludeRefinedModuleClassVariableNoWarning - module Mod - @@_test_include_refined_module_class_variable = true - end - - module Mod2 - refine Mod do - end - end - - include Mod - - def t - @@_test_include_refined_module_class_variable - end - end - - def test_include_refined_module_class_variable - assert_warning('') do - IncludeRefinedModuleClassVariableNoWarning.new.t + EnvUtil.suppress_warning { + @@rule + } end end @@ -115,7 +56,7 @@ class TestVariable < Test::Unit::TestCase atlas = Titans.new assert_equal("Cronus", atlas.ruler0) assert_equal("Zeus", atlas.ruler3) - assert_raise(RuntimeError) { atlas.ruler4 } + assert_equal("Cronus", atlas.ruler4) assert_nothing_raised do class << Gods defined?(@@rule) && @@rule @@ -194,7 +135,7 @@ class TestVariable < Test::Unit::TestCase def test_special_constant_ivars [ true, false, :symbol, "dsym#{rand(9999)}".to_sym, 1, 1.0 ].each do |v| assert_empty v.instance_variables - msg = "can't modify frozen #{v.class}: #{v.inspect}" + msg = "can't modify frozen #{v.class}" assert_raise_with_message(FrozenError, msg) do v.instance_variable_set(:@foo, :bar) @@ -209,25 +150,6 @@ class TestVariable < Test::Unit::TestCase end end - class ExIvar < Hash - def initialize - @a = 1 - @b = 2 - @c = 3 - end - - def ivars - [@a, @b, @c] - end - end - - def test_external_ivars - 3.times{ - # check inline cache for external ivar access - assert_equal [1, 2, 3], ExIvar.new.ivars - } - end - def test_local_variables_with_kwarg bug11674 = '[ruby-core:71437] [Bug #11674]' v = with_kwargs_11(v1:1,v2:2,v3:3,v4:4,v5:5,v6:6,v7:7,v8:8,v9:9,v10:10,v11:11) diff --git a/test/ruby/test_vm_dump.rb b/test/ruby/test_vm_dump.rb index 679ce94b91..68f0fa7f27 100644 --- a/test/ruby/test_vm_dump.rb +++ b/test/ruby/test_vm_dump.rb @@ -16,6 +16,6 @@ class TestVMDump < Test::Unit::TestCase end def test_darwin_invalid_access - assert_darwin_vm_dump_works(['-rfiddle', '-eFiddle.dlunwrap(100).inspect']) + assert_darwin_vm_dump_works(['-rfiddle', '-eFiddle.dlunwrap(100).class']) end end diff --git a/test/ruby/test_weakmap.rb b/test/ruby/test_weakmap.rb index 3b9eef770a..cde186c5f3 100644 --- a/test/ruby/test_weakmap.rb +++ b/test/ruby/test_weakmap.rb @@ -16,50 +16,30 @@ class TestWeakMap < Test::Unit::TestCase def test_aset_const x = Object.new - @wm[true] = x - assert_same(x, @wm[true]) - @wm[false] = x - assert_same(x, @wm[false]) - @wm[nil] = x - assert_same(x, @wm[nil]) - @wm[42] = x - assert_same(x, @wm[42]) - @wm[:foo] = x - assert_same(x, @wm[:foo]) - - @wm[x] = true - assert_same(true, @wm[x]) - @wm[x] = false - assert_same(false, @wm[x]) - @wm[x] = nil - assert_same(nil, @wm[x]) - @wm[x] = 42 - assert_same(42, @wm[x]) - @wm[x] = :foo - assert_same(:foo, @wm[x]) + assert_raise(ArgumentError) {@wm[true] = x} + assert_raise(ArgumentError) {@wm[false] = x} + assert_raise(ArgumentError) {@wm[nil] = x} + assert_raise(ArgumentError) {@wm[42] = x} + assert_raise(ArgumentError) {@wm[:foo] = x} + assert_raise(ArgumentError) {@wm[x] = true} + assert_raise(ArgumentError) {@wm[x] = false} + assert_raise(ArgumentError) {@wm[x] = nil} + assert_raise(ArgumentError) {@wm[x] = 42} + assert_raise(ArgumentError) {@wm[x] = :foo} end - def assert_weak_include(m, k, n = 100) - if n > 0 - return assert_weak_include(m, k, n-1) - end + def test_include? + m = __callee__[/test_(.*)/, 1] + k = "foo" 1.times do x = Object.new @wm[k] = x assert_send([@wm, m, k]) assert_not_send([@wm, m, "FOO".downcase]) - x = Object.new - end - end - - def test_include? - m = __callee__[/test_(.*)/, 1] - k = "foo" - 1.times do - assert_weak_include(m, k) + x = nil end GC.start - skip('TODO: failure introduced from r60440') + skip # TODO: failure introduced from r60440 assert_not_send([@wm, m, k]) end alias test_member? test_include? @@ -152,10 +132,4 @@ class TestWeakMap < Test::Unit::TestCase assert_equal(2, @wm.__send__(m)) end alias test_length test_size - - def test_frozen_object - o = Object.new.freeze - assert_nothing_raised(FrozenError) {@wm[o] = 'foo'} - assert_nothing_raised(FrozenError) {@wm['foo'] = o} - end end |
