diff options
Diffstat (limited to 'test/ruby')
103 files changed, 2017 insertions, 17221 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/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 33fb82e1d7..e81636fa43 100644 --- a/test/ruby/test_alias.rb +++ b/test/ruby/test_alias.rb @@ -47,6 +47,12 @@ class TestAlias < Test::Unit::TestCase assert_raise(NoMethodError) { x.quux } end + class C + def m + $SAFE + end + end + def test_nonexistmethod assert_raise(NameError){ Class.new{ diff --git a/test/ruby/test_argf.rb b/test/ruby/test_argf.rb index 5c2356524f..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 @@ -725,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| {# @@ -991,6 +964,7 @@ class TestArgf < Test::Unit::TestCase 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 @@ -1001,6 +975,7 @@ class TestArgf < Test::Unit::TestCase $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 @@ -1011,6 +986,7 @@ class TestArgf < Test::Unit::TestCase $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 @@ -1021,6 +997,7 @@ class TestArgf < Test::Unit::TestCase $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 755f54ac5a..0000000000 --- a/test/ruby/test_arithmetic_sequence.rb +++ /dev/null @@ -1,494 +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 = 1.step(10, by: 0) - assert_equal(1, seq.first) - assert_equal([1], seq.first(1)) - assert_equal([1, 1, 1], 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_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_last_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 - - seq = ((1/10r)..(1/2r)).step(0) - assert_equal(1/10r, seq.next) - 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 f2956a7fba..3212ed3aca 100644 --- a/test/ruby/test_array.rb +++ b/test/ruby/test_array.rb @@ -41,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) @@ -148,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)) @@ -167,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)) @@ -177,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] @@ -206,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 @@ -241,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) @@ -281,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 # '<<' @@ -389,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']} @@ -453,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 @@ -556,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 @@ -574,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! @@ -750,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 @@ -773,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) @@ -793,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) @@ -857,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) @@ -886,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 ] @@ -1128,6 +1085,20 @@ class TestArray < Test::Unit::TestCase assert_equal("1,2,3", a.join(',')) $, = "" + 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') @@ -1278,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 @@ -1403,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 @@ -1433,16 +1410,6 @@ class TestArray < Test::Unit::TestCase assert_nil(a.rindex([1,2])) assert_equal(3, 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) end def test_shift @@ -1492,14 +1459,14 @@ class TestArray < Test::Unit::TestCase assert_equal(@cls[99], a.slice(-2..-2)) assert_equal(@cls[10, 11, 12], a.slice(9..11)) - assert_equal(@cls[98, 99, 100], a.slice(97..)) - assert_equal(@cls[10, 11, 12], a.slice(-91..-89)) assert_equal(@cls[10, 11, 12], a.slice(-91..-89)) assert_nil(a.slice(-101..-1)) - assert_nil(a.slice(-101..)) 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 @@ -1540,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 @@ -1605,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 @@ -1675,7 +1632,7 @@ 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 @@ -1698,17 +1655,15 @@ class TestArray < Test::Unit::TestCase $, = 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) { @@ -1723,27 +1678,6 @@ 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(1, [1, 2, 3, 1, 2].min) assert_equal(3, [1, 2, 3, 1, 2].min {|a,b| b <=> a }) @@ -1787,25 +1721,6 @@ class TestArray < Test::Unit::TestCase assert_same(obj, [obj, 1.0].max) end - def test_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 @@ -1854,31 +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_instance_of(sc, a.uniq) - assert_equal(sc[], a.uniq) - assert_equal(b, a) - - a = sc[1] - b = a.dup - assert_instance_of(sc, a.uniq) - assert_equal(sc[1], a.uniq) - assert_equal(b, a) - - a = sc[1, 1] - b = a.dup - assert_instance_of(sc, a.uniq) - assert_equal(sc[1], a.uniq) - assert_equal(b, a) - - a = sc[1, 1] - b = a.dup - assert_instance_of(sc, a.uniq{|x| x}) - assert_equal(sc[1], a.uniq{|x| x}) - assert_equal(b, a) end def test_uniq_with_block @@ -2075,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) @@ -2347,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) @@ -2385,7 +2236,6 @@ class TestArray < Test::Unit::TestCase def test_aref assert_raise(ArgumentError) { [][0, 0, 0] } - assert_raise(TypeError) { [][(1..10).step(2)] } end def test_fetch @@ -2523,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) @@ -2635,6 +2466,9 @@ class TestArray < Test::Unit::TestCase 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) } @@ -2878,6 +2712,13 @@ class TestArray < Test::Unit::TestCase 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 } @@ -3081,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)}} @@ -3202,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) 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 171dbb6293..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,14 +52,6 @@ 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 @@ -76,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 } @@ -257,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 @@ -268,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; @@ -277,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 @@ -288,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; @@ -364,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) @@ -381,75 +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 - klass = self.class - bug = "Bug16764" - Dir.mktmpdir('autoload') do |tmpdir| - path = "#{tmpdir}/test-#{bug}.rb" - File.write(path, "#{klass}::#{bug} = __FILE__\n") - klass.autoload(:Bug16764, path) - assert_equal [__FILE__, __LINE__-1], klass.const_source_location(bug) - assert_equal path, klass.const_get(bug) - assert_equal [path, 1], klass.const_source_location(bug) - end - end - - def test_no_leak - assert_no_memory_leak([], '', <<~'end;', 'many autoloads', timeout: 60) - 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)} 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 ab32ee54e2..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 diff --git a/test/ruby/test_bignum.rb b/test/ruby/test_bignum.rb index 434c5befd9..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 @@ -611,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_class.rb b/test/ruby/test_class.rb index 46485c4fd2..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(LocalJumpError) { - 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 a4fe9d4232..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)} @@ -273,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) @@ -319,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) @@ -370,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 @@ -429,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 @@ -515,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 @@ -872,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) @@ -1116,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 1c73b66648..8784e0e988 100644 --- a/test/ruby/test_const.rb +++ b/test/ruby/test_const.rb @@ -48,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 e1571d5714..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 diff --git a/test/ruby/test_dir.rb b/test/ruby/test_dir.rb index 1bb228fd45..000bc24e85 100644 --- a/test/ruby/test_dir.rb +++ b/test/ruby/test_dir.rb @@ -11,13 +11,11 @@ class TestDir < Test::Unit::TestCase $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 @@ -122,7 +120,6 @@ class TestDir < Test::Unit::TestCase end def test_chroot_nodir - skip if RUBY_PLATFORM =~ /android/ assert_raise(NotImplementedError, Errno::ENOENT, Errno::EPERM ) { Dir.chroot(File.join(@nodir, "")) } end @@ -139,9 +136,8 @@ class TestDir < Test::Unit::TestCase 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_raise_with_message(ArgumentError, /nul-separated/) do - Dir.glob(@root + "\0\0\0" + File.join(@root, "*")) - end + 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) @@ -191,28 +187,6 @@ class TestDir < Test::Unit::TestCase 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) - 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 - if Process.const_defined?(:RLIMIT_NOFILE) def test_glob_too_may_open_files assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}", chdir: @root) @@ -234,38 +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).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}) - assert_equal(@dirs, Dir.glob("*/", base: @root).sort) - assert_equal(@dirs, Dir.chdir(@root) {Dir.glob("*/", base: ".").sort}) - assert_equal(%w[dir/], Dir.chdir(@root) {Dir.glob("*/", base: "a").sort}) - assert_equal(@dirs, Dir.chdir(@root) {Dir.glob("*/", base: "").sort}) - assert_equal(@dirs, Dir.chdir(@root) {Dir.glob("*/", base: nil).sort}) - assert_equal(dirs, Dir.glob("**/*/", base: @root).sort) - assert_equal(dirs, Dir.chdir(@root) {Dir.glob("**/*/", base: ".").sort}) - assert_equal(%w[dir/], Dir.chdir(@root) {Dir.glob("**/*/", base: "a").sort}) - assert_equal(dirs, Dir.chdir(@root) {Dir.glob("**/*/", base: "").sort}) - assert_equal(dirs, Dir.chdir(@root) {Dir.glob("**/*/", 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)}.sort) - 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).sort}) - assert_equal(%w[dir/], Dir.chdir(@root) {Dir.open("a") {|d| Dir.glob("*/", base: d).sort}}) - assert_equal(dirs, Dir.open(@root) {|d| Dir.glob("**/*/", base: d).sort}) - assert_equal(%w[dir/], Dir.chdir(@root) {Dir.open("a") {|d| Dir.glob("**/*/", 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) @@ -288,13 +242,11 @@ class TestDir < Test::Unit::TestCase 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")} 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} end @@ -392,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 @@ -465,11 +413,8 @@ 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("*").sort assert_not_empty(list) diff --git a/test/ruby/test_dir_m17n.rb b/test/ruby/test_dir_m17n.rb index c2c0c4999e..7584074c7e 100644 --- a/test/ruby/test_dir_m17n.rb +++ b/test/ruby/test_dir_m17n.rb @@ -18,7 +18,7 @@ class TestDir_M17N < Test::Unit::TestCase filename = #{code}.chr('UTF-8').force_encoding("#{encoding}") 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 @@ -26,7 +26,7 @@ class TestDir_M17N < Test::Unit::TestCase assert_separately(%w[-EASCII-8BIT], <<-EOS, :chdir=>dir) filename = #{code}.chr('UTF-8').force_encoding("ASCII-8BIT") opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM - ents = Dir.entries(".", **(opts||{})) + 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 @@ -35,7 +35,7 @@ class TestDir_M17N < Test::Unit::TestCase when ents.include?(expected_filename) filename = expected_filename else - ents = Dir.entries(".", :encoding => Encoding.find("filesystem")) + ents = Dir.entries(".", {:encoding => Encoding.find("filesystem")}) filename = expected_filename end end @@ -52,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 } @@ -67,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 @@ -75,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 @@ -88,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) @@ -125,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) @@ -151,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 @@ -159,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 @@ -183,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") @@ -200,7 +200,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").force_encoding("euc-jp") end @@ -210,14 +210,14 @@ class TestDir_M17N < Test::Unit::TestCase filename = "\xA4\xA2".force_encoding('ASCII-8BIT') 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||{})) + ents = Dir.entries(".", opts) unless ents.include?(filename) case RUBY_PLATFORM when /darwin/ filename = filename.encode("utf-8", "euc-jp").b when /mswin|mingw/ if ents.include?(win_expected_filename.b) - ents = Dir.entries(".", :encoding => Encoding.find("filesystem")) + ents = Dir.entries(".", {:encoding => Encoding.find("filesystem")}) filename = win_expected_filename end end @@ -246,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 @@ -255,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 @@ -420,7 +420,7 @@ class TestDir_M17N < Test::Unit::TestCase else orig.each {|o| o.force_encoding(enc) } end - ents = Dir.entries(".", **(opts||{})).reject {|n| /\A\./ =~ n} + ents = Dir.entries(".", opts).reject {|n| /\A\./ =~ n} ents.sort! PP.assert_equal(orig, ents, bug7267) } diff --git a/test/ruby/test_econv.rb b/test/ruby/test_econv.rb index a469614d84..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") } diff --git a/test/ruby/test_encoding.rb b/test/ruby/test_encoding.rb index 019cb2417f..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 @@ -117,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 ebb7e78381..2167271886 100644 --- a/test/ruby/test_enum.rb +++ b/test/ruby/test_enum.rb @@ -144,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] @@ -156,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, @@ -180,27 +175,6 @@ 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 }) @@ -228,13 +202,11 @@ class TestEnumerable < Test::Unit::TestCase assert_equal(15, [3, 5, 7].inject(:+)) assert_float_equal(15.0, [3, 5, 7.0].inject(:+)) assert_equal(2*FIXNUM_MAX, Array.new(2, FIXNUM_MAX).inject(:+)) - assert_equal(3*FIXNUM_MAX, Array.new(3, FIXNUM_MAX).inject(:+)) assert_equal(2*(FIXNUM_MAX+1), Array.new(2, FIXNUM_MAX+1).inject(:+)) assert_equal(10*FIXNUM_MAX, Array.new(10, FIXNUM_MAX).inject(:+)) assert_equal(0, ([FIXNUM_MAX, 1, -FIXNUM_MAX, -1]*10).inject(:+)) assert_equal(FIXNUM_MAX*10, ([FIXNUM_MAX+1, -1]*10).inject(:+)) assert_equal(2*FIXNUM_MIN, Array.new(2, FIXNUM_MIN).inject(:+)) - assert_equal(3*FIXNUM_MIN, Array.new(3, FIXNUM_MIN).inject(:+)) assert_equal((FIXNUM_MAX+1).to_f, [FIXNUM_MAX, 1, 0.0].inject(:+)) assert_float_equal(10.0, [3.0, 5].inject(2.0, :+)) assert_float_equal((FIXNUM_MAX+1).to_f, [0.0, FIXNUM_MAX+1].inject(:+)) @@ -296,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)) @@ -347,21 +314,6 @@ class TestEnumerable < Test::Unit::TestCase 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 }) @@ -377,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 })) @@ -411,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 })) @@ -443,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 }) @@ -737,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) @@ -1135,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 b619150571..66a45cc14e 100644 --- a/test/ruby/test_enumerator.rb +++ b/test/ruby/test_enumerator.rb @@ -72,6 +72,7 @@ class TestEnumerator < Test::Unit::TestCase _, 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 } @@ -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 02cd3b8502..ffed94efa6 100644 --- a/test/ruby/test_env.rb +++ b/test/ruby/test_env.rb @@ -46,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 @@ -112,6 +113,7 @@ class TestEnv < Test::Unit::TestCase assert_invalid_env {|v| ENV[v]} ENV[PATH_ENV] = "" assert_equal("", ENV[PATH_ENV]) + assert_predicate(ENV[PATH_ENV], :tainted?) assert_nil(ENV[""]) end @@ -120,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) @@ -134,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 @@ -151,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 @@ -216,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 } @@ -260,32 +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_clear ENV.clear assert_equal(0, ENV.size) @@ -358,6 +326,7 @@ class TestEnv < Test::Unit::TestCase assert_equal("foo", v) end assert_invalid_env {|var| ENV.assoc(var)} + assert_predicate(v, :tainted?) assert_equal(Encoding.find("locale"), v.encoding) end @@ -392,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 @@ -433,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 @@ -447,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 @@ -464,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} @@ -477,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| diff --git a/test/ruby/test_eval.rb b/test/ruby/test_eval.rb index 3d6116edbc..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,8 +359,28 @@ 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 + + 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 def test_nil_instance_eval_cvar @@ -469,12 +503,6 @@ class TestEval < Test::Unit::TestCase assert_same a, b end - def test_eval_location_binding - assert_warning(/__FILE__ in eval/) do - assert_equal(__FILE__, eval("__FILE__", binding)) - end - end - def test_fstring_instance_eval bug = "[ruby-core:78116] [Bug #12930]".freeze assert_same bug, (bug.instance_eval {self}) @@ -498,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 69bf7ebf0e..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 @@ -488,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 @@ -506,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]' @@ -550,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 @@ -682,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 @@ -790,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, {}} @@ -824,26 +837,6 @@ 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}) - end - end - def test_anonymous_message assert_in_out_err([], "raise Class.new(RuntimeError), 'foo'", [], /foo\n/) end @@ -855,166 +848,6 @@ end.join alias inspect pretty_inspect end - def test_frozen_error_receiver - obj = Object.new.freeze - (obj.foo = 1) rescue (e = $!) - assert_same(obj, e.receiver) - obj.singleton_class.const_set(:A, 2) rescue (e = $!) - assert_same(obj.singleton_class, e.receiver) - end - - def test_frozen_error_initialize - obj = Object.new - exc = FrozenError.new("bar", receiver: obj) - assert_equal("bar", exc.message) - assert_same(obj, exc.receiver) - - exc = FrozenError.new("bar") - assert_equal("bar", exc.message) - assert_raise_with_message(ArgumentError, "no receiver is available") { - exc.receiver - } - - exc = FrozenError.new - assert_equal("FrozenError", exc.message) - assert_raise_with_message(ArgumentError, "no receiver is available") { - exc.receiver - } - end - - def test_frozen_error_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_name_error_new_default - error = NameError.new - assert_equal("NameError", error.message) - end - - def test_name_error_new_message - error = NameError.new("Message") - assert_equal("Message", error.message) - end - - def test_name_error_new_name - error = NameError.new("Message") - assert_nil(error.name) - - error = NameError.new("Message", :foo) - assert_equal(:foo, error.name) - end - - def test_name_error_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 - - def test_nomethod_error_new_default - error = NoMethodError.new - assert_equal("NoMethodError", error.message) - end - - def test_nomethod_error_new_message - error = NoMethodError.new("Message") - assert_equal("Message", error.message) - end - - def test_nomethod_error_new_name - error = NoMethodError.new("Message") - assert_nil(error.name) - - error = NoMethodError.new("Message", :foo) - assert_equal(:foo, error.name) - end - - def test_nomethod_error_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_nomethod_error_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_nomethod_error_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 = defined?(DidYouMean.formatter) ? - "Message\nDid you mean? for" : "Message" - - error = NoMethodError.new("Message", :foo, receiver: receiver) - assert_equal([msg, :foo, receiver], - [error.message, error.name, error.receiver]) - - error = NoMethodError.new("Message", :foo, [1, 2]) - assert_raise(ArgumentError) {error.receiver} - - error = NoMethodError.new("Message", :foo, [1, 2], receiver: receiver) - assert_equal([msg, :foo, [1, 2], receiver], - [error.message, error.name, error.args, 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, [1, 2], true, receiver], - [error.name, error.args, error.private_call?, error.receiver]) - end - def test_name_error_info_const obj = PrettyObject.new @@ -1126,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 @@ -1180,7 +976,6 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status| def capture_warning_warn verbose = $VERBOSE - deprecated = Warning[:deprecated] warning = [] ::Warning.class_eval do @@ -1193,13 +988,11 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status| end $VERBOSE = true - Warning[:deprecated] = true yield return warning ensure $VERBOSE = verbose - Warning[:deprecated] = deprecated ::Warning.class_eval do remove_method :warn @@ -1220,21 +1013,8 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status| 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_equal("#{__FILE__}:#{__LINE__-1}: warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call\n", warning[0]) - assert_match(/warning: The called method (?:`.*' )?is defined here|warning: test warning/, warning[1]) - 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 @@ -1282,13 +1062,6 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status| }; 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_undefined_backtrace assert_separately([], "#{<<-"begin;"}\n#{<<-"end;"}") begin; @@ -1368,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) @@ -1408,43 +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/, '') - assert_operator(message, :start_with?, remark) - assert_operator(message, :end_with?, bottom) - else - assert_not_match(/\e/, message) - assert_operator(message, :start_with?, bottom) - assert_operator(message, :end_with?, top) - end end def test_exception_in_message @@ -1455,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 a7ed9ac7e0..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 RubyVM::MJIT.enabled? max = 10_000 assert_equal(max, max.times{ Fiber.new{} @@ -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,38 +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_transfer ary = [] f2 = nil @@ -302,27 +260,18 @@ class TestFiber < Test::Unit::TestCase 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 @@ -351,10 +300,8 @@ class TestFiber < Test::Unit::TestCase 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| - out, err, status = EnvUtil.invoke_ruby([env, '-e', script], '', true, true, chdir: tmpdir, timeout: 30) - assert(!status.signaled?, FailDesc[status, nil, err]) - out + out, _ = Dir.mktmpdir("test_fiber") {|tmpdir| + EnvUtil.invoke_ruby([env, '-e', script], '', true, true, chdir: tmpdir, timeout: 30) } use_length ? out.length : out end @@ -362,7 +309,7 @@ class TestFiber < Test::Unit::TestCase 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 * 5, 1024 * 1024 * 10, 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]) @@ -375,7 +322,7 @@ class TestFiber < Test::Unit::TestCase 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 * 5, nil + size_large = invoke_rec script, 1024 * 1024 * 10, nil assert_operator(size_default, :<, size_large) return if /mswin|mingw/ =~ RUBY_PLATFORM @@ -436,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 975bcb6bc2..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 @@ -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_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 7cbf3b5a8f..7fabfd351d 100644 --- a/test/ruby/test_float.rb +++ b/test/ruby/test_float.rb @@ -788,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?) @@ -807,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") {} 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_gc.rb b/test/ruby/test_gc.rb index ef99f69f50..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,7 +53,6 @@ class TestGc < Test::Unit::TestCase def test_start_full_mark return unless use_rgengc? - skip 'stress' if GC.stress GC.start(full_mark: false) assert_nil GC.latest_gc_info(:major_by) @@ -64,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) @@ -109,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 @@ -132,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] @@ -263,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 @@ -322,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 @@ -372,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 @@ -403,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 @@ -469,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 75d9b01f2c..0000000000 --- a/test/ruby/test_gc_compact.rb +++ /dev/null @@ -1,65 +0,0 @@ -# frozen_string_literal: true -require 'test/unit' -require 'fiddle' - -class TestGCCompact < Test::Unit::TestCase - 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 046ea40f5d..bdcf022668 100644 --- a/test/ruby/test_hash.rb +++ b/test/ruby/test_hash.rb @@ -149,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 @@ -279,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 @@ -315,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 # '==' @@ -342,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 @@ -436,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 @@ -651,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]) @@ -693,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 @@ -742,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 @@ -819,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 @@ -855,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) @@ -926,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]) @@ -1011,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 @@ -1033,42 +1014,6 @@ class TestHash < Test::Unit::TestCase assert_equal({}, {}.slice) 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] @@ -1137,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 @@ -1664,16 +1585,9 @@ class TestHash < Test::Unit::TestCase 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)) @@ -1697,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(*) @@ -1747,86 +1623,4 @@ class TestHash < Test::Unit::TestCase super 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 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_integer.rb b/test/ruby/test_integer.rb index a111698771..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?) @@ -640,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 306f0bcce0..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 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 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,50 +1691,112 @@ class TestIO < Test::Unit::TestCase f.gets; assert_equal(3, $.) end SRC + + 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_gets + def test_readline 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.readline; assert_equal(1, $.) + r.readline; assert_equal(2, $.) r.lineno = 1000; assert_equal(2, $.) - r.gets; assert_equal(1001, $.) - r.gets; assert_equal(1001, $.) + r.readline; assert_equal(1001, $.) + assert_raise(EOFError) { r.readline } end) end - def test_set_lineno_readline + def test_each_char pipe(proc do |w| w.puts "foo" w.puts "bar" w.puts "baz" w.close end, proc do |r| - r.readline; assert_equal(1, $.) - r.readline; assert_equal(2, $.) - r.lineno = 1000; assert_equal(2, $.) - r.readline; assert_equal(1001, $.) - assert_raise(EOFError) { r.readline } + a = [] + r.each_char {|c| a << c } + assert_equal(%w(f o o) + ["\n"] + %w(b a r) + ["\n"] + %w(b a z) + ["\n"], a) end) end - def test_each_char + def test_lines + verbose, $VERBOSE = $VERBOSE, nil pipe(proc do |w| w.puts "foo" w.puts "bar" w.puts "baz" w.close end, proc do |r| - a = [] - r.each_char {|c| a << c } - assert_equal(%w(f o o) + ["\n"] + %w(b a r) + ["\n"] + %w(b a z) + ["\n"], a) + e = nil + 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_bytes + verbose, $VERBOSE = $VERBOSE, nil + pipe(proc do |w| + w.binmode + w.puts "foo" + w.puts "bar" + w.puts "baz" + w.close + end, proc do |r| + e = nil + 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_chars + verbose, $VERBOSE = $VERBOSE, nil + pipe(proc do |w| + w.puts "foo" + w.puts "bar" + w.puts "baz" + w.close + end, proc do |r| + e = nil + 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 @@ -1871,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) @@ -2153,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 RubyVM::MJIT.enabled? - feature2250 = '[ruby-core:26222]' pre = 'ft2250' t = Tempfile.new(pre) @@ -2172,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 @@ -2202,33 +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)) - - w = /Using the last argument as keyword parameters is deprecated.*The called method `(to_)?open'/m - redefined = nil - w.singleton_class.define_method(:===) do |s| - match = super(s) - redefined = !$1 - match - end - - assert_warn(w) do - assert_equal({:a=>1}, open(o, {a: 1})) - end - - class << o - remove_method(:to_open) - end - def o.to_open(kw); kw; end - assert_equal({:a=>1}, open(o, a: 1)) - unless redefined - assert_equal({:a=>1}, open(o, {a: 1})) - end - end - def test_open_pipe open("|" + EnvUtil.rubybin, "r+") do |f| f.puts "puts 'foo'" @@ -2239,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 @@ -2251,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 @@ -2297,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 @@ -2364,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 @@ -2439,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 = [] @@ -2503,7 +2460,7 @@ class TestIO < Test::Unit::TestCase end def test_print_separators - EnvUtil.suppress_warning {$, = ':'} + $, = ':' $\ = "\n" pipe(proc do |w| w.print('a') @@ -2590,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 @@ -2604,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| @@ -2691,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} @@ -2714,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 @@ -2722,6 +2686,7 @@ __END__ end def test_flush_in_finalizer1 + require 'tempfile' bug3910 = '[ruby-dev:42341]' tmp = Tempfile.open("bug3910") {|t| path = t.path @@ -2747,6 +2712,7 @@ __END__ end def test_flush_in_finalizer2 + require 'tempfile' bug3910 = '[ruby-dev:42341]' Tempfile.open("bug3910") {|t| path = t.path @@ -2880,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 @@ -3062,9 +3028,7 @@ __END__ assert_equal(1, File.write(path, "f", 0, encoding: "UTF-8")) assert_equal("ff", File.read(path)) assert_raise(TypeError) { - assert_warn(/The last argument is split into positional and keyword parameters/) do - File.write(path, "foo", Object.new => Object.new) - end + File.write(path, "foo", Object.new => Object.new) } end end @@ -3191,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 @@ -3287,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) @@ -3579,17 +3548,8 @@ __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| @@ -3611,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 @@ -3736,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| @@ -3758,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 @@ -3799,81 +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_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], <<-"end;", <<-"end;", rss: true, timeout: 60) + 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 end; - 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 + 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 end diff --git a/test/ruby/test_io_m17n.rb b/test/ruby/test_io_m17n.rb index e5b0ef0585..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) @@ -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 709061d54a..ed88c9b43d 100644 --- a/test/ruby/test_iseq.rb +++ b/test/ruby/test_iseq.rb @@ -91,11 +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 LINE_BEFORE_METHOD = __LINE__ @@ -246,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 @@ -259,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 @@ -283,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 @@ -387,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 @@ -403,169 +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)") + assert_equal(iseq2.to_a, iseq.to_a) 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]") + 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 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) - 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; - 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} - } - - 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 + ISeq.load_from_binary(iseq_bin).eval } - 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) + 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 54c095338f..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}) diff --git a/test/ruby/test_jit.rb b/test/ruby/test_jit.rb deleted file mode 100644 index e3d8f9cee2..0000000000 --- a/test/ruby/test_jit.rb +++ /dev/null @@ -1,1124 +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/, - /\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, - :opt_call_c_function, - - # 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 setup - unless JITSupport.supported? - skip 'JIT seems not supported on this platform' - end - - # ruby -w -Itest/lib test/ruby/test_jit.rb - if $VERBOSE && !defined?(@@at_exit_hooked) - 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 - @@at_exit_hooked = true - end - 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_freezestring - assert_eval_with_jit("#{<<~"begin;"}\n#{<<~'end;'}", stdout: 'true', success_count: 1, insns: %i[freezestring]) - begin; - # frozen_string_literal: true - print proc { "#{true}".frozen? }.call - end; - 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: 2, 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_call_c_function - skip "support this in opt_call_c_function (low priority)" - end - - def test_compile_insn_opt_invokebuiltin_delegate_leave - insns = collect_insns(RubyVM::InstructionSequence.of("\x00".method(:unpack)).to_a) - 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("Too many JIT code -- 1 units unloaded\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(3, 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 .o files are deleted on unload_units - assert_send([Dir, :empty?, dir], debug_info) - end - 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_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 - - verbose, $VERBOSE = $VERBOSE, false # suppress "instance variable @b not initialized" - print(Foo.new.bar) - print(Foo.new.bar) - print(Foo.new.bar) - $VERBOSE = verbose - 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_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 Numeric - 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_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:, 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) - actual = err.scan(/^#{JIT_SUCCESS_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 != 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 - - assert_equal( - success_count, actual, - "Expected #{success_count} times of JIT success, but succeeded #{actual} times.\n\n"\ - "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 - )}", - ) - 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_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 ab3c11e149..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,9 +22,7 @@ class TestKeywordArguments < Test::Unit::TestCase def test_f2 assert_equal([:xyz, "foo", 424242], f2(:xyz)) - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `f2'/m) do - assert_equal([{"bar"=>42}, "foo", 424242], f2("bar"=>42)) - end + assert_equal([{"bar"=>42}, "foo", 424242], f2("bar"=>42)) end @@ -130,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); @@ -192,3806 +147,6 @@ class TestKeywordArguments < Test::Unit::TestCase assert_equal(["bar", 111111], f[str: "bar", num: 111111]) 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_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, c.m(**{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, c.m(**kw)) - end - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m'/m) do - assert_equal(h, c.m(h)) - end - assert_raise(ArgumentError) { c.m(h2) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `m'/m) do - assert_raise(ArgumentError) { c.m(h3) } - end - - c.singleton_class.remove_method(:m) - def c.m(arg, **args) - [arg, args] - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - c.m(**{}) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - c.m(**kw) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], c.m(**h)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], c.m(a: 1)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h2, kw], c.m(**h2)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], c.m(**h3)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], c.m(a: 1, **h2)) - end - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m'/m) do - assert_equal([1, h], c.m(h)) - end - assert_equal([h2, kw], c.m(h2)) - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `m'/m) do - assert_equal([h2, h], c.m(h3)) - end - end - - def test_implicit_super_kwsplat - kw = {} - h = {:a=>1} - h2 = {'a'=>1} - h3 = {'a'=>1, :a=>1} - - sc = Class.new - c = sc.new - redef = -> do - if defined?(c.m) - class << c - remove_method(:m) - end - end - eval <<-END - def c.m(*args, **kw) - super(*args, **kw) - end - END - end - redef[] - 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_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, c.m(**{})) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, c.m(**kw)) - end - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m'/m) do - assert_equal(h, c.m(h)) - end - assert_raise(ArgumentError) { c.m(h2) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `m'/m) do - assert_raise(ArgumentError) { c.m(h3) } - end - - sc.class_eval do - remove_method(:m) - def m(arg, **args) - [arg, args] - end - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - c.m(**{}) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - c.m(**kw) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], c.m(**h)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], c.m(a: 1)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h2, kw], c.m(**h2)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], c.m(**h3)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], c.m(a: 1, **h2)) - end - - 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 - redef = -> do - if defined?(c.m) - class << c - remove_method(:m) - end - end - eval <<-END - def c.m(*args, **kw) - super(*args, **kw) - end - END - end - redef[] - 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_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, c.m(**{})) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, c.m(**kw)) - end - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m'/m) do - assert_equal(h, c.m(h)) - end - assert_raise(ArgumentError) { c.m(h2) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `m'/m) do - assert_raise(ArgumentError) { c.m(h3) } - end - - sc.class_eval do - remove_method(:m) - def m(arg, **args) - [arg, args] - end - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - c.m(**{}) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - c.m(**kw) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], c.m(**h)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], c.m(a: 1)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h2, kw], c.m(**h2)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], c.m(**h3)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], c.m(a: 1, **h2)) - end - - 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_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal(kw, f[**{}]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal(kw, f[**kw]) - end - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method `\[\]'/m) do - assert_equal(h, f[h]) - end - assert_raise(ArgumentError) { f[h2] } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `\[\]'/m) do - assert_raise(ArgumentError) { f[h3] } - end - - f = ->(a, **x) { [a,x] } - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `\[\]'/m) do - assert_equal([{}, {}], f[**{}]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `\[\]'/m) do - assert_equal([{}, {}], f[**kw]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `\[\]'/m) do - assert_equal([h, {}], f[**h]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `\[\]'/m) do - assert_equal([h, {}], f[a: 1]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `\[\]'/m) do - assert_equal([h2, {}], f[**h2]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `\[\]'/m) do - assert_equal([h3, {}], f[**h3]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `\[\]'/m) do - assert_equal([h3, {}], f[a: 1, **h2]) - end - - 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_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal(kw, f[**{}]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal(kw, f[**kw]) - end - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(h, f[h]) - end - assert_raise(ArgumentError) { f[h2] } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method is defined here/m) do - assert_raise(ArgumentError) { f[h3] } - end - - f = ->(a, **x) { [a,x] } - f = f.method(:call) - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([{}, {}], f[**{}]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([{}, {}], f[**kw]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h, {}], f[**h]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h, {}], f[a: 1]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h2, {}], f[**h2]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h3, {}], f[**h3]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h3, {}], f[a: 1, **h2]) - end - - 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_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal(kw, t.new(**{}, &f).value) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal(kw, t.new(**kw, &f).value) - end - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(h, t.new(h, &f).value) - end - assert_raise(ArgumentError) { t.new(h2, &f).value } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method is defined here/m) do - assert_raise(ArgumentError) { t.new(h3, &f).value } - end - - f = ->(a, **x) { [a,x] } - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([{}, {}], t.new(**{}, &f).value) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([{}, {}], t.new(**kw, &f).value) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h, {}], t.new(**h, &f).value) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h, {}], t.new(a: 1, &f).value) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h2, {}], t.new(**h2, &f).value) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h3, {}], t.new(**h3, &f).value) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h3, {}], t.new(a: 1, **h2, &f).value) - end - - 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_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal(kw, t.new(&f).resume(**{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal(kw, t.new(&f).resume(**kw)) - end - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(h, t.new(&f).resume(h)) - end - assert_raise(ArgumentError) { t.new(&f).resume(h2) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method is defined here/m) do - assert_raise(ArgumentError) { t.new(&f).resume(h3) } - end - - f = ->(a, **x) { [a,x] } - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([{}, {}], t.new(&f).resume(**{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([{}, {}], t.new(&f).resume(**kw)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h, {}], t.new(&f).resume(**h)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h, {}], t.new(&f).resume(a: 1)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h2, {}], t.new(&f).resume(**h2)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h3, {}], t.new(&f).resume(**h3)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h3, {}], t.new(&f).resume(a: 1, **h2)) - end - - 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_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal(kw, g.new(&f).each(**{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal(kw, g.new(&f).each(**kw)) - end - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(h, g.new(&f).each(h)) - end - assert_raise(ArgumentError) { g.new(&f).each(h2) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method is defined here/m) do - assert_raise(ArgumentError) { g.new(&f).each(h3) } - end - - f = ->(_, a, **x) { [a,x] } - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([{}, {}], g.new(&f).each(**{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([{}, {}], g.new(&f).each(**kw)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h, {}], g.new(&f).each(**h)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h, {}], g.new(&f).each(a: 1)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h2, {}], g.new(&f).each(**h2)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h3, {}], g.new(&f).each(**h3)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h3, {}], g.new(&f).each(a: 1, **h2)) - end - - 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_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal(kw, g.new{|y| y.yield(**{})}.each(&f)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal(kw, g.new{|y| y.yield(**kw)}.each(&f)) - end - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(h, g.new{|y| y.yield(h)}.each(&f)) - end - assert_raise(ArgumentError) { g.new{|y| y.yield(h2)}.each(&f) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method is defined here/m) do - assert_raise(ArgumentError) { g.new{|y| y.yield(h3)}.each(&f) } - end - - f = ->(a, **x) { [a,x] } - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([{}, {}], g.new{|y| y.yield(**{})}.each(&f)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([{}, {}], g.new{|y| y.yield(**kw)}.each(&f)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h, {}], g.new{|y| y.yield(**h)}.each(&f)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h, {}], g.new{|y| y.yield(a: 1)}.each(&f)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h2, {}], g.new{|y| y.yield(**h2)}.each(&f)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h3, {}], g.new{|y| y.yield(**h3)}.each(&f)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h3, {}], g.new{|y| y.yield(a: 1, **h2)}.each(&f)) - end - - 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_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do - assert_equal(kw, c[**{}].args) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do - assert_equal(kw, c[**kw].args) - end - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method `initialize'/m) do - assert_equal(h, c[h].args) - end - assert_raise(ArgumentError) { c[h2].args } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `initialize'/m) do - assert_raise(ArgumentError) { c[h3].args } - end - - c = Class.new(sc) do - def initialize(arg, **args) - @args = [arg, args] - end - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do - assert_equal([kw, kw], c[**{}].args) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do - assert_equal([kw, kw], c[**kw].args) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do - assert_equal([h, kw], c[**h].args) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do - assert_equal([h, kw], c[a: 1].args) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do - assert_equal([h2, kw], c[**h2].args) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do - assert_equal([h3, kw], c[**h3].args) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do - assert_equal([h3, kw], c[a: 1, **h2].args) - end - - 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_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do - assert_equal(kw, c[**{}].args) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do - assert_equal(kw, c[**kw].args) - end - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method `initialize'/m) do - assert_equal(h, c[h].args) - end - assert_raise(ArgumentError) { c[h2].args } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `initialize'/m) do - assert_raise(ArgumentError) { c[h3].args } - end - - c = Class.new(sc) do - def initialize(arg, **args) - @args = [arg, args] - end - end.method(:new) - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do - assert_equal([kw, kw], c[**{}].args) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do - assert_equal([kw, kw], c[**kw].args) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do - assert_equal([h, kw], c[**h].args) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do - assert_equal([h, kw], c[a: 1].args) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do - assert_equal([h2, kw], c[**h2].args) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do - assert_equal([h3, kw], c[**h3].args) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do - assert_equal([h3, kw], c[a: 1, **h2].args) - end - - 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_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, c.method(:m)[**{}]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, c.method(:m)[**kw]) - end - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m'/m) do - assert_equal(h, c.method(:m)[h]) - end - assert_raise(ArgumentError) { c.method(:m)[h2] } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `m'/m) do - assert_raise(ArgumentError) { c.method(:m)[h3] } - end - - c.singleton_class.remove_method(:m) - def c.m(arg, **args) - [arg, args] - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([kw, kw], c.method(:m)[**{}]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([kw, kw], c.method(:m)[**kw]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], c.method(:m)[**h]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], c.method(:m)[a: 1]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h2, kw], c.method(:m)[**h2]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], c.method(:m)[**h3]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], c.method(:m)[a: 1, **h2]) - end - - 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_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, sc.instance_method(:m).bind_call(c, **{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, sc.instance_method(:m).bind_call(c, **kw)) - end - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m'/m) do - assert_equal(h, sc.instance_method(:m).bind_call(c, h)) - end - assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, h2) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `m'/m) do - assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, h3) } - end - - sc.remove_method(:m) - def c.m(arg, **args) - [arg, args] - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([kw, kw], sc.instance_method(:m).bind_call(c, **{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([kw, kw], sc.instance_method(:m).bind_call(c, **kw)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], sc.instance_method(:m).bind_call(c, **h)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], sc.instance_method(:m).bind_call(c, a: 1)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h2, kw], sc.instance_method(:m).bind_call(c, **h2)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], sc.instance_method(:m).bind_call(c, **h3)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], sc.instance_method(:m).bind_call(c, a: 1, **h2)) - end - - 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_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, c.send(:m, **{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, c.send(:m, **kw)) - end - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m'/m) do - assert_equal(h, c.send(:m, h)) - end - assert_raise(ArgumentError) { c.send(:m, h2) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `m'/m) do - assert_raise(ArgumentError) { c.send(:m, h3) } - end - - c.singleton_class.remove_method(:m) - def c.m(arg, **args) - [arg, args] - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - c.send(:m, **{}) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - c.send(:m, **kw) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], c.send(:m, **h)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], c.send(:m, a: 1)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h2, kw], c.send(:m, **h2)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], c.send(:m, **h3)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], c.send(:m, a: 1, **h2)) - end - - 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_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, c.public_send(:m, **{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, c.public_send(:m, **kw)) - end - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m'/m) do - assert_equal(h, c.public_send(:m, h)) - end - assert_raise(ArgumentError) { c.public_send(:m, h2) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `m'/m) do - assert_raise(ArgumentError) { c.public_send(:m, h3) } - end - - c.singleton_class.remove_method(:m) - def c.m(arg, **args) - [arg, args] - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - c.public_send(:m, **{}) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - c.public_send(:m, **kw) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], c.public_send(:m, **h)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], c.public_send(:m, a: 1)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h2, kw], c.public_send(:m, **h2)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], c.public_send(:m, **h3)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], c.public_send(:m, a: 1, **h2)) - end - - 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_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, m.call(:m, **{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, m.call(:m, **kw)) - end - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m'/m) do - assert_equal(h, m.call(:m, h)) - end - assert_raise(ArgumentError) { m.call(:m, h2) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `m'/m) do - assert_raise(ArgumentError) { m.call(:m, h3) } - end - - c.singleton_class.remove_method(:m) - def c.m(arg, **args) - [arg, args] - end - m = c.method(:send) - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - m.call(:m, **{}) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - m.call(:m, **kw) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], m.call(:m, **h)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], m.call(:m, a: 1)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h2, kw], m.call(:m, **h2)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], m.call(:m, **h3)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], m.call(:m, a: 1, **h2)) - end - - 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_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, :m.to_proc.call(c, **{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, :m.to_proc.call(c, **kw)) - end - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m'/m) do - assert_equal(h, :m.to_proc.call(c, h)) - end - assert_raise(ArgumentError) { :m.to_proc.call(c, h2) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `m'/m) do - assert_raise(ArgumentError) { :m.to_proc.call(c, h3) } - end - - c.singleton_class.remove_method(:m) - def c.m(arg, **args) - [arg, args] - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([kw, kw], :m.to_proc.call(c, **{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([kw, kw], :m.to_proc.call(c, **kw)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], :m.to_proc.call(c, **h)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], :m.to_proc.call(c, a: 1)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h2, kw], :m.to_proc.call(c, **h2)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], :m.to_proc.call(c, **h3)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], :m.to_proc.call(c, a: 1, **h2)) - end - - 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_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, m.call(c, **{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, m.call(c, **kw)) - end - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m'/m) do - assert_equal(h, m.call(c, h)) - end - assert_raise(ArgumentError) { m.call(c, h2) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `m'/m) do - assert_raise(ArgumentError) { m.call(c, h3) } - end - - c.singleton_class.remove_method(:m) - def c.m(arg, **args) - [arg, args] - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([kw, kw], m.call(c, **{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([kw, kw], m.call(c, **kw)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], m.call(c, **h)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], m.call(c, a: 1)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h2, kw], m.call(c, **h2)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], m.call(c, **h3)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], m.call(c, a: 1, **h2)) - end - - 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_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal(kw, c.m(**{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal(kw, c.m(**kw)) - end - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method `method_missing'/m) do - assert_equal(h, c.m(h)) - end - assert_raise(ArgumentError) { c.m(h2) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `method_missing'/m) do - assert_raise(ArgumentError) { c.m(h3) } - end - - c.singleton_class.remove_method(:method_missing) - def c.method_missing(_, arg, **args) - [arg, args] - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([kw, kw], c.m(**{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([kw, kw], c.m(**kw)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h, kw], c.m(**h)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h, kw], c.m(a: 1)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h2, kw], c.m(**h2)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h3, kw], c.m(**h3)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h3, kw], c.m(a: 1, **h2)) - end - - 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) } - - redef = -> do - c.singleton_class.remove_method(:method_missing) - eval <<-END - def c.method_missing(_, args) - args - end - END - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal(kw, c.m(**{})) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal(kw, c.m(**kw)) - end - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m'/m) do - assert_equal(h, c.m(h)) - end - assert_raise(ArgumentError) { c.m(h2) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `m'/m) do - assert_raise(ArgumentError) { c.m(h3) } - end - - redef = -> do - c.singleton_class.remove_method(:method_missing) - eval <<-END - def c.method_missing(_, arg, **args) - [arg, args] - end - END - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([kw, kw], c.m(**{})) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([kw, kw], c.m(**kw)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h, kw], c.m(**h)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h, kw], c.m(a: 1)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h2, kw], c.m(**h2)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h3, kw], c.m(**h3)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h3, kw], c.m(a: 1, **h2)) - end - - 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_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal(kw, c.m(**{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal(kw, c.m(**kw)) - end - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method `method_missing'/m) do - assert_equal(h, c.m(h)) - end - assert_raise(ArgumentError) { c.m(h2) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `method_missing'/m) do - assert_raise(ArgumentError) { c.m(h3) } - end - - c.singleton_class.remove_method(:method_missing) - def c.method_missing(_, arg, **args) - [arg, args] - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([kw, kw], c.m(**{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([kw, kw], c.m(**kw)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h, kw], c.m(**h)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h, kw], c.m(a: 1)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h2, kw], c.m(**h2)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h3, kw], c.m(**h3)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h3, kw], c.m(a: 1, **h2)) - end - - 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_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal(kw, c.m(**{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal(kw, c.m(**kw)) - end - 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_warn(/Using the last argument as keyword parameters is deprecated/m) do - assert_equal(h, c.m(h)) - end - assert_raise(ArgumentError) { c.m(h2) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated/m) do - assert_raise(ArgumentError) { c.m(h3) } - end - - c = Object.new - class << c - define_method(:m) {|arg, **opt| [arg, opt] } - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal([kw, kw], c.m(**{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal([kw, kw], c.m(**kw)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal([h, kw], c.m(**h)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal([h, kw], c.m(a: 1)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal([h2, kw], c.m(**h2)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal([h3, kw], c.m(**h3)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal([h3, kw], c.m(a: 1, **h2)) - end - - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal([[], h], c.m(h)) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal([[h], h], c.m(h, h)) - end - - c = Object.new - class << c - define_method(:m) {|arg=nil, a: nil| [arg, a] } - end - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal([h2, 1], c.m(h3)) - end - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal([h2, 1], c.m(**h3)) - end - 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_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal(kw, m.call(**{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal(kw, m.call(**kw)) - end - 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_warn(/Using the last argument as keyword parameters is deprecated/m) do - assert_equal(h, m.call(h)) - end - assert_raise(ArgumentError) { m.call(h2) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated/m) do - assert_raise(ArgumentError) { m.call(h3) } - end - - c = Object.new - class << c - define_method(:m) {|arg, **opt| [arg, opt] } - end - m = c.method(:m) - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal([kw, kw], m.call(**{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal([kw, kw], m.call(**kw)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal([h, kw], m.call(**h)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal([h, kw], m.call(a: 1)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal([h2, kw], m.call(**h2)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal([h3, kw], m.call(**h3)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal([h3, kw], m.call(a: 1, **h2)) - end - - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal([[], h], m.call(h)) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal([[h], h], m.call(h, h)) - end - - c = Object.new - class << c - define_method(:m) {|arg=nil, a: nil| [arg, a] } - end - m = c.method(:m) - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal([h2, 1], m.call(h3)) - end - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal([h2, 1], m.call(**h3)) - end - 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_warn(/Passing the keyword argument for `m=' as the last hash parameter is deprecated/) do - c.send(:m=, **{}) - end - assert_warn(/Passing the keyword argument for `m=' as the last hash parameter is deprecated/) do - c.send(:m=, **kw) - end - 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_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - m.call(**{}) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - m.call(**kw) - end - 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_warn(/Using the last argument as keyword parameters is deprecated/) do - assert_equal([[1], h1], foo.call(1, {:a=>1}, &->(*args, **kw){[args, kw]})) - end - assert_equal([1, h1], foo.call(1, {:a=>1}, &->(*args){args})) - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h1, {}], foo.call(:a=>1, &->(arg, **kw){[arg, kw]})) - end - 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 - 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 - - define_method(:block_splat) {|*args| } - ruby2_keywords :block_splat, def foo_bar_after_bmethod(*args) - bar(*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_after_bmethod(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([[1], h1], o.foo_bar_after_bmethod(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([[h1], {}], o.foo_bar_after_bmethod(h1, **{})) - - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `bar'/m) do - assert_equal([[1], h1], o.foo(:bar, 1, h1)) - end - assert_equal([1, h1], o.foo(:baz, 1, h1)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `bar'/m) do - assert_equal([[1], h1], o.bfoo(:bar, 1, h1)) - end - assert_equal([1, h1], o.bfoo(:baz, 1, h1)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `bar'/m) do - assert_equal([[1], h1], o.store_foo(:bar, 1, h1)) - end - assert_equal([1, h1], o.store_foo(:baz, 1, h1)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `bar'/m) do - assert_equal([[1], h1], o.foo_bar(1, h1)) - end - assert_equal([1, h1], o.foo_baz(1, h1)) - assert_equal([[1], h1], o.foo_bar_after_bmethod(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_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal([[1], h1], o.foo(:dbar, 1, h1)) - end - assert_equal([1, h1], o.foo(:dbaz, 1, h1)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal([[1], h1], o.bfoo(:dbar, 1, h1)) - end - assert_equal([1, h1], o.bfoo(:dbaz, 1, h1)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal([[1], h1], o.store_foo(:dbar, 1, h1)) - end - assert_equal([1, h1], o.store_foo(:dbaz, 1, h1)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal([[1], h1], o.foo_dbar(1, h1)) - end - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do - assert_equal([[1], h1], o.block(1, h1)) - end - assert_equal([[h1], {}], o.block(h1, **{})) - - assert_equal([[1], h1], o.cfunc(1, :a=>1)) - assert_equal([[1], h1], o.cfunc(1, **h1)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `initialize'/m) do - assert_equal([[1], h1], o.cfunc(1, h1)) - end - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method `method_missing'/m) do - assert_equal([[:b, 1], h1], o.b(1, h1)) - end - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method `bar'/m) do - assert_equal([[1], h1], o.bar(1, h1)) - end - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method `bar'/m) do - assert_equal([[1], h1], o.bar(1, h1)) - end - 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, **{})) - - c.class_eval do - remove_method(:bar) - def bar(*args, **kw) - [args, kw] - end - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `bar'/m) do - assert_equal([[1], h1], o.foo(:pass_bar, 1, :a=>1)) - end - - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `initialize'/m) do - assert_equal([[1], h1], o.foo(:pass_cfunc, 1, :a=>1)) - end - - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method `dig'/m) do - assert_equal(h, [c].dig(0, **h)) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `dig'/m) do - assert_equal(h, [c].dig(0, a: 1)) - end - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `dig'/m) do - assert_raise(ArgumentError) { [c].dig(0, **h3) } - end - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `dig'/m) do - assert_raise(ArgumentError) { [c].dig(0, a: 1, **h2) } - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `dig'/m) do - assert_equal(h, [c].dig(0, h)) - end - assert_raise(ArgumentError) { [c].dig(0, h2) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `dig'/m) do - assert_raise(ArgumentError) { [c].dig(0, h3) } - end - - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method `dig'/m) do - assert_equal([1, h], [c].dig(0, **h)) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `dig'/m) do - assert_equal([1, h], [c].dig(0, a: 1)) - end - assert_equal([h2, kw], [c].dig(0, **h2)) - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `dig'/m) do - assert_equal([h2, h], [c].dig(0, **h3)) - end - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `dig'/m) do - assert_equal([h2, h], [c].dig(0, a: 1, **h2)) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `dig'/m) do - assert_equal([1, h], [c].dig(0, h)) - end - assert_equal([h2, kw], [c].dig(0, h2)) - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `dig'/m) do - assert_equal([h2, h], [c].dig(0, h3)) - end - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method `method_missing'/m) do - assert_equal(h, [c].dig(0, **h)) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `method_missing'/m) do - assert_equal(h, [c].dig(0, a: 1)) - end - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `method_missing'/m) do - assert_raise(ArgumentError) { [c].dig(0, **h3) } - end - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `method_missing'/m) do - assert_raise(ArgumentError) { [c].dig(0, a: 1, **h2) } - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `method_missing'/m) do - assert_equal(h, [c].dig(0, h)) - end - assert_raise(ArgumentError) { [c].dig(0, h2) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `method_missing'/m) do - assert_raise(ArgumentError) { [c].dig(0, h3) } - end - - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method `method_missing'/m) do - assert_equal([1, h], [c].dig(0, **h)) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `method_missing'/m) do - assert_equal([1, h], [c].dig(0, a: 1)) - end - assert_equal([h2, kw], [c].dig(0, **h2)) - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `method_missing'/m) do - assert_equal([h2, h], [c].dig(0, **h3)) - end - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `method_missing'/m) do - assert_equal([h2, h], [c].dig(0, a: 1, **h2)) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `method_missing'/m) do - assert_equal([1, h], [c].dig(0, h)) - end - assert_equal([h2, kw], [c].dig(0, h2)) - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `method_missing'/m) do - assert_equal([h2, h], [c].dig(0, h3)) - end - 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_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal(kw, c.to_enum(:each, **{}, &m).size) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal(kw, c.to_enum(:each, **kw, &m).size) - end - 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_warn(/Using the last argument as keyword parameters is deprecated/m) do - assert_equal(h, c.to_enum(:each, h, &m).size) - end - assert_raise(ArgumentError) { c.to_enum(:each, h2, &m).size } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated/m) do - assert_raise(ArgumentError) { c.to_enum(:each, h3, &m).size } - end - - m = ->(arg, **args){ [arg, args] } - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - c.to_enum(:each, **{}, &m).size - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - c.to_enum(:each, **kw, &m).size - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal([h, kw], c.to_enum(:each, **h, &m).size) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal([h, kw], c.to_enum(:each, a: 1, &m).size) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal([h2, kw], c.to_enum(:each, **h2, &m).size) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal([h3, kw], c.to_enum(:each, **h3, &m).size) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do - assert_equal([h3, kw], c.to_enum(:each, a: 1, **h2, &m).size) - end - 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_warn(/Using the last argument as keyword parameters is deprecated/m) do - assert_equal([1, h], c.to_enum(:each, h, &m).size) - end - assert_equal([h2, kw], c.to_enum(:each, h2, &m).size) - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated/m) do - assert_equal([h2, h], c.to_enum(:each, h3, &m).size) - end - 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_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal(kw, c.instance_exec(**{}, &m)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal(kw, c.instance_exec(**kw, &m)) - end - 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_warn(/Using the last argument as keyword parameters is deprecated/) do - assert_equal(h, c.instance_exec(h, &m)) - end - assert_raise(ArgumentError) { c.instance_exec(h2, &m) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated/) do - assert_raise(ArgumentError) { c.instance_exec(h3, &m) } - end - - m = ->(arg, **args) { [arg, args] } - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - c.instance_exec(**{}, &m) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - c.instance_exec(**kw, &m) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h, kw], c.instance_exec(**h, &m)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h, kw], c.instance_exec(a: 1, &m)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h2, kw], c.instance_exec(**h2, &m)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h3, kw], c.instance_exec(**h3, &m)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h3, kw], c.instance_exec(a: 1, **h2, &m)) - end - 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_warn(/Using the last argument as keyword parameters is deprecated/m) do - assert_equal([1, h], c.instance_exec(h, &m)) - end - assert_equal([h2, kw], c.instance_exec(h2, &m)) - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated/m) do - assert_equal([h2, h], c.instance_exec(h3, &m)) - end - 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_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal(kw, c.instance_exec(**{}, &m)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal(kw, c.instance_exec(**kw, &m)) - end - 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_warn(/Using the last argument as keyword parameters is deprecated/) do - assert_equal(h, c.instance_exec(h, &m)) - end - assert_raise(ArgumentError) { c.instance_exec(h2, &m) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated/) do - assert_raise(ArgumentError) { c.instance_exec(h3, &m) } - end - - c.singleton_class.remove_method(:m) - def c.m(arg, **args) - [arg, args] - end - m = c.method(:m) - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - c.instance_exec(**{}, &m) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - c.instance_exec(**kw, &m) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h, kw], c.instance_exec(**h, &m)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h, kw], c.instance_exec(a: 1, &m)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h2, kw], c.instance_exec(**h2, &m)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h3, kw], c.instance_exec(**h3, &m)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h3, kw], c.instance_exec(a: 1, **h2, &m)) - end - 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_warn(/Using the last argument as keyword parameters is deprecated/m) do - assert_equal([1, h], c.instance_exec(h, &m)) - end - assert_equal([h2, kw], c.instance_exec(h2, &m)) - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated/) do - assert_equal([h2, h], c.instance_exec(h3, &m)) - end - 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_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal(kw, c.instance_exec(**{}, &m)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal(kw, c.instance_exec(**kw, &m)) - end - 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_warn(/Using the last argument as keyword parameters is deprecated/) do - assert_equal(h, c.instance_exec(h, &m)) - end - assert_raise(ArgumentError) { c.instance_exec(h2, &m) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated/) do - assert_raise(ArgumentError) { c.instance_exec(h3, &m) } - end - - c.singleton_class.remove_method(:m) - c.define_singleton_method(:m) do |arg, **args| - [arg, args] - end - m = c.method(:m) - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - c.instance_exec(**{}, &m) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - c.instance_exec(**kw, &m) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h, kw], c.instance_exec(**h, &m)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h, kw], c.instance_exec(a: 1, &m)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h2, kw], c.instance_exec(**h2, &m)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h3, kw], c.instance_exec(**h3, &m)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h3, kw], c.instance_exec(a: 1, **h2, &m)) - end - 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_warn(/Using the last argument as keyword parameters is deprecated/m) do - assert_equal([1, h], c.instance_exec(h, &m)) - end - assert_equal([h2, kw], c.instance_exec(h2, &m)) - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated/) do - assert_equal([h2, h], c.instance_exec(h3, &m)) - end - 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_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal(kw, c.instance_exec(c, **{}, &:m)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal(kw, c.instance_exec(c, **kw, &:m)) - end - 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_warn(/Using the last argument as keyword parameters is deprecated/) do - assert_equal(h, c.instance_exec(c, h, &:m)) - end - assert_raise(ArgumentError) { c.instance_exec(c, h2, &:m) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated/) do - assert_raise(ArgumentError) { c.instance_exec(c, h3, &:m) } - end - - c.singleton_class.remove_method(:m) - def c.m(arg, **args) - [arg, args] - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - c.instance_exec(c, **{}, &:m) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - c.instance_exec(c, **kw, &:m) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h, kw], c.instance_exec(c, **h, &:m)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h, kw], c.instance_exec(c, a: 1, &:m)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h2, kw], c.instance_exec(c, **h2, &:m)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h3, kw], c.instance_exec(c, **h3, &:m)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do - assert_equal([h3, kw], c.instance_exec(c, a: 1, **h2, &:m)) - end - 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_warn(/Using the last argument as keyword parameters is deprecated/m) do - assert_equal([1, h], c.instance_exec(c, h, &:m)) - end - assert_equal([h2, kw], c.instance_exec(c, h2, &:m)) - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated/) do - assert_equal([h2, h], c.instance_exec(c, h3, &:m)) - end - 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_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `c'/m) do - assert_equal(kw, c.m(:c, **{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `c'/m) do - assert_equal(kw, c.m(:c, **kw)) - end - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method `c'/m) do - assert_equal([h, h], c.m(:c, h, &m)) - end - assert_raise(ArgumentError) { c.m(:c, h2, &m) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `c'/m) do - assert_raise(ArgumentError) { c.m(:c, h3, &m) } - end - - c.singleton_class.remove_method(:c) - def c.c(arg, **args) - [arg, args] - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `c'/m) do - assert_equal([kw, kw], c.m(:c, **{})) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `c'/m) do - assert_equal([kw, kw], c.m(:c, **kw)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `c'/m) do - assert_equal([h, kw], c.m(:c, **h)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `c'/m) do - assert_equal([h, kw], c.m(:c, a: 1)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `c'/m) do - assert_equal([h2, kw], c.m(:c, **h2)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `c'/m) do - assert_equal([h3, kw], c.m(:c, **h3)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `c'/m) do - assert_equal([h3, kw], c.m(:c, a: 1, **h2)) - end - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method `c'/m) do - assert_equal([1, h], c.m(:c, h)) - end - assert_equal([h2, kw], c.m(:c, h2)) - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `c'/m) do - assert_equal([h2, h], c.m(:c, h3)) - end - end def p1 Proc.new do |str: "foo", num: 424242| @@ -4099,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 @@ -4119,73 +274,14 @@ class TestKeywordArguments < Test::Unit::TestCase bug7665 = '[ruby-core:51278]' bug8463 = '[ruby-core:55203] [Bug #8463]' expect = [*%w[foo bar], {zzz: 42}] - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `rest_keyrest'/m) do - assert_equal(expect, rest_keyrest(*expect), bug7665) - end + assert_equal(expect, rest_keyrest(*expect), bug7665) pr = proc {|*args, **opt| next *args, opt} - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do - assert_equal(expect, pr.call(*expect), bug7665) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do - assert_equal(expect, pr.call(expect), bug8463) - end + assert_equal(expect, pr.call(*expect), bug7665) + assert_equal(expect, pr.call(expect), bug8463) pr = proc {|a, *b, **opt| next a, *b, opt} - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do - assert_equal(expect, pr.call(expect), bug8463) - end + assert_equal(expect, pr.call(expect), bug8463) pr = proc {|a, **opt| next a, opt} - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do - assert_equal(expect.values_at(0, -1), pr.call(expect), bug8463) - end - 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_split - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `req_plus_keyword'/m) do - assert_equal([{:a=>1}, {}], req_plus_keyword(:a=>1)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `req_plus_keyword'/m) do - assert_equal([{"a"=>1}, {}], req_plus_keyword("a"=>1)) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `req_plus_keyword'/m) do - assert_equal([{"a"=>1, :a=>1}, {}], req_plus_keyword("a"=>1, :a=>1)) - end - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method `opt_plus_keyword'/m) do - assert_equal([1, {:a=>1}], opt_plus_keyword({:a=>1})) - end - assert_equal([{"a"=>1}, {}], opt_plus_keyword({"a"=>1})) - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `opt_plus_keyword'/m) do - assert_equal([{"a"=>1}, {:a=>1}], opt_plus_keyword({"a"=>1, :a=>1})) - end - - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method `splat_plus_keyword'/m) do - assert_equal([[], {:a=>1}], splat_plus_keyword({:a=>1})) - end - assert_equal([[{"a"=>1}], {}], splat_plus_keyword({"a"=>1})) - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `splat_plus_keyword'/m) do - assert_equal([[{"a"=>1}], {:a=>1}], splat_plus_keyword({"a"=>1, :a=>1})) - end + assert_equal(expect.values_at(0, -1), pr.call(expect), bug8463) end def test_bare_kwrest @@ -4370,9 +466,7 @@ class TestKeywordArguments < Test::Unit::TestCase [a, b, c, d, e, f, g] end end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `foo'/m) do - assert_equal([1, 2, 1, [], {:f=>5}, 2, {}], a.new.foo(1, 2, f:5), bug8993) - end + assert_equal([1, 2, 1, [], {:f=>5}, 2, {}], a.new.foo(1, 2, f:5), bug8993) end def test_splat_keyword_nondestructive @@ -4405,49 +499,27 @@ class TestKeywordArguments < Test::Unit::TestCase o = Object.new def o.to_hash() { k: 9 } end assert_equal([1, 42, [], o, :key, {}, nil], f9(1, o)) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m1'/m) do - assert_equal([1, 9], m1(1, o) {|a, k: 0| break [a, k]}, bug10016) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m1'/m) do - assert_equal([1, 9], m1(1, o, &->(a, k: 0) {break [a, k]}), bug10016) - end + 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, /unknown keyword: :a/) { + 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] @@ -4493,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 @@ -4607,477 +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) } - - redef = -> do - c.singleton_class.remove_method(:m) - eval <<-END - def c.m(args) - args - end - END - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, c.call(**{}, &:m)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal(kw, c.call(**kw, &:m)) - end - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do - assert_equal(h, c.call(h, &:m)) - end - assert_raise(ArgumentError) { c.call(h2, &:m) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `call'/m) do - assert_raise(ArgumentError) { c.call(h3, &:m) } - end - - redef = -> do - c.singleton_class.remove_method(:m) - eval <<-END - def c.m(arg, **args) - [arg, args] - end - END - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([kw, kw], c.call(**{}, &:m)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([kw, kw], c.call(**kw, &:m)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], c.call(**h, &:m)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h, kw], c.call(a: 1, &:m)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h2, kw], c.call(**h2, &:m)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], c.call(**h3, &:m)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do - assert_equal([h3, kw], c.call(a: 1, **h2, &:m)) - end - - 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) } - - redef = -> do - c.singleton_class.remove_method(:method_missing) - eval <<-END - def c.method_missing(_, args) - args - end - END - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal(kw, c.call(**{}, &:m)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal(kw, c.call(**kw, &:m)) - end - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do - assert_equal(h, c.call(h, &:m2)) - end - assert_raise(ArgumentError) { c.call(h2, &:m2) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `call'/m) do - assert_raise(ArgumentError) { c.call(h3, &:m2) } - end - - redef = -> do - c.singleton_class.remove_method(:method_missing) - eval <<-END - def c.method_missing(_, arg, **args) - [arg, args] - end - END - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([kw, kw], c.call(**{}, &:m)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([kw, kw], c.call(**kw, &:m)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h, kw], c.call(**h, &:m)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h, kw], c.call(a: 1, &:m)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h2, kw], c.call(**h2, &:m)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h3, kw], c.call(**h3, &:m)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h3, kw], c.call(a: 1, **h2, &:m)) - end - - 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) } - - redef = -> do - c.singleton_class.remove_method(:method_missing) - eval <<-END - def c.method_missing(_, args) - args - end - END - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal(kw, c.call(**{}, &:m2)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal(kw, c.call(**kw, &:m2)) - end - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do - assert_equal(h, c.call(h, &:m2)) - end - assert_raise(ArgumentError) { c.call(h2, &:m2) } - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `call'/m) do - assert_raise(ArgumentError) { c.call(h3, &:m2) } - end - - redef = -> do - c.singleton_class.remove_method(:method_missing) - eval <<-END - def c.method_missing(_, arg, **args) - [arg, args] - end - END - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([kw, kw], c.call(**{}, &:m2)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([kw, kw], c.call(**kw, &:m2)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h, kw], c.call(**h, &:m2)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h, kw], c.call(a: 1, &:m2)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h2, kw], c.call(**h2, &:m2)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h3, kw], c.call(**h3, &:m2)) - end - redef[] - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do - assert_equal([h3, kw], c.call(a: 1, **h2, &:m2)) - end - - 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 - - def test_ruby2_keywords_hash_empty_kw_splat - def self.foo(*a) a.last end - singleton_class.send(:ruby2_keywords, :foo) - bug16642 = '[ruby-core:97203] [Bug #16642]' - - res = foo(**{}) - assert_equal({}, res, bug16642) - assert_equal(false, res.frozen?, bug16642) - - res = foo(*[], **{}) - assert_equal({}, res, bug16642) - assert_equal(false, res.frozen?, bug16642) - end end diff --git a/test/ruby/test_lambda.rb b/test/ruby/test_lambda.rb index 03b501a6c9..3ac2e4cb98 100644 --- a/test/ruby/test_lambda.rb +++ b/test/ruby/test_lambda.rb @@ -74,26 +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 - f = pass_along {} - refute_predicate(f, :lambda?, '[Bug #15620]') - assert_nothing_raised(ArgumentError) { f.call(:extra_arg) } - end - - def test_create_non_lambda_for_proc_two_levels - f = pass_along2 {} - refute_predicate(f, :lambda?, '[Bug #15620]') - assert_nothing_raised(ArgumentError) { f.call(:extra_arg) } - end - def test_instance_exec bug12568 = '[ruby-core:76300] [Bug #12568]' assert_nothing_raised(ArgumentError, bug12568) do @@ -177,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, @@ -215,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 6e5c1714a5..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 @@ -452,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) @@ -474,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 @@ -634,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 7f4a329c4a..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,35 +177,18 @@ 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 = 'n = 1; _="foo#{n ? "-#{n}" : ""}"'; 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" } 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 def test_regexp @@ -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 6c7d0e6bae..9c7df4cb03 100644 --- a/test/ruby/test_m17n.rb +++ b/test/ruby/test_m17n.rb @@ -365,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 @@ -615,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 @@ -1533,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"))) @@ -1582,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 @@ -1590,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", @@ -1629,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")) } @@ -1639,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 cfb8bff882..99c162a92f 100644 --- a/test/ruby/test_m17n_comb.rb +++ b/test/ruby/test_m17n_comb.rb @@ -744,10 +744,6 @@ 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 @@ -764,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 @@ -776,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 850f467c10..0565a1c04f 100644 --- a/test/ruby/test_marshal.rb +++ b/test/ruby/test_marshal.rb @@ -189,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]') @@ -448,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 @@ -559,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 @@ -725,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 @@ -745,26 +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 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_method.rb b/test/ruby/test_method.rb index 0f0807af9d..77273dade5 100644 --- a/test/ruby/test_method.rb +++ b/test/ruby/test_method.rb @@ -22,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 @@ -31,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 @@ -436,29 +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) + 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 @@ -496,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|} @@ -530,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) @@ -544,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) @@ -553,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 @@ -570,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) @@ -579,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 @@ -604,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 @@ -628,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 @@ -637,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 @@ -734,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 @@ -991,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} @@ -1064,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 @@ -1244,106 +1046,4 @@ class TestMethod < Test::Unit::TestCase 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 end diff --git a/test/ruby/test_module.rb b/test/ruby/test_module.rb index 5cfda018f3..076ea0901f 100644 --- a/test/ruby/test_module.rb +++ b/test/ruby/test_module.rb @@ -28,13 +28,10 @@ class TestModule < Test::Unit::TestCase def setup @verbose = $VERBOSE $VERBOSE = nil - @deprecated = Warning[:deprecated] - Warning[:deprecated] = true end def teardown $VERBOSE = @verbose - Warning[:deprecated] = @deprecated end def test_LT_0 @@ -297,11 +294,8 @@ class TestModule < Test::Unit::TestCase end def test_nested_get - 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 @@ -334,7 +328,6 @@ class TestModule < Test::Unit::TestCase 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 @@ -345,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') @@ -480,48 +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 - - 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 !User.method_defined?(:wombat) + assert User.method_defined?(:mixin) + assert User.method_defined?(:user) + assert User.method_defined?(:user2) + assert !User.method_defined?(:user3) - 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) + 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 @@ -566,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 @@ -609,8 +547,6 @@ 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 @@ -730,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) @@ -813,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 @@ -820,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 @@ -1059,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 @@ -1068,47 +986,33 @@ 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 @@ -1397,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 @@ -1532,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 @@ -1579,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 @@ -1924,29 +1781,6 @@ class TestModule < Test::Unit::TestCase assert_equal(0, 1 / 2) end - def test_visibility_after_refine_and_visibility_change - m = Module.new - c = Class.new do - def x; :x end - end - c.prepend(m) - Module.new do - refine c do - def x; :y end - end - end - - o1 = c.new - o2 = c.new - assert_equal(:x, o1.public_send(:x)) - assert_equal(:x, o2.public_send(:x)) - o1.singleton_class.send(:private, :x) - o2.singleton_class.send(:public, :x) - - assert_raise(NoMethodError) { o1.public_send(:x) } - assert_equal(:x, o2.public_send(:x)) - end - def test_prepend_visibility bug8005 = '[ruby-core:53106] [Bug #8005]' c = Class.new do @@ -2173,13 +2007,17 @@ 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 @@ -2408,7 +2246,7 @@ class TestModule < Test::Unit::TestCase A.prepend InspectIsShallow - expect = "#<Method: A(ShallowInspect)#inspect(shallow_inspect)() -:7>" + expect = "#<Method: A(ShallowInspect)#inspect(shallow_inspect)>" assert_equal expect, A.new.method(:inspect).inspect, "#{bug_10282}" RUBY end @@ -2434,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 @@ -2472,56 +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 - private def assert_top_method_is_private(method) @@ -2530,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_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 636f827fe3..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,11 +260,11 @@ 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, 0).size } - 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) } @@ -276,14 +272,6 @@ class TestNumeric < Test::Unit::TestCase 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 } @@ -292,14 +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 } - - e = assert_warn(/Using the last argument as keyword parameters is deprecated/) { - 1.step(10, {by: "1"}) - } - assert_warn('') { - assert_raise(ArgumentError) {e.size} - } - assert_equal(bignum*2+1, (-bignum).step(bignum, 1).size) assert_equal(bignum*2, (-bignum).step(bignum-1, 1).size) @@ -309,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] @@ -351,20 +332,6 @@ class TestNumeric < Test::Unit::TestCase assert_step [bignum]*4, [bignum, by: 0, to: 0], 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 - end - def test_num2long assert_raise(TypeError) { 1 & nil } assert_raise(TypeError) { 1 & 1.0 } diff --git a/test/ruby/test_object.rb b/test/ruby/test_object.rb index 442a7551a0..c25dcf9c37 100644 --- a/test/ruby/test_object.rb +++ b/test/ruby/test_object.rb @@ -96,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 @@ -121,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(:!)) @@ -237,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 } @@ -783,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 @@ -792,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 @@ -842,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 @@ -891,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} @@ -909,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 b42314b765..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 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 @@ -714,6 +670,17 @@ class TestRubyOptimization < Test::Unit::TestCase 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 + def test_peephole_optimization_without_trace assert_separately [], <<-END RubyVM::InstructionSequence.compile_option = {trace_instruction: false} @@ -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 1e909bce1b..b725634a38 100644 --- a/test/ruby/test_parse.rb +++ b/test/ruby/test_parse.rb @@ -13,24 +13,21 @@ class TestParse < Test::Unit::TestCase $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 @@ -85,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 @@ -153,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 @@ -271,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 @@ -350,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 @@ -358,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+'"') @@ -376,25 +376,23 @@ 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 @@ -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,56 +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_raise(SyntaxError) { eval('%s') } + assert_raise(SyntaxError) { eval('%ss') } + assert_raise(SyntaxError) { eval('%z()') } end def test_symbol @@ -617,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( @@ -642,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( @@ -709,22 +668,17 @@ 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_equal(1.0/0, eval("1e10000")) - assert_syntax_error('1_E', /trailing `_'/) - assert_syntax_error('1E1E1', /unexpected constant/) + assert_raise(SyntaxError) { eval('1_E') } + assert_raise(SyntaxError) { eval('1E1E1') } end def test_global_variable @@ -734,19 +688,17 @@ x = __ENCODING__ $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 @@ -766,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 @@ -800,24 +785,32 @@ 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 @@ -874,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 @@ -891,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 @@ -900,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 @@ -1046,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 @@ -1075,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 @@ -1085,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 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 2afa823d53..0000000000 --- a/test/ruby/test_pattern_matching.rb +++ /dev/null @@ -1,1342 +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 in [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_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_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 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_modifier_in - 1 in a - assert_equal 1, a - assert_raise(NoMatchingPatternError) do - {a: 1} in {a: 0} - end - assert_syntax_error("if {} in {a:}; end", /void value expression/) - assert_syntax_error(%q{ - 1 in a, b - }, /unexpected/, '[ruby-core:95098]') - assert_syntax_error(%q{ - 1 in a: - }, /unexpected/, '[ruby-core:95098]') - end - - def assert_experimental_warning(code) - w = Warning[:experimental] - - Warning[:experimental] = false - assert_warn('') {eval(code)} - - Warning[:experimental] = true - assert_warn(/Pattern matching 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 in 0") - 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_proc.rb b/test/ruby/test_proc.rb index 3f0d599a04..df9bb5f549 100644 --- a/test/ruby/test_proc.rb +++ b/test/ruby/test_proc.rb @@ -55,13 +55,7 @@ class TestProc < Test::Unit::TestCase def assert_arity(n) meta = class << self; self; end - b = assert_warn(/Capturing the given block using Proc\.new is deprecated/) do - Proc.new - end - meta.class_eval { - remove_method(:foo) if method_defined?(:foo) - define_method(:foo, b) - } + meta.class_eval {define_method(:foo, Proc.new)} assert_equal(n, method(:foo).arity) end @@ -157,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 @@ -372,15 +397,6 @@ 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) { lambda } @@ -391,14 +407,14 @@ class TestProc < Test::Unit::TestCase 1.times { b = lambda } b end - assert_raise(ArgumentError) {o.foo { :foo }.call} + assert_equal(:foo, o.foo { :foo }.call) def o.foo(&b) b = nil 1.times { b = lambda } b end - assert_raise(ArgumentError) {o.foo { :foo }.call} + assert_equal(:foo, o.foo { :foo }.call) end def test_arity2 @@ -1087,26 +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_parameters assert_equal([], proc {}.parameters) assert_equal([], proc {||}.parameters) @@ -1175,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 @@ -1286,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 @@ -1329,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 @@ -1377,254 +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 method_for_test_proc_without_block_for_symbol - assert_warn(/Capturing the given block using Kernel#proc is deprecated/) do - binding.eval('proc') - end - end - - def test_proc_without_block_for_symbol - assert_equal('1', method_for_test_proc_without_block_for_symbol(&:to_s).call(1), '[Bug #14782]') - 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} - - assert_predicate((f << g), :lambda?) - assert_predicate((g >> 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)) - 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)) - 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 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(1, (f << g).call(a: 3)[:a]) - end - assert_equal(2, (f >> g).call(a: 3)[:a]) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(1, (f << g).call({a: 3})[:a]) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(2, (f >> g).call({a: 3})[:a]) - end - assert_equal(2, (g << f).call(a: 3)[:a]) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(1, (g >> f).call(a: 3)[:a]) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(2, (g << f).call({a: 3})[:a]) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(1, (g >> f).call({a: 3})[:a]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(1, (f << g).call(**{})[:a]) - end - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(1, (f << g).call(a: 3)[:a]) - end - assert_equal(2, (f >> g).call(a: 3)[:a]) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(1, (f << g).call({a: 3})[:a]) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(2, (f >> g).call({a: 3})[:a]) - end - assert_equal(2, (g << f).call(a: 3)[:a]) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(1, (g >> f).call(a: 3)[:a]) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(2, (g << f).call({a: 3})[:a]) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(1, (g >> f).call({a: 3})[:a]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(1, (f << g).call(**{})[:a]) - end - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(1, (f << g).call(a: 3)[:a]) - end - assert_equal(2, (f >> g).call(a: 3)[:a]) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(1, (f << g).call({a: 3})[:a]) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(2, (f >> g).call({a: 3})[:a]) - end - assert_equal(2, (g << f).call(a: 3)[:a]) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(1, (g >> f).call(a: 3)[:a]) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(2, (g << f).call({a: 3})[:a]) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do - assert_equal(1, (g >> f).call({a: 3})[:a]) - end - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `call'/m) do - assert_equal(1, (f << g).call(**{})[:a]) - end - 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_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do - assert_equal(2, (f >> g).call(a: 3)[:a]) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do - assert_equal(1, (f << g).call({a: 3})[:a]) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do - assert_equal(2, (f >> g).call({a: 3})[:a]) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do - assert_equal(2, (g << f).call(a: 3)[:a]) - end - assert_equal(1, (g >> f).call(a: 3)[:a]) - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do - assert_equal(2, (g << f).call({a: 3})[:a]) - end - assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do - assert_equal(1, (g >> f).call({a: 3})[:a]) - end - assert_equal(1, (f << g).call(**{})[:a]) - assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do - assert_equal(2, (f >> g).call(**{})[:a]) - end - end -end - diff --git a/test/ruby/test_process.rb b/test/ruby/test_process.rb index ab723c6f63..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) @@ -634,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") } @@ -680,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 @@ -763,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 @@ -1019,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| @@ -1483,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 @@ -1499,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 @@ -1565,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 @@ -1583,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 @@ -1593,7 +1550,6 @@ 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 @@ -1629,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 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 @@ -1741,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 @@ -1808,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} @@ -1862,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? @@ -1882,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 @@ -1906,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 @@ -1914,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) @@ -2098,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 @@ -2180,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 @@ -2250,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 @@ -2258,7 +2183,7 @@ 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 @@ -2271,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 @@ -2279,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) } @@ -2332,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 @@ -2366,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 @@ -2375,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 @@ -2399,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) diff --git a/test/ruby/test_rand.rb b/test/ruby/test_rand.rb index 939d17bdf7..882d33fb40 100644 --- a/test/ruby/test_rand.rb +++ b/test/ruby/test_rand.rb @@ -347,15 +347,10 @@ END end def assert_random_bytes(r) - srand(0) assert_equal("", r.bytes(0)) - assert_equal("", Random.bytes(0)) - x = "\xAC".force_encoding("ASCII-8BIT") - assert_equal(x, r.bytes(1)) - assert_equal(x, Random.bytes(1)) - x = "/\xAA\xC4\x97u\xA6\x16\xB7\xC0\xCC".force_encoding("ASCII-8BIT") - assert_equal(x, r.bytes(10)) - assert_equal(x, Random.bytes(10)) + 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 @@ -399,8 +394,6 @@ END 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) assert_in_delta(1.5488135039273248, r.rand(1.0...2.0), 0.0001, '[ruby-core:24655]') diff --git a/test/ruby/test_range.rb b/test/ruby/test_range.rb index 3953b3ecc2..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,34 +103,6 @@ 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 } } - 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) end def test_initialize_twice @@ -169,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 @@ -182,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 @@ -194,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 @@ -217,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 @@ -242,76 +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..).step(-1) { } } - 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) { } } - 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 } @@ -331,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 @@ -384,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 @@ -428,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 @@ -468,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 @@ -541,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 @@ -570,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 @@ -599,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 @@ -730,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 @@ -778,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 @@ -832,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) @@ -936,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 @@ -949,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 5676b41445..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,35 +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)} - - 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)} @@ -595,16 +566,9 @@ 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 - - assert_raise(ZeroDivisionError) do - 1 / 0r.coerce(0+0i)[0] - end - assert_raise(ZeroDivisionError) do - 1 / 0r.coerce(0.0+0i)[0] - end end class ObjectX @@ -815,42 +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)) - } - - 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))) @@ -859,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 6fb04de5d6..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,59 +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 + 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 - 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 @@ -364,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 @@ -538,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 @@ -916,7 +849,7 @@ class TestRefinement < Test::Unit::TestCase #{PrependAfterRefine_CODE} undef PrependAfterRefine } - }, timeout: 30 + } end def test_prepend_after_refine @@ -974,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 @@ -1562,7 +1491,6 @@ class TestRefinement < Test::Unit::TestCase undef :foo end end - ext end def test_call_refined_method_in_duplicate_module @@ -2064,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 @@ -2081,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) @@ -2291,95 +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 private diff --git a/test/ruby/test_regexp.rb b/test/ruby/test_regexp.rb index dc203fa82a..fe271dc3d7 100644 --- a/test/ruby/test_regexp.rb +++ b/test/ruby/test_regexp.rb @@ -90,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 @@ -218,23 +213,6 @@ class TestRegexp < Test::Unit::TestCase def test_assign_named_capture_to_reserved_word /(?<nil>.)/ =~ "a" assert_not_include(local_variables, :nil, "[ruby-dev:32675]") - - def (obj = Object.new).test(s, nil: :ng) - /(?<nil>.)/ =~ s - binding.local_variable_get(:nil) - end - assert_equal("b", obj.test("b")) - - tap do |nil: :ng| - /(?<nil>.)/ =~ "c" - assert_equal("c", binding.local_variable_get(:nil)) - end - 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 @@ -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 @@ -965,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 @@ -1017,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 } @@ -1041,7 +1010,6 @@ class TestRegexp < Test::Unit::TestCase assert_raise(TypeError) { $` } assert_raise(TypeError) { $' } assert_raise(TypeError) { $+ } -=end end def test_unicode @@ -1098,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") @@ -1111,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"]) @@ -1149,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 diff --git a/test/ruby/test_require.rb b/test/ruby/test_require.rb index a86ea356c5..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,6 +105,16 @@ 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) Dir.mktmpdir {|tmp| begin @@ -123,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 @@ -201,12 +254,12 @@ class TestRequire < Test::Unit::TestCase def assert_syntax_error_backtrace 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 end @@ -214,13 +267,6 @@ class TestRequire < Test::Unit::TestCase 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 @@ -336,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| @@ -386,6 +419,38 @@ 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 $:.delete(".") @@ -472,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 @@ -481,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 @@ -825,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 2842b63804..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 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) @@ -75,27 +66,18 @@ class TestRubyOptions < Test::Unit::TestCase 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(-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(-e) + ['p Warning[:deprecated]'], "", %w(false), []) - code = 'puts "#{$VERBOSE}:#{Warning[:deprecated]}:#{Warning[:experimental]}"' - Tempfile.create(["test_ruby_test_rubyoption", ".rb"]) do |t| - t.puts code - t.close - assert_in_out_err(["-r#{t.path}", '-e', code], "", %w(false:false:true false:false:true), []) - assert_in_out_err(["-r#{t.path}", '-w', '-e', code], "", %w(true:true:true true:true:true), []) - assert_in_out_err(["-r#{t.path}", '-W:deprecated', '-e', code], "", %w(false:true:true false:true:true), []) - assert_in_out_err(["-r#{t.path}", '-W:no-experimental', '-e', code], "", %w(false:false:false false:false:false), []) - end 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), []) @@ -114,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 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 @@ -147,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/) @@ -166,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 @@ -189,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 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 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 @@ -262,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 @@ -296,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, @@ -319,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\)/) @@ -335,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)) @@ -345,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 @@ -464,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}", ] @@ -501,25 +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"], ].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 = 2 - n += pre.count("\n") if pre - - a.for("no directives with #{src}") do - err = ["#{t.path}:#{n}: warning: mismatched indentations at '#{e}' with '#{k}' at #{n-1}"] + |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 @@ -528,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 -*-" @@ -537,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 #{n+1}"] + 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 -*-" @@ -548,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 -*-" @@ -559,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 #{n-1}"] + 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}" @@ -632,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 @@ -643,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 @@ -673,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 @@ -700,37 +605,42 @@ 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) @@ -795,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' @@ -812,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 } @@ -852,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 @@ -891,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 @@ -989,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 @@ -1009,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], @@ -1025,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"', err], - ['+"foo#{123}bar" << "bar"', []], - ['-"foo#{123}bar" << "bar"', freeze && debug ? with_debug_pat : 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 @@ -1069,27 +987,10 @@ class TestRubyOptions < Test::Unit::TestCase end end - def test_rubylib_invalid_encoding - env = {"RUBYLIB"=>"\xFF", "LOCALE"=>"en_US.UTF-8", "LC_ALL"=>"en_US.UTF-8"} - assert_ruby_status([env, "-e;"]) - 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_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 e16a4fc01e..3085c0902a 100644 --- a/test/ruby/test_settracefunc.rb +++ b/test/ruby/test_settracefunc.rb @@ -468,6 +468,7 @@ 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], @@ -516,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 @@ -562,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' @@ -589,73 +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_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], - [: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], - [: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], - [: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 @@ -740,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{} @@ -767,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 @@ -832,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{ @@ -915,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)| @@ -1131,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 @@ -1549,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| @@ -1735,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 @@ -1891,6 +1768,7 @@ class TestSetTraceFunc < Test::Unit::TestCase define_method(:m) {} tp = TracePoint.new(:call) do + next unless target_thread? raise '' end @@ -1956,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 RubyVM::MJIT.enabled? t.add_trace_func proc{|ev, file, line, *args| if file == __FILE__ @@ -1983,316 +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_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) - set_trace_func(proc {}); set_trace_func(nil) # Is it okay that this is required? - 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_string.rb b/test/ruby/test_string.rb index 746471553d..9574ed31c9 100644 --- a/test/ruby/test_string.rb +++ b/test/ruby/test_string.rb @@ -4,11 +4,6 @@ require 'test/unit' class TestString < Test::Unit::TestCase ENUMERATOR_WANTARRAY = RUBY_VERSION >= "3.0.0" - WIDE_ENCODINGS = [ - Encoding::UTF_16BE, Encoding::UTF_16LE, - Encoding::UTF_32BE, Encoding::UTF_32LE, - ] - def initialize(*args) @cls = String @aref_re_nth = true @@ -17,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 @@ -607,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') @@ -661,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 @@ -841,20 +826,21 @@ 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 @@ -901,15 +887,20 @@ CODE assert_equal [65, 66, 67], s.bytes {} } else - 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 + 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 @@ -940,15 +931,20 @@ CODE assert_equal [0x3042, 0x3044, 0x3046], s.codepoints {} } else - 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 + 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 @@ -973,11 +969,14 @@ CODE assert_equal ["A", "B", "C"], s.chars {} } else - 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]) + 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 @@ -1000,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 @@ -1024,19 +1023,12 @@ 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 if ENUMERATOR_WANTARRAY @@ -1044,13 +1036,15 @@ CODE assert_equal ["A", "B", "C"], "ABC".grapheme_clusters {} } else - 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]) + 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 @@ -1163,10 +1157,12 @@ CODE assert_equal ["hello\n", "world"], s.lines {} } else - 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]) + 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 @@ -1199,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 } @@ -1243,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 @@ -1434,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 @@ -1530,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($~) @@ -1538,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 @@ -1706,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 @@ -1758,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; $; = " " @@ -1781,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)), @@ -1808,7 +1785,6 @@ CODE s.split("b", 1).map(&:upcase!) assert_equal("abc", s) end - def test_squeeze assert_equal(S("abc"), S("aaabbbbccc").squeeze) assert_equal(S("aa bb cc"), S("aa bb cc").squeeze(S(" "))) @@ -1914,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")) @@ -1961,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 @@ -2987,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) @@ -3134,22 +3121,6 @@ CODE assert_same(str, -bar, "uminus deduplicates [Feature #13077]") 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 85de0f23a9..af68346442 100644 --- a/test/ruby/test_struct.rb +++ b/test/ruby/test_struct.rb @@ -60,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) @@ -105,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) } @@ -113,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) @@ -124,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) } @@ -151,17 +132,6 @@ module TestStruct assert_equal([1, 2], o.each.to_a) 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_pair klass = @Struct.new(:a, :b) o = klass.new(1, 2) @@ -246,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 @@ -309,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 @@ -397,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 @@ -435,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 bbfc581500..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 diff --git a/test/ruby/test_symbol.rb b/test/ruby/test_symbol.rb index 660f2e1574..36cbf4a710 100644 --- a/test/ruby/test_symbol.rb +++ b/test/ruby/test_symbol.rb @@ -161,42 +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 - 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 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 @@ -533,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, @@ -555,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 86417ba12f..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,40 +93,6 @@ class TestSyntax < Test::Unit::TestCase assert_valid_syntax("tap (proc do end)", __FILE__, bug9726) 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/) @@ -182,9 +148,7 @@ class TestSyntax < Test::Unit::TestCase h = {k3: 31} assert_raise(ArgumentError) {o.kw(**h)} h = {"k1"=>11, k2: 12} - assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `kw'/m) do - assert_raise(ArgumentError) {o.kw(**h)} - end + assert_raise(TypeError) {o.kw(**h)} end def test_keyword_duplicated @@ -223,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 @@ -258,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) - 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 = var) var end") + end + assert_nil(o.foo, bug9593) - 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 = bar {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 bar;end; var)) var end") + end + + o = Object.new + 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 @@ -433,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 @@ -465,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 @@ -552,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 @@ -564,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/) @@ -620,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 @@ -780,8 +694,6 @@ e" \ TEXT end; - - assert_equal(" TEXT\n", eval("<<~eos\n" " \\\n" "TEXT\n" "eos\n")) end def test_lineno_after_heredoc @@ -799,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 @@ -928,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 @@ -975,15 +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_syntax_error('0..%w.', /unterminated string/, bug10957) + assert_syntax_error('0...%w.', /unterminated string/, bug10957) end def test_too_big_nth_ref @@ -999,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 @@ -1035,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 @@ -1065,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)'] @@ -1111,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 @@ -1241,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) @@ -1266,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 @@ -1347,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 @@ -1374,298 +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_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/) - mesg = proc {|n| /`_#{n}' is reserved for numbered parameter/} - assert_warn(mesg[1]) {eval('proc {_1 = nil}')} - assert_warn(mesg[2]) {eval('_2=1')} - assert_warn(mesg[3]) {eval('proc {|_3|}')} - assert_warn(mesg[4]) {instance_eval('def x(_4) end')} - assert_warn(mesg[5]) {instance_eval('def _5; end')} - assert_warn(mesg[6]) {instance_eval('def self._6; end')} - 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} - 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_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') - 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)) - } - warning = "warning: Using the last argument as keyword parameters is deprecated" - assert_warning(/\A\z|:(?!#{__LINE__+1})\d+: #{warning}/o) { - assert_equal([[], {}], obj.foo({}) {|*x| x}) - } - assert_warning(/\A\z|:(?!#{__LINE__+1})\d+: #{warning}/o) { - assert_equal([[], {}], 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 30a3cc784e..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 - t2&.kill - t3&.kill - 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 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,7 +443,6 @@ class TestThread < Test::Unit::TestCase q2.push(true) Thread.pass while th.alive? } - assert_raise(RuntimeError) { th.join } } end; end @@ -513,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 @@ -534,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 @@ -554,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 @@ -586,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 @@ -616,8 +591,7 @@ class TestThread < Test::Unit::TestCase end Thread.pass until t.stop? assert_predicate(t, :alive?) - ensure - t&.kill + t.kill end def test_mutex_deadlock @@ -795,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 @@ -813,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 @@ -871,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 @@ -947,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 @@ -1106,7 +1072,7 @@ q.pop Thread.pass until mutex.locked? assert_equal(mutex.owned?, false) ensure - th&.kill + th.kill if th end end @@ -1150,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 @@ -1179,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 @@ -1232,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") @@ -1322,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 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 @@ -1343,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 41e6865ed4..0000000000 --- a/test/ruby/test_thread_queue.rb +++ /dev/null @@ -1,630 +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 = 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, $$ - } - } - 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 1749d92a17..5ddcc9dcfe 100644 --- a/test/ruby/test_time.rb +++ b/test/ruby/test_time.rb @@ -173,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) @@ -375,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)) @@ -553,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?) @@ -590,10 +556,6 @@ 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_succ @@ -885,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") @@ -1011,58 +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) - end - def test_getlocal_dont_share_eigenclass bug5012 = "[ruby-dev:44071]" @@ -1194,20 +1097,6 @@ class TestTime < Test::Unit::TestCase } end - def test_getlocal_utc_offset - t = Time.gm(2000) - assert_equal [00, 30, 21, 31, 12, 1999], t.getlocal("-02:30").to_a[0, 6] - assert_equal [00, 00, 9, 1, 1, 2000], t.getlocal("+09:00").to_a[0, 6] - assert_equal [20, 29, 21, 31, 12, 1999], t.getlocal("-02:30:40").to_a[0, 6] - assert_equal [35, 10, 9, 1, 1, 2000], t.getlocal("+09:10:35").to_a[0, 6] - assert_equal [00, 30, 21, 31, 12, 1999], t.getlocal("-0230").to_a[0, 6] - assert_equal [00, 00, 9, 1, 1, 2000], t.getlocal("+0900").to_a[0, 6] - assert_equal [20, 29, 21, 31, 12, 1999], t.getlocal("-023040").to_a[0, 6] - assert_equal [35, 10, 9, 1, 1, 2000], t.getlocal("+091035").to_a[0, 6] - assert_raise(ArgumentError) {t.getlocal("-02:3040")} - assert_raise(ArgumentError) {t.getlocal("+0910:35")} - end - def test_getlocal_nil now = Time.now now2 = nil @@ -1238,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 @@ -1271,9 +1155,7 @@ class TestTime < Test::Unit::TestCase 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 5ee12e4dbd..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 @@ -219,7 +218,6 @@ class TestTimeTZ < Test::Unit::TestCase def test_right_utc with_tz(tz="right/UTC") { - ::Bug::Time.reset_leap_second_info 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]) @@ -227,31 +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 - ::Bug::Time.reset_leap_second_info - 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, "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) - } - } - with_tz("right/UTC") { - ::Bug::Time.reset_leap_second_info - 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_not_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]) @@ -260,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 @@ -376,7 +289,6 @@ class TestTimeTZ < Test::Unit::TestCase mesg = "#{mesg_utc}.localtime" define_method(gen_test_name(tz)) { with_tz(tz) { - ::Bug::Time.reset_leap_second_info t = nil assert_nothing_raised(mesg) { t = Time.utc(*u) } assert_equal(expected_utc, time_to_s(t), mesg_utc) @@ -548,253 +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")) - 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_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 1f4c623acb..44d238ffd2 100644 --- a/test/ruby/test_transcode.rb +++ b/test/ruby/test_transcode.rb @@ -2116,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") @@ -2183,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 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 b053e11607..a9b1fd50ff 100644 --- a/test/ruby/test_variable.rb +++ b/test/ruby/test_variable.rb @@ -35,57 +35,6 @@ class TestVariable < Test::Unit::TestCase end 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 - end - end - def test_variable assert_instance_of(Integer, $$) @@ -186,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) @@ -201,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_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 |
