summaryrefslogtreecommitdiff
path: root/test/ruby
diff options
context:
space:
mode:
Diffstat (limited to 'test/ruby')
-rw-r--r--test/ruby/enc/test_case_comprehensive.rb4
-rw-r--r--test/ruby/enc/test_emoji_breaks.rb208
-rw-r--r--test/ruby/enc/test_grapheme_breaks.rb4
-rw-r--r--test/ruby/enc/test_regex_casefold.rb4
-rw-r--r--test/ruby/rjit/test_assembler.rb368
-rw-r--r--test/ruby/test_argf.rb15
-rw-r--r--test/ruby/test_arity.rb43
-rw-r--r--test/ruby/test_array.rb143
-rw-r--r--test/ruby/test_assignment.rb108
-rw-r--r--test/ruby/test_ast.rb678
-rw-r--r--test/ruby/test_autoload.rb91
-rw-r--r--test/ruby/test_backtrace.rb35
-rw-r--r--test/ruby/test_beginendblock.rb9
-rw-r--r--test/ruby/test_bignum.rb13
-rw-r--r--test/ruby/test_call.rb1219
-rw-r--r--test/ruby/test_class.rb52
-rw-r--r--test/ruby/test_clone.rb53
-rw-r--r--test/ruby/test_comparable.rb10
-rw-r--r--test/ruby/test_compile_prism.rb2110
-rw-r--r--test/ruby/test_complex.rb144
-rw-r--r--test/ruby/test_complex2.rb2
-rw-r--r--test/ruby/test_complexrational.rb4
-rw-r--r--test/ruby/test_data.rb283
-rw-r--r--test/ruby/test_default_gems.rb19
-rw-r--r--test/ruby/test_defined.rb14
-rw-r--r--test/ruby/test_dir.rb155
-rw-r--r--test/ruby/test_dup.rb110
-rw-r--r--test/ruby/test_econv.rb2
-rw-r--r--test/ruby/test_encoding.rb35
-rw-r--r--test/ruby/test_enum.rb14
-rw-r--r--test/ruby/test_enumerator.rb136
-rw-r--r--test/ruby/test_env.rb56
-rw-r--r--test/ruby/test_eval.rb7
-rw-r--r--test/ruby/test_exception.rb147
-rw-r--r--test/ruby/test_fiber.rb4
-rw-r--r--test/ruby/test_file.rb54
-rw-r--r--test/ruby/test_file_exhaustive.rb68
-rw-r--r--test/ruby/test_float.rb20
-rw-r--r--test/ruby/test_frozen.rb30
-rw-r--r--test/ruby/test_gc.rb514
-rw-r--r--test/ruby/test_gc_compact.rb354
-rw-r--r--test/ruby/test_hash.rb753
-rw-r--r--test/ruby/test_integer.rb99
-rw-r--r--test/ruby/test_integer_comb.rb23
-rw-r--r--test/ruby/test_io.rb272
-rw-r--r--test/ruby/test_io_buffer.rb265
-rw-r--r--test/ruby/test_io_m17n.rb114
-rw-r--r--test/ruby/test_io_timeout.rb58
-rw-r--r--test/ruby/test_iseq.rb77
-rw-r--r--test/ruby/test_jit.rb1273
-rw-r--r--test/ruby/test_jit_debug.rb17
-rw-r--r--test/ruby/test_keyword.rb299
-rw-r--r--test/ruby/test_lambda.rb26
-rw-r--r--test/ruby/test_lazy_enumerator.rb25
-rw-r--r--test/ruby/test_m17n.rb74
-rw-r--r--test/ruby/test_marshal.rb40
-rw-r--r--test/ruby/test_math.rb10
-rw-r--r--test/ruby/test_method.rb124
-rw-r--r--test/ruby/test_module.rb133
-rw-r--r--test/ruby/test_nomethod_error.rb2
-rw-r--r--test/ruby/test_object.rb78
-rw-r--r--test/ruby/test_objectspace.rb5
-rw-r--r--test/ruby/test_optimization.rb27
-rw-r--r--test/ruby/test_pack.rb110
-rw-r--r--test/ruby/test_parse.rb295
-rw-r--r--test/ruby/test_pattern_matching.rb60
-rw-r--r--test/ruby/test_proc.rb198
-rw-r--r--test/ruby/test_process.rb261
-rw-r--r--test/ruby/test_rand.rb14
-rw-r--r--test/ruby/test_random_formatter.rb55
-rw-r--r--test/ruby/test_range.rb311
-rw-r--r--test/ruby/test_rational.rb2
-rw-r--r--test/ruby/test_refinement.rb305
-rw-r--r--test/ruby/test_regexp.rb713
-rw-r--r--test/ruby/test_require.rb38
-rw-r--r--test/ruby/test_require_lib.rb31
-rw-r--r--test/ruby/test_rubyoptions.rb295
-rw-r--r--test/ruby/test_rubyvm.rb4
-rw-r--r--test/ruby/test_rubyvm_jit.rb91
-rw-r--r--test/ruby/test_settracefunc.rb432
-rw-r--r--test/ruby/test_shapes.rb1041
-rw-r--r--test/ruby/test_signal.rb46
-rw-r--r--test/ruby/test_sprintf.rb17
-rw-r--r--test/ruby/test_stack.rb1
-rw-r--r--test/ruby/test_string.rb1125
-rw-r--r--test/ruby/test_string_memory.rb55
-rw-r--r--test/ruby/test_struct.rb32
-rw-r--r--test/ruby/test_super.rb12
-rw-r--r--test/ruby/test_symbol.rb19
-rw-r--r--test/ruby/test_syntax.rb291
-rw-r--r--test/ruby/test_system.rb13
-rw-r--r--test/ruby/test_thread.rb134
-rw-r--r--test/ruby/test_thread_cv.rb6
-rw-r--r--test/ruby/test_thread_queue.rb93
-rw-r--r--test/ruby/test_time.rb148
-rw-r--r--test/ruby/test_time_tz.rb10
-rw-r--r--test/ruby/test_transcode.rb512
-rw-r--r--test/ruby/test_variable.rb111
-rw-r--r--test/ruby/test_vm_dump.rb2
-rw-r--r--test/ruby/test_weakkeymap.rb144
-rw-r--r--test/ruby/test_weakmap.rb69
-rw-r--r--test/ruby/test_yjit.rb1146
-rw-r--r--test/ruby/test_yjit_exit_locations.rb96
103 files changed, 3926 insertions, 15545 deletions
diff --git a/test/ruby/enc/test_case_comprehensive.rb b/test/ruby/enc/test_case_comprehensive.rb
index de18ac865c..bde47017a2 100644
--- a/test/ruby/enc/test_case_comprehensive.rb
+++ b/test/ruby/enc/test_case_comprehensive.rb
@@ -24,7 +24,7 @@ class TestComprehensiveCaseMapping < Test::Unit::TestCase
def test_data_files_available
unless TestComprehensiveCaseMapping.data_files_available?
- omit "Unicode data files not available in #{UNICODE_DATA_PATH}."
+ skip "Unicode data files not available in #{UNICODE_DATA_PATH}."
end
end
end
@@ -37,7 +37,7 @@ TestComprehensiveCaseMapping.data_files_available? and class TestComprehensiveC
end
def self.read_data_file(filename)
- File.foreach(expand_filename(filename), encoding: Encoding::ASCII_8BIT) do |line|
+ IO.foreach(expand_filename(filename), encoding: Encoding::ASCII_8BIT) do |line|
if $. == 1
if filename == 'UnicodeData'
elsif line.start_with?("# #{filename}-#{UNICODE_VERSION}.txt")
diff --git a/test/ruby/enc/test_emoji_breaks.rb b/test/ruby/enc/test_emoji_breaks.rb
index bb5114680e..cdde4da9bf 100644
--- a/test/ruby/enc/test_emoji_breaks.rb
+++ b/test/ruby/enc/test_emoji_breaks.rb
@@ -4,47 +4,50 @@
require "test/unit"
class TestEmojiBreaks < Test::Unit::TestCase
- class 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' or filename=='emoji-variation-sequences'
- 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
+
+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' or filename=='emoji-variation-sequences'
+ 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 BreakFile
- attr_reader :basename, :fullname, :version
- FILES = []
+class TestEmojiBreaks::BreakFile
+ attr_reader :basename, :fullname, :version
+ FILES = []
- def initialize(basename, path, version)
- @basename = basename
- @fullname = "#{path}/#{basename}.txt" # File.expand_path(path + version, __dir__)
- @version = version
- FILES << self
- end
+ def initialize(basename, path, version)
+ @basename = basename
+ @fullname = "#{path}/#{basename}.txt" # File.expand_path(path + version, __dir__)
+ @version = version
+ FILES << self
+ end
- def self.files
- FILES
- end
+ def self.files
+ FILES
end
+end
+class TestEmojiBreaks < Test::Unit::TestCase
UNICODE_VERSION = RbConfig::CONFIG['UNICODE_VERSION']
UNICODE_DATA_PATH = File.expand_path("../../../enc/unicode/data/#{UNICODE_VERSION}/ucd/emoji", __dir__)
EMOJI_VERSION = RbConfig::CONFIG['UNICODE_EMOJI_VERSION']
@@ -53,7 +56,7 @@ class TestEmojiBreaks < Test::Unit::TestCase
EMOJI_DATA_FILES = %w[emoji-sequences emoji-test emoji-zwj-sequences].map do |basename|
BreakFile.new(basename, EMOJI_DATA_PATH, EMOJI_VERSION)
end
- UNICODE_DATA_FILE = BreakFile.new('emoji-variation-sequences', UNICODE_DATA_PATH, UNICODE_VERSION)
+ UNICODE_DATA_FILE = BreakFile.new('emoji-variation-sequences', UNICODE_DATA_PATH, UNICODE_VERSION[0..-3]) # [0..-3] deals with a versioning mismatch problem in Unicode
EMOJI_DATA_FILES << UNICODE_DATA_FILE
def self.data_files_available?
@@ -65,90 +68,83 @@ class TestEmojiBreaks < Test::Unit::TestCase
def test_data_files_available
assert_equal 4, EMOJI_DATA_FILES.size # debugging test
unless TestEmojiBreaks.data_files_available?
- omit "Emoji data files not available in #{EMOJI_DATA_PATH}."
+ skip "Emoji data files not available in #{EMOJI_DATA_PATH}."
end
end
+end
- if data_files_available?
- def read_data
- tests = []
- EMOJI_DATA_FILES.each do |file|
- version_mismatch = true
- file_tests = []
- File.foreach(file.fullname, encoding: Encoding::UTF_8) do |line|
- line.chomp!
- if $.==1
- if line=="# #{file.basename}-#{file.version}.txt"
- version_mismatch = false
- elsif line!="# #{file.basename}.txt"
- raise "File Name Mismatch: line: #{line}, expected filename: #{file.basename}.txt"
- end
- end
- version_mismatch = false if line =~ /^# Version: #{file.version}/ # 13.0 and older
- version_mismatch = false if line =~ /^# Used with Emoji Version #{EMOJI_VERSION}/ # 14.0 and newer
- next if line.match?(/\A(#|\z)/)
- if line =~ /^(\h{4,6})\.\.(\h{4,6}) *(;.+)/ # deal with Unicode ranges in emoji-sequences.txt (Bug #18028)
- range_start = $1.to_i(16)
- range_end = $2.to_i(16)
- rest = $3
- (range_start..range_end).each do |code_point|
- file_tests << BreakTest.new(file.basename, $., *(code_point.to_s(16)+rest).split('#', 2))
- end
- else
- file_tests << BreakTest.new(file.basename, $., *line.split('#', 2))
+TestEmojiBreaks.data_files_available? and class TestEmojiBreaks
+ def read_data
+ tests = []
+ EMOJI_DATA_FILES.each do |file|
+ version_mismatch = true
+ file_tests = []
+ IO.foreach(file.fullname, encoding: Encoding::UTF_8) do |line|
+ line.chomp!
+ raise "File Name Mismatch: line: #{line}, expected filename: #{file.basename}.txt" if $.==1 and not line=="# #{file.basename}.txt"
+ version_mismatch = false if line =~ /^# Version: #{file.version}/
+ next if line.match?(/\A(#|\z)/)
+ if line =~ /^(\h{4,6})\.\.(\h{4,6}) *(;.+)/ # deal with Unicode ranges in emoji-sequences.txt (Bug #18028)
+ range_start = $1.to_i(16)
+ range_end = $2.to_i(16)
+ rest = $3
+ (range_start..range_end).each do |code_point|
+ file_tests << BreakTest.new(file.basename, $., *(code_point.to_s(16)+rest).split('#', 2))
end
+ else
+ file_tests << BreakTest.new(file.basename, $., *line.split('#', 2))
end
- raise "File Version Mismatch: file: #{file.fullname}, version: #{file.version}" if version_mismatch
- tests += file_tests
end
- tests
+ raise "File Version Mismatch: file: #{file.fullname}, version: #{file.version}" if version_mismatch
+ tests += file_tests
end
+ tests
+ end
- def all_tests
- @@tests ||= read_data
- rescue Errno::ENOENT
- @@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
+ 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
+ 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
+ # 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
diff --git a/test/ruby/enc/test_grapheme_breaks.rb b/test/ruby/enc/test_grapheme_breaks.rb
index 7e6d722d40..e8f3aa04a7 100644
--- a/test/ruby/enc/test_grapheme_breaks.rb
+++ b/test/ruby/enc/test_grapheme_breaks.rb
@@ -37,14 +37,14 @@ class TestGraphemeBreaksFromFile < Test::Unit::TestCase
def test_data_files_available
unless TestGraphemeBreaksFromFile.file_available?
- omit "Unicode data file GraphemeBreakTest not available in #{UNICODE_DATA_PATH}."
+ skip "Unicode data file GraphemeBreakTest not available in #{UNICODE_DATA_PATH}."
end
end
if file_available?
def read_data
tests = []
- File.foreach(GRAPHEME_BREAK_TEST_FILE, encoding: Encoding::UTF_8) do |line|
+ IO.foreach(GRAPHEME_BREAK_TEST_FILE, encoding: Encoding::UTF_8) do |line|
if $. == 1 and not line.start_with?("# GraphemeBreakTest-#{UNICODE_VERSION}.txt")
raise "File Version Mismatch"
end
diff --git a/test/ruby/enc/test_regex_casefold.rb b/test/ruby/enc/test_regex_casefold.rb
index b5d5c6e337..ec5dc7f220 100644
--- a/test/ruby/enc/test_regex_casefold.rb
+++ b/test/ruby/enc/test_regex_casefold.rb
@@ -19,7 +19,7 @@ class TestCaseFold < Test::Unit::TestCase
end
def read_tests
- File.readlines("#{UNICODE_DATA_PATH}/CaseFolding.txt", encoding: Encoding::ASCII_8BIT)
+ IO.readlines("#{UNICODE_DATA_PATH}/CaseFolding.txt", encoding: Encoding::ASCII_8BIT)
.collect.with_index { |linedata, linenumber| [linenumber.to_i+1, linedata.chomp] }
.reject { |number, data| data =~ /^(#|$)/ }
.collect do |linenumber, linedata|
@@ -39,7 +39,7 @@ class TestCaseFold < Test::Unit::TestCase
@@tests ||= read_tests
rescue Errno::ENOENT => e
@@tests ||= []
- omit e.message
+ skip e.message
end
def self.generate_test_casefold(encoding)
diff --git a/test/ruby/rjit/test_assembler.rb b/test/ruby/rjit/test_assembler.rb
deleted file mode 100644
index fbf780d6c3..0000000000
--- a/test/ruby/rjit/test_assembler.rb
+++ /dev/null
@@ -1,368 +0,0 @@
-require 'test/unit'
-require_relative '../../lib/jit_support'
-
-return unless JITSupport.rjit_supported?
-return unless RubyVM::RJIT.enabled?
-return unless RubyVM::RJIT::C.HAVE_LIBCAPSTONE
-
-require 'stringio'
-require 'ruby_vm/rjit/assembler'
-
-module RubyVM::RJIT
- class TestAssembler < Test::Unit::TestCase
- MEM_SIZE = 16 * 1024
-
- def setup
- @mem_block ||= C.mmap(MEM_SIZE)
- @cb = CodeBlock.new(mem_block: @mem_block, mem_size: MEM_SIZE)
- end
-
- def test_add
- asm = Assembler.new
- asm.add([:rcx], 1) # ADD r/m64, imm8 (Mod 00: [reg])
- asm.add(:rax, 0x7f) # ADD r/m64, imm8 (Mod 11: reg)
- asm.add(:rbx, 0x7fffffff) # ADD r/m64 imm32 (Mod 11: reg)
- asm.add(:rsi, :rdi) # ADD r/m64, r64 (Mod 11: reg)
- assert_compile(asm, <<~EOS)
- 0x0: add qword ptr [rcx], 1
- 0x4: add rax, 0x7f
- 0x8: add rbx, 0x7fffffff
- 0xf: add rsi, rdi
- EOS
- end
-
- def test_and
- asm = Assembler.new
- asm.and(:rax, 0) # AND r/m64, imm8 (Mod 11: reg)
- asm.and(:rbx, 0x7fffffff) # AND r/m64, imm32 (Mod 11: reg)
- asm.and(:rcx, [:rdi, 8]) # AND r64, r/m64 (Mod 01: [reg]+disp8)
- assert_compile(asm, <<~EOS)
- 0x0: and rax, 0
- 0x4: and rbx, 0x7fffffff
- 0xb: and rcx, qword ptr [rdi + 8]
- EOS
- end
-
- def test_call
- asm = Assembler.new
- asm.call(rel32(0xff)) # CALL rel32
- asm.call(:rax) # CALL r/m64 (Mod 11: reg)
- assert_compile(asm, <<~EOS)
- 0x0: call 0xff
- 0x5: call rax
- EOS
- end
-
- def test_cmove
- asm = Assembler.new
- asm.cmove(:rax, :rcx) # CMOVE r64, r/m64 (Mod 11: reg)
- assert_compile(asm, <<~EOS)
- 0x0: cmove rax, rcx
- EOS
- end
-
- def test_cmovg
- asm = Assembler.new
- asm.cmovg(:rbx, :rdi) # CMOVG r64, r/m64 (Mod 11: reg)
- assert_compile(asm, <<~EOS)
- 0x0: cmovg rbx, rdi
- EOS
- end
-
- def test_cmovge
- asm = Assembler.new
- asm.cmovge(:rsp, :rbp) # CMOVGE r64, r/m64 (Mod 11: reg)
- assert_compile(asm, <<~EOS)
- 0x0: cmovge rsp, rbp
- EOS
- end
-
- def test_cmovl
- asm = Assembler.new
- asm.cmovl(:rdx, :rsp) # CMOVL r64, r/m64 (Mod 11: reg)
- assert_compile(asm, <<~EOS)
- 0x0: cmovl rdx, rsp
- EOS
- end
-
- def test_cmovle
- asm = Assembler.new
- asm.cmovle(:rax, :rax) # CMOVLE r64, r/m64 (Mod 11: reg)
- assert_compile(asm, <<~EOS)
- 0x0: cmovle rax, rax
- EOS
- end
-
- def test_cmovne
- asm = Assembler.new
- asm.cmovne(:rax, :rbx) # CMOVNE r64, r/m64 (Mod 11: reg)
- assert_compile(asm, <<~EOS) # cmovne == cmovnz
- 0x0: cmovne rax, rbx
- EOS
- end
-
- def test_cmovnz
- asm = Assembler.new
- asm.cmovnz(:rax, :rbx) # CMOVNZ r64, r/m64 (Mod 11: reg)
- assert_compile(asm, <<~EOS) # cmovne == cmovnz
- 0x0: cmovne rax, rbx
- EOS
- end
-
- def test_cmovz
- asm = Assembler.new
- asm.cmovz(:rax, :rbx) # CMOVZ r64, r/m64 (Mod 11: reg)
- assert_compile(asm, <<~EOS) # cmove == cmovz
- 0x0: cmove rax, rbx
- EOS
- end
-
- def test_cmp
- asm = Assembler.new
- asm.cmp(BytePtr[:rax, 8], 8) # CMP r/m8, imm8 (Mod 01: [reg]+disp8)
- asm.cmp(DwordPtr[:rax, 8], 0x100) # CMP r/m32, imm32 (Mod 01: [reg]+disp8)
- asm.cmp([:rax, 8], 8) # CMP r/m64, imm8 (Mod 01: [reg]+disp8)
- asm.cmp([:rbx, 8], 0x100) # CMP r/m64, imm32 (Mod 01: [reg]+disp8)
- asm.cmp([:rax, 0x100], 8) # CMP r/m64, imm8 (Mod 10: [reg]+disp32)
- asm.cmp(:rax, 8) # CMP r/m64, imm8 (Mod 11: reg)
- asm.cmp(:rax, 0x100) # CMP r/m64, imm32 (Mod 11: reg)
- asm.cmp([:rax, 8], :rbx) # CMP r/m64, r64 (Mod 01: [reg]+disp8)
- asm.cmp([:rax, -0x100], :rbx) # CMP r/m64, r64 (Mod 10: [reg]+disp32)
- asm.cmp(:rax, :rbx) # CMP r/m64, r64 (Mod 11: reg)
- assert_compile(asm, <<~EOS)
- 0x0: cmp byte ptr [rax + 8], 8
- 0x4: cmp dword ptr [rax + 8], 0x100
- 0xb: cmp qword ptr [rax + 8], 8
- 0x10: cmp qword ptr [rbx + 8], 0x100
- 0x18: cmp qword ptr [rax + 0x100], 8
- 0x20: cmp rax, 8
- 0x24: cmp rax, 0x100
- 0x2b: cmp qword ptr [rax + 8], rbx
- 0x2f: cmp qword ptr [rax - 0x100], rbx
- 0x36: cmp rax, rbx
- EOS
- end
-
- def test_jbe
- asm = Assembler.new
- asm.jbe(rel32(0xff)) # JBE rel32
- assert_compile(asm, <<~EOS)
- 0x0: jbe 0xff
- EOS
- end
-
- def test_je
- asm = Assembler.new
- asm.je(rel32(0xff)) # JE rel32
- assert_compile(asm, <<~EOS)
- 0x0: je 0xff
- EOS
- end
-
- def test_jl
- asm = Assembler.new
- asm.jl(rel32(0xff)) # JL rel32
- assert_compile(asm, <<~EOS)
- 0x0: jl 0xff
- EOS
- end
-
- def test_jmp
- asm = Assembler.new
- label = asm.new_label('label')
- asm.jmp(label) # JZ rel8
- asm.write_label(label)
- asm.jmp(rel32(0xff)) # JMP rel32
- asm.jmp([:rax, 8]) # JMP r/m64 (Mod 01: [reg]+disp8)
- asm.jmp(:rax) # JMP r/m64 (Mod 11: reg)
- assert_compile(asm, <<~EOS)
- 0x0: jmp 2
- 0x2: jmp 0xff
- 0x7: jmp qword ptr [rax + 8]
- 0xa: jmp rax
- EOS
- end
-
- def test_jne
- asm = Assembler.new
- asm.jne(rel32(0xff)) # JNE rel32
- assert_compile(asm, <<~EOS)
- 0x0: jne 0xff
- EOS
- end
-
- def test_jnz
- asm = Assembler.new
- asm.jnz(rel32(0xff)) # JNZ rel32
- assert_compile(asm, <<~EOS)
- 0x0: jne 0xff
- EOS
- end
-
- def test_jo
- asm = Assembler.new
- asm.jo(rel32(0xff)) # JO rel32
- assert_compile(asm, <<~EOS)
- 0x0: jo 0xff
- EOS
- end
-
- def test_jz
- asm = Assembler.new
- asm.jz(rel32(0xff)) # JZ rel32
- assert_compile(asm, <<~EOS)
- 0x0: je 0xff
- EOS
- end
-
- def test_lea
- asm = Assembler.new
- asm.lea(:rax, [:rax, 8]) # LEA r64,m (Mod 01: [reg]+disp8)
- asm.lea(:rax, [:rax, 0xffff]) # LEA r64,m (Mod 10: [reg]+disp32)
- assert_compile(asm, <<~EOS)
- 0x0: lea rax, [rax + 8]
- 0x4: lea rax, [rax + 0xffff]
- EOS
- end
-
- def test_mov
- asm = Assembler.new
- asm.mov(:eax, DwordPtr[:rbx, 8]) # MOV r32 r/m32 (Mod 01: [reg]+disp8)
- asm.mov(:eax, 0x100) # MOV r32, imm32 (Mod 11: reg)
- asm.mov(:rax, [:rbx]) # MOV r64, r/m64 (Mod 00: [reg])
- asm.mov(:rax, [:rbx, 8]) # MOV r64, r/m64 (Mod 01: [reg]+disp8)
- asm.mov(:rax, [:rbx, 0x100]) # MOV r64, r/m64 (Mod 10: [reg]+disp32)
- asm.mov(:rax, :rbx) # MOV r64, r/m64 (Mod 11: reg)
- asm.mov(:rax, 0x100) # MOV r/m64, imm32 (Mod 11: reg)
- asm.mov(:rax, 0x100000000) # MOV r64, imm64
- asm.mov(DwordPtr[:rax, 8], 0x100) # MOV r/m32, imm32 (Mod 01: [reg]+disp8)
- asm.mov([:rax], 0x100) # MOV r/m64, imm32 (Mod 00: [reg])
- asm.mov([:rax], :rbx) # MOV r/m64, r64 (Mod 00: [reg])
- asm.mov([:rax, 8], 0x100) # MOV r/m64, imm32 (Mod 01: [reg]+disp8)
- asm.mov([:rax, 8], :rbx) # MOV r/m64, r64 (Mod 01: [reg]+disp8)
- asm.mov([:rax, 0x100], 0x100) # MOV r/m64, imm32 (Mod 10: [reg]+disp32)
- asm.mov([:rax, 0x100], :rbx) # MOV r/m64, r64 (Mod 10: [reg]+disp32)
- assert_compile(asm, <<~EOS)
- 0x0: mov eax, dword ptr [rbx + 8]
- 0x3: mov eax, 0x100
- 0x8: mov rax, qword ptr [rbx]
- 0xb: mov rax, qword ptr [rbx + 8]
- 0xf: mov rax, qword ptr [rbx + 0x100]
- 0x16: mov rax, rbx
- 0x19: mov rax, 0x100
- 0x20: movabs rax, 0x100000000
- 0x2a: mov dword ptr [rax + 8], 0x100
- 0x31: mov qword ptr [rax], 0x100
- 0x38: mov qword ptr [rax], rbx
- 0x3b: mov qword ptr [rax + 8], 0x100
- 0x43: mov qword ptr [rax + 8], rbx
- 0x47: mov qword ptr [rax + 0x100], 0x100
- 0x52: mov qword ptr [rax + 0x100], rbx
- EOS
- end
-
- def test_or
- asm = Assembler.new
- asm.or(:rax, 0) # OR r/m64, imm8 (Mod 11: reg)
- asm.or(:rax, 0xffff) # OR r/m64, imm32 (Mod 11: reg)
- asm.or(:rax, [:rbx, 8]) # OR r64, r/m64 (Mod 01: [reg]+disp8)
- assert_compile(asm, <<~EOS)
- 0x0: or rax, 0
- 0x4: or rax, 0xffff
- 0xb: or rax, qword ptr [rbx + 8]
- EOS
- end
-
- def test_push
- asm = Assembler.new
- asm.push(:rax) # PUSH r64
- assert_compile(asm, <<~EOS)
- 0x0: push rax
- EOS
- end
-
- def test_pop
- asm = Assembler.new
- asm.pop(:rax) # POP r64
- assert_compile(asm, <<~EOS)
- 0x0: pop rax
- EOS
- end
-
- def test_ret
- asm = Assembler.new
- asm.ret # RET
- assert_compile(asm, "0x0: ret \n")
- end
-
- def test_sar
- asm = Assembler.new
- asm.sar(:rax, 0) # SAR r/m64, imm8 (Mod 11: reg)
- assert_compile(asm, <<~EOS)
- 0x0: sar rax, 0
- EOS
- end
-
- def test_sub
- asm = Assembler.new
- asm.sub(:rax, 8) # SUB r/m64, imm8 (Mod 11: reg)
- asm.sub(:rax, :rbx) # SUB r/m64, r64 (Mod 11: reg)
- assert_compile(asm, <<~EOS)
- 0x0: sub rax, 8
- 0x4: sub rax, rbx
- EOS
- end
-
- def test_test
- asm = Assembler.new
- asm.test(BytePtr[:rax, 8], 16) # TEST r/m8*, imm8 (Mod 01: [reg]+disp8)
- asm.test([:rax, 8], 8) # TEST r/m64, imm32 (Mod 01: [reg]+disp8)
- asm.test([:rax, 0xffff], 0xffff) # TEST r/m64, imm32 (Mod 10: [reg]+disp32)
- asm.test(:rax, 0xffff) # TEST r/m64, imm32 (Mod 11: reg)
- asm.test(:eax, :ebx) # TEST r/m32, r32 (Mod 11: reg)
- asm.test(:rax, :rbx) # TEST r/m64, r64 (Mod 11: reg)
- assert_compile(asm, <<~EOS)
- 0x0: test byte ptr [rax + 8], 0x10
- 0x4: test qword ptr [rax + 8], 8
- 0xc: test qword ptr [rax + 0xffff], 0xffff
- 0x17: test rax, 0xffff
- 0x1e: test eax, ebx
- 0x20: test rax, rbx
- EOS
- end
-
- def test_xor
- asm = Assembler.new
- asm.xor(:rax, :rbx)
- assert_compile(asm, <<~EOS)
- 0x0: xor rax, rbx
- EOS
- end
-
- private
-
- def rel32(offset)
- @cb.write_addr + 0xff
- end
-
- def assert_compile(asm, expected)
- actual = compile(asm)
- assert_equal expected, actual, "---\n#{actual}---"
- end
-
- def compile(asm)
- start_addr = @cb.write_addr
- @cb.write(asm)
- end_addr = @cb.write_addr
-
- io = StringIO.new
- @cb.dump_disasm(start_addr, end_addr, io:, color: false, test: true)
- io.seek(0)
- disasm = io.read
-
- disasm.gsub!(/^ /, '')
- disasm.sub!(/\n\z/, '')
- disasm
- end
- end
-end
diff --git a/test/ruby/test_argf.rb b/test/ruby/test_argf.rb
index 12f7d6485a..e3bd1cd075 100644
--- a/test/ruby/test_argf.rb
+++ b/test/ruby/test_argf.rb
@@ -143,17 +143,6 @@ class TestArgf < Test::Unit::TestCase
};
end
- def test_lineno_after_shebang
- expected = %w"1 1 1 2 2 2 3 3 1 4 4 2"
- assert_in_out_err(["--enable=gems", "-", @t1.path, @t2.path], "#{<<~"{#"}\n#{<<~'};'}", expected)
- #!/usr/bin/env ruby
- {#
- ARGF.each do |line|
- puts [$., ARGF.lineno, ARGF.file.lineno]
- end
- };
- end
-
def test_new_lineno_each
f = ARGF.class.new(@t1.path, @t2.path, @t3.path)
result = []
@@ -268,13 +257,13 @@ class TestArgf < Test::Unit::TestCase
def test_inplace_nonascii
ext = Encoding.default_external or
- omit "no default external encoding"
+ 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 omit "no name to test"
+ t or skip "no name to test"
assert_in_out_err(["-i.bak", "-", t.path],
"#{<<~"{#"}\n#{<<~'};'}")
{#
diff --git a/test/ruby/test_arity.rb b/test/ruby/test_arity.rb
index bd26d5f0f5..b98248f603 100644
--- a/test/ruby/test_arity.rb
+++ b/test/ruby/test_arity.rb
@@ -2,7 +2,7 @@
require 'test/unit'
class TestArity < Test::Unit::TestCase
- def assert_arity(expected, method_proc = nil, argc = 0)
+ def err_mess(method_proc = nil, argc = 0)
args = (1..argc).to_a
assert_raise_with_message(ArgumentError, /wrong number of arguments \(.*\b(\d+)\b.* (\d\S*?)\)/) do
case method_proc
@@ -14,7 +14,7 @@ class TestArity < Test::Unit::TestCase
method_proc.call(*args)
end
end
- assert_equal expected, [$1, $2]
+ [$1, $2]
end
def a
@@ -36,22 +36,22 @@ class TestArity < Test::Unit::TestCase
end
def test_method_err_mess
- assert_arity(%w[1 0], :a, 1)
- assert_arity(%w[10 7..9], :b, 10)
- assert_arity(%w[2 3+], :c, 2)
- assert_arity(%w[2 1], :d, 2)
- assert_arity(%w[0 1], :d, 0)
- assert_arity(%w[2 1], :e, 2)
- assert_arity(%w[0 1], :e, 0)
- assert_arity(%w[1 2+], :f, 1)
+ assert_equal %w[1 0], err_mess(:a, 1)
+ assert_equal %w[10 7..9], err_mess(:b, 10)
+ assert_equal %w[2 3+], err_mess(:c, 2)
+ assert_equal %w[2 1], err_mess(:d, 2)
+ assert_equal %w[0 1], err_mess(:d, 0)
+ assert_equal %w[2 1], err_mess(:e, 2)
+ assert_equal %w[0 1], err_mess(:e, 0)
+ assert_equal %w[1 2+], err_mess(:f, 1)
end
def test_proc_err_mess
- assert_arity(%w[0 1..2], ->(b, c=42){}, 0)
- assert_arity(%w[1 2+], ->(a, b, c=42, *d){}, 1)
- assert_arity(%w[3 4+], ->(a, b, *c, d, e){}, 3)
- assert_arity(%w[3 1..2], ->(b, c=42){}, 3)
- assert_arity(%w[1 0], ->(&block){}, 1)
+ assert_equal %w[0 1..2], err_mess(->(b, c=42){}, 0)
+ assert_equal %w[1 2+], err_mess(->(a, b, c=42, *d){}, 1)
+ assert_equal %w[3 4+], err_mess(->(a, b, *c, d, e){}, 3)
+ assert_equal %w[3 1..2], err_mess(->(b, c=42){}, 3)
+ assert_equal %w[1 0], err_mess(->(&block){}, 1)
# Double checking:
p = Proc.new{|b, c=42| :ok}
assert_equal :ok, p.call(1, 2, 3)
@@ -59,11 +59,12 @@ class TestArity < Test::Unit::TestCase
end
def test_message_change_issue_6085
- assert_arity(%w[3 1..2]) { SignalException.new(1, "", nil) }
- assert_arity(%w[1 0]) { Hash.new(1){} }
- assert_arity(%w[3 1..2]) { Module.send :define_method, 1, 2, 3 }
- assert_arity(%w[1 2]) { "".sub!(//) }
- assert_arity(%w[0 1..2]) { "".sub!{} }
- assert_arity(%w[0 1+]) { exec }
+ assert_equal %w[3 1..2], err_mess{ SignalException.new(1, "", nil) }
+ assert_equal %w[1 0], err_mess{ Hash.new(1){} }
+ assert_equal %w[3 1..2], err_mess{ Module.send :define_method, 1, 2, 3 }
+ assert_equal %w[1 2], err_mess{ "".sub!(//) }
+ assert_equal %w[0 1..2], err_mess{ "".sub!{} }
+ assert_equal %w[0 1+], err_mess{ exec }
+ assert_equal %w[0 1+], err_mess{ Struct.new }
end
end
diff --git a/test/ruby/test_array.rb b/test/ruby/test_array.rb
index 97e2fa3de8..0ed8ada95c 100644
--- a/test/ruby/test_array.rb
+++ b/test/ruby/test_array.rb
@@ -529,19 +529,14 @@ class TestArray < Test::Unit::TestCase
end
def test_assoc
- def (a4 = Object.new).to_ary
- %w( pork porcine )
- end
-
a1 = @cls[*%w( cat feline )]
a2 = @cls[*%w( dog canine )]
a3 = @cls[*%w( mule asinine )]
- a = @cls[ a1, a2, a3, a4 ]
+ a = @cls[ a1, a2, a3 ]
assert_equal(a1, a.assoc('cat'))
assert_equal(a3, a.assoc('mule'))
- assert_equal(%w( pork porcine ), a.assoc("pork"))
assert_equal(nil, a.assoc('asinine'))
assert_equal(nil, a.assoc('wombat'))
assert_equal(nil, a.assoc(1..2))
@@ -1334,17 +1329,13 @@ class TestArray < Test::Unit::TestCase
end
def test_rassoc
- def (a4 = Object.new).to_ary
- %w( pork porcine )
- end
a1 = @cls[*%w( cat feline )]
a2 = @cls[*%w( dog canine )]
a3 = @cls[*%w( mule asinine )]
- a = @cls[ a1, a2, a3, a4 ]
+ a = @cls[ a1, a2, a3 ]
assert_equal(a1, a.rassoc('feline'))
assert_equal(a3, a.rassoc('asinine'))
- assert_equal(%w( pork porcine ), a.rassoc("porcine"))
assert_equal(nil, a.rassoc('dog'))
assert_equal(nil, a.rassoc('mule'))
assert_equal(nil, a.rassoc(1..2))
@@ -1454,14 +1445,6 @@ class TestArray < Test::Unit::TestCase
assert_raise(FrozenError) { fa.replace(42) }
end
- def test_replace_wb_variable_width_alloc
- small_embed = []
- 4.times { GC.start } # age small_embed
- large_embed = [1, 2, 3, 4, 5, Array.new] # new young object
- small_embed.replace(large_embed) # adds old to young reference
- GC.verify_internal_consistency
- end
-
def test_reverse
a = @cls[*%w( dog cat bee ant )]
assert_equal(@cls[*%w(ant bee cat dog)], a.reverse)
@@ -1595,96 +1578,6 @@ class TestArray < Test::Unit::TestCase
assert_equal_instance(a.values_at(*idx), a.slice((3..90)%2))
idx = 90.step(3, -2).to_a
assert_equal_instance(a.values_at(*idx), a.slice((90 .. 3)% -2))
-
- a = [0, 1, 2, 3, 4, 5]
- assert_equal([2, 1, 0], a.slice((2..).step(-1)))
- assert_equal([2, 0], a.slice((2..).step(-2)))
- assert_equal([2], a.slice((2..).step(-3)))
- assert_equal([2], a.slice((2..).step(-4)))
-
- assert_equal([3, 2, 1, 0], a.slice((-3..).step(-1)))
- assert_equal([3, 1], a.slice((-3..).step(-2)))
- assert_equal([3, 0], a.slice((-3..).step(-3)))
- assert_equal([3], a.slice((-3..).step(-4)))
- assert_equal([3], a.slice((-3..).step(-5)))
-
- assert_equal([5, 4, 3, 2, 1, 0], a.slice((..0).step(-1)))
- assert_equal([5, 3, 1], a.slice((..0).step(-2)))
- assert_equal([5, 2], a.slice((..0).step(-3)))
- assert_equal([5, 1], a.slice((..0).step(-4)))
- assert_equal([5, 0], a.slice((..0).step(-5)))
- assert_equal([5], a.slice((..0).step(-6)))
- assert_equal([5], a.slice((..0).step(-7)))
-
- assert_equal([5, 4, 3, 2, 1], a.slice((...0).step(-1)))
- assert_equal([5, 3, 1], a.slice((...0).step(-2)))
- assert_equal([5, 2], a.slice((...0).step(-3)))
- assert_equal([5, 1], a.slice((...0).step(-4)))
- assert_equal([5], a.slice((...0).step(-5)))
- assert_equal([5], a.slice((...0).step(-6)))
-
- assert_equal([5, 4, 3, 2], a.slice((...1).step(-1)))
- assert_equal([5, 3], a.slice((...1).step(-2)))
- assert_equal([5, 2], a.slice((...1).step(-3)))
- assert_equal([5], a.slice((...1).step(-4)))
- assert_equal([5], a.slice((...1).step(-5)))
-
- assert_equal([5, 4, 3, 2, 1], a.slice((..-5).step(-1)))
- assert_equal([5, 3, 1], a.slice((..-5).step(-2)))
- assert_equal([5, 2], a.slice((..-5).step(-3)))
- assert_equal([5, 1], a.slice((..-5).step(-4)))
- assert_equal([5], a.slice((..-5).step(-5)))
- assert_equal([5], a.slice((..-5).step(-6)))
-
- assert_equal([5, 4, 3, 2], a.slice((...-5).step(-1)))
- assert_equal([5, 3], a.slice((...-5).step(-2)))
- assert_equal([5, 2], a.slice((...-5).step(-3)))
- assert_equal([5], a.slice((...-5).step(-4)))
- assert_equal([5], a.slice((...-5).step(-5)))
-
- assert_equal([4, 3, 2, 1], a.slice((4..1).step(-1)))
- assert_equal([4, 2], a.slice((4..1).step(-2)))
- assert_equal([4, 1], a.slice((4..1).step(-3)))
- assert_equal([4], a.slice((4..1).step(-4)))
- assert_equal([4], a.slice((4..1).step(-5)))
-
- assert_equal([4, 3, 2], a.slice((4...1).step(-1)))
- assert_equal([4, 2], a.slice((4...1).step(-2)))
- assert_equal([4], a.slice((4...1).step(-3)))
- assert_equal([4], a.slice((4...1).step(-4)))
-
- assert_equal([4, 3, 2, 1], a.slice((-2..1).step(-1)))
- assert_equal([4, 2], a.slice((-2..1).step(-2)))
- assert_equal([4, 1], a.slice((-2..1).step(-3)))
- assert_equal([4], a.slice((-2..1).step(-4)))
- assert_equal([4], a.slice((-2..1).step(-5)))
-
- assert_equal([4, 3, 2], a.slice((-2...1).step(-1)))
- assert_equal([4, 2], a.slice((-2...1).step(-2)))
- assert_equal([4], a.slice((-2...1).step(-3)))
- assert_equal([4], a.slice((-2...1).step(-4)))
-
- assert_equal([4, 3, 2, 1], a.slice((4..-5).step(-1)))
- assert_equal([4, 2], a.slice((4..-5).step(-2)))
- assert_equal([4, 1], a.slice((4..-5).step(-3)))
- assert_equal([4], a.slice((4..-5).step(-4)))
- assert_equal([4], a.slice((4..-5).step(-5)))
-
- assert_equal([4, 3, 2], a.slice((4...-5).step(-1)))
- assert_equal([4, 2], a.slice((4...-5).step(-2)))
- assert_equal([4], a.slice((4...-5).step(-3)))
- assert_equal([4], a.slice((4...-5).step(-4)))
-
- assert_equal([4, 3, 2, 1], a.slice((-2..-5).step(-1)))
- assert_equal([4, 2], a.slice((-2..-5).step(-2)))
- assert_equal([4, 1], a.slice((-2..-5).step(-3)))
- assert_equal([4], a.slice((-2..-5).step(-4)))
- assert_equal([4], a.slice((-2..-5).step(-5)))
-
- assert_equal([4, 3, 2], a.slice((-2...-5).step(-1)))
- assert_equal([4, 2], a.slice((-2...-5).step(-2)))
- assert_equal([4], a.slice((-2...-5).step(-3)))
- assert_equal([4], a.slice((-2...-5).step(-4)))
end
def test_slice_out_of_range
@@ -1702,14 +1595,6 @@ class TestArray < Test::Unit::TestCase
assert_equal([100], a.slice(-1, 1_000_000_000))
end
- def test_slice_gc_compact_stress
- EnvUtil.under_gc_compact_stress { assert_equal([1, 2, 3, 4, 5], (0..10).to_a[1, 5]) }
- EnvUtil.under_gc_compact_stress do
- a = [0, 1, 2, 3, 4, 5]
- assert_equal([2, 1, 0], a.slice((2..).step(-1)))
- end
- end
-
def test_slice!
a = @cls[1, 2, 3, 4, 5]
assert_equal(3, a.slice!(2))
@@ -3003,9 +2888,7 @@ class TestArray < Test::Unit::TestCase
assert_raise(RangeError) {
[*0..2].shuffle(random: gen)
}
- end
- def test_shuffle_random_clobbering
ary = (0...10000).to_a
gen = proc do
ary.replace([])
@@ -3015,9 +2898,7 @@ class TestArray < Test::Unit::TestCase
alias rand call
end
assert_raise(RuntimeError) {ary.shuffle!(random: gen)}
- end
- def test_shuffle_random_zero
zero = Object.new
def zero.to_int
0
@@ -3030,10 +2911,7 @@ class TestArray < Test::Unit::TestCase
end
ary = (0...10000).to_a
assert_equal(ary.rotate, ary.shuffle(random: gen_to_int))
- end
- def test_shuffle_random_invalid_generator
- ary = (0...10).to_a
assert_raise(NoMethodError) {
ary.shuffle(random: Object.new)
}
@@ -3050,9 +2928,7 @@ class TestArray < Test::Unit::TestCase
assert_include([0, 1, 2], sample)
}
end
- end
- def test_sample_statistics
srand(0)
a = (1..18).to_a
(0..20).each do |n|
@@ -3069,13 +2945,9 @@ class TestArray < Test::Unit::TestCase
end
assert_operator(h.values.min * 2, :>=, h.values.max) if n != 0
end
- end
- def test_sample_invalid_argument
assert_raise(ArgumentError, '[ruby-core:23374]') {[1, 2].sample(-1)}
- end
- def test_sample_random_srand0
gen = Random.new(0)
srand(0)
a = (1..18).to_a
@@ -3084,15 +2956,13 @@ class TestArray < Test::Unit::TestCase
assert_equal(a.sample(n), a.sample(n, random: gen), "#{i}/#{n}")
end
end
- end
- def test_sample_unknown_keyword
assert_raise_with_message(ArgumentError, /unknown keyword/) do
[0, 1, 2].sample(xawqij: "a")
end
end
- def test_sample_random_generator
+ def test_sample_random
ary = (0...10000).to_a
assert_raise(ArgumentError) {ary.sample(1, 2, random: nil)}
gen0 = proc do |max|
@@ -3135,9 +3005,7 @@ class TestArray < Test::Unit::TestCase
assert_equal([5000, 0, 5001, 2, 5002, 4, 5003, 6, 5004, 8, 5005], ary.sample(11, random: gen0))
ary.sample(11, random: gen1) # implementation detail, may change in the future
assert_equal([], ary)
- end
- def test_sample_random_generator_half
half = Object.new
def half.to_int
5000
@@ -3150,10 +3018,7 @@ class TestArray < Test::Unit::TestCase
end
ary = (0...10000).to_a
assert_equal(5000, ary.sample(random: gen_to_int))
- end
- def test_sample_random_invalid_generator
- ary = (0..10).to_a
assert_raise(NoMethodError) {
ary.sample(random: Object.new)
}
@@ -3415,7 +3280,7 @@ class TestArray < Test::Unit::TestCase
end
EOS
rescue Timeout::Error => e
- omit e.message
+ skip e.message
end
end
diff --git a/test/ruby/test_assignment.rb b/test/ruby/test_assignment.rb
index 3a8dafb7f0..41e8bffe82 100644
--- a/test/ruby/test_assignment.rb
+++ b/test/ruby/test_assignment.rb
@@ -139,104 +139,6 @@ class TestAssignment < Test::Unit::TestCase
order.clear
end
- def test_massign_const_order
- order = []
-
- test_mod_class = Class.new(Module) do
- define_method(:x1){order << :x1; self}
- define_method(:y1){order << :y1; self}
- define_method(:x2){order << :x2; self}
- define_method(:x3){order << :x3; self}
- define_method(:x4){order << :x4; self}
- define_method(:[]){|*args| order << [:[], *args]; self}
- define_method(:r1){order << :r1; :r1}
- define_method(:r2){order << :r2; :r2}
-
- define_method(:constant_values) do
- h = {}
- constants.each do |sym|
- h[sym] = const_get(sym)
- end
- h
- end
-
- define_singleton_method(:run) do |code|
- m = new
- m.instance_eval(code)
- ret = [order.dup, m.constant_values]
- order.clear
- ret
- end
- end
-
- ord, constants = test_mod_class.run(
- "x1.y1::A, x2[1, 2, 3]::B, self[4]::C = r1, 6, r2"
- )
- assert_equal([:x1, :y1, :x2, [:[], 1, 2, 3], [:[], 4], :r1, :r2], ord)
- assert_equal({:A=>:r1, :B=>6, :C=>:r2}, constants)
-
- ord, constants = test_mod_class.run(
- "x1.y1::A, *x2[1, 2, 3]::B, self[4]::C = r1, 6, 7, r2"
- )
- assert_equal([:x1, :y1, :x2, [:[], 1, 2, 3], [:[], 4], :r1, :r2], ord)
- assert_equal({:A=>:r1, :B=>[6, 7], :C=>:r2}, constants)
-
- ord, constants = test_mod_class.run(
- "x1.y1::A, *x2[1, 2, 3]::B, x3[4]::C = r1, 6, 7, r2"
- )
- assert_equal([:x1, :y1, :x2, [:[], 1, 2, 3], :x3, [:[], 4], :r1, :r2], ord)
- assert_equal({:A=>:r1, :B=>[6, 7], :C=>:r2}, constants)
-
-
- ord, constants = test_mod_class.run(
- "x1.y1::A, *x2[1, 2, 3]::B, x3[4]::C, x4::D = r1, 6, 7, r2, 8"
- )
- assert_equal([:x1, :y1, :x2, [:[], 1, 2, 3], :x3, [:[], 4], :x4, :r1, :r2], ord)
- assert_equal({:A=>:r1, :B=>[6, 7], :C=>:r2, :D=>8}, constants)
-
- ord, constants = test_mod_class.run(
- "(x1.y1::A, x2::B), _a = [r1, r2], 7"
- )
- assert_equal([:x1, :y1, :x2, :r1, :r2], ord)
- assert_equal({:A=>:r1, :B=>:r2}, constants)
-
- ord, constants = test_mod_class.run(
- "(x1.y1::A, x1::B), *x2[1, 2, 3]::C = [r1, 5], 6, 7, r2, 8"
- )
- assert_equal([:x1, :y1, :x1, :x2, [:[], 1, 2, 3], :r1, :r2], ord)
- assert_equal({:A=>:r1, :B=>5, :C=>[6, 7, :r2, 8]}, constants)
-
- ord, constants = test_mod_class.run(
- "*x2[1, 2, 3]::A, (x3[4]::B, x4::C) = 6, 7, [r2, 8]"
- )
- assert_equal([:x2, [:[], 1, 2, 3], :x3, [:[], 4], :x4, :r2], ord)
- assert_equal({:A=>[6, 7], :B=>:r2, :C=>8}, constants)
-
- ord, constants = test_mod_class.run(
- "(x1.y1::A, x1::B), *x2[1, 2, 3]::C, x3[4]::D, x4::E = [r1, 5], 6, 7, r2, 8"
- )
- assert_equal([:x1, :y1, :x1, :x2, [:[], 1, 2, 3], :x3, [:[], 4], :x4, :r1, :r2], ord)
- assert_equal({:A=>:r1, :B=>5, :C=>[6, 7], :D=>:r2, :E=>8}, constants)
-
- ord, constants = test_mod_class.run(
- "(x1.y1::A, x1::B), *x2[1, 2, 3]::C, (x3[4]::D, x4::E) = [r1, 5], 6, 7, [r2, 8]"
- )
- assert_equal([:x1, :y1, :x1, :x2, [:[], 1, 2, 3], :x3, [:[], 4], :x4, :r1, :r2], ord)
- assert_equal({:A=>:r1, :B=>5, :C=>[6, 7], :D=>:r2, :E=>8}, constants)
-
- ord, constants = test_mod_class.run(
- "((x1.y1::A, x1::B), _a), *x2[1, 2, 3]::C, ((x3[4]::D, x4::E), _b) = [[r1, 5], 10], 6, 7, [[r2, 8], 11]"
- )
- assert_equal([:x1, :y1, :x1, :x2, [:[], 1, 2, 3], :x3, [:[], 4], :x4, :r1, :r2], ord)
- assert_equal({:A=>:r1, :B=>5, :C=>[6, 7], :D=>:r2, :E=>8}, constants)
-
- ord, constants = test_mod_class.run(
- "((x1.y1::A, x1::B), _a), *x2[1, 2, 3]::C, ((*x3[4]::D, x4::E), _b) = [[r1, 5], 10], 6, 7, [[r2, 8], 11]"
- )
- assert_equal([:x1, :y1, :x1, :x2, [:[], 1, 2, 3], :x3, [:[], 4], :x4, :r1, :r2], ord)
- assert_equal({:A=>:r1, :B=>5, :C=>[6, 7], :D=>[:r2], :E=>8}, constants)
- end
-
def test_massign_splat
a,b,*c = *[]; assert_equal([nil,nil,[]], [a,b,c])
a,b,*c = *[1]; assert_equal([1,nil,[]], [a,b,c])
@@ -717,16 +619,6 @@ class TestAssignment < Test::Unit::TestCase
result = eval("if (a, b = MyObj.new); [a, b]; end", nil, __FILE__, __LINE__)
assert_equal [[1,2],[3,4]], result
end
-
- def test_const_assign_order
- assert_raise(RuntimeError) do
- eval('raise("recv")::C = raise(ArgumentError, "bar")')
- end
-
- assert_raise(RuntimeError) do
- eval('m = 1; m::C = raise("bar")')
- end
- end
end
require_relative 'sentence'
diff --git a/test/ruby/test_ast.rb b/test/ruby/test_ast.rb
index 234c7af219..cd7299f200 100644
--- a/test/ruby/test_ast.rb
+++ b/test/ruby/test_ast.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: false
require 'test/unit'
require 'tempfile'
-require 'pp'
class RubyVM
module AbstractSyntaxTree
@@ -132,34 +131,6 @@ class TestAst < Test::Unit::TestCase
end
end
- Dir.glob("test/**/*.rb", base: SRCDIR).each do |path|
- define_method("test_all_tokens:#{path}") do
- node = RubyVM::AbstractSyntaxTree.parse_file("#{SRCDIR}/#{path}", keep_tokens: true)
- tokens = node.all_tokens.sort_by { [_1.last[0], _1.last[1]] }
- tokens_bytes = tokens.map { _1[2]}.join.bytes
- source_bytes = File.read("#{SRCDIR}/#{path}").bytes
-
- assert_equal(source_bytes, tokens_bytes)
-
- (tokens.count - 1).times do |i|
- token_0 = tokens[i]
- token_1 = tokens[i + 1]
- end_pos = token_0.last[2..3]
- beg_pos = token_1.last[0..1]
-
- if end_pos[0] == beg_pos[0]
- # When both tokens are same line, column should be consecutives
- assert_equal(beg_pos[1], end_pos[1], "#{token_0}. #{token_1}")
- else
- # Line should be next
- assert_equal(beg_pos[0], end_pos[0] + 1, "#{token_0}. #{token_1}")
- # It should be on the beginning of the line
- assert_equal(0, beg_pos[1], "#{token_0}. #{token_1}")
- end
- end
- end
- end
-
private def parse(src)
EnvUtil.suppress_warning {
RubyVM::AbstractSyntaxTree.parse(src)
@@ -214,147 +185,6 @@ class TestAst < Test::Unit::TestCase
end
end
- def assert_parse(code, warning: '')
- node = assert_warning(warning) {RubyVM::AbstractSyntaxTree.parse(code)}
- assert_kind_of(RubyVM::AbstractSyntaxTree::Node, node, code)
- end
-
- def assert_invalid_parse(msg, code)
- assert_raise_with_message(SyntaxError, msg, code) do
- RubyVM::AbstractSyntaxTree.parse(code)
- end
- end
-
- def test_invalid_exit
- [
- "break",
- "break true",
- "next",
- "next true",
- "redo",
- ].each do |code, *args|
- msg = /Invalid #{code[/\A\w+/]}/
- assert_parse("while false; #{code}; end")
- assert_parse("until true; #{code}; end")
- assert_parse("begin #{code}; end while false")
- assert_parse("begin #{code}; end until true")
- assert_parse("->{#{code}}")
- assert_parse("->{class X; #{code}; end}")
- assert_invalid_parse(msg, "#{code}")
- assert_invalid_parse(msg, "def m; #{code}; end")
- assert_invalid_parse(msg, "begin; #{code}; end")
- assert_parse("END {#{code}}")
-
- assert_parse("!defined?(#{code})")
- assert_parse("def m; defined?(#{code}); end")
- assert_parse("!begin; defined?(#{code}); end")
-
- next if code.include?(" ")
- assert_parse("!defined? #{code}")
- assert_parse("def m; defined? #{code}; end")
- assert_parse("!begin; defined? #{code}; end")
- end
- end
-
- def test_invalid_retry
- msg = /Invalid retry/
- assert_invalid_parse(msg, "retry")
- assert_invalid_parse(msg, "def m; retry; end")
- assert_invalid_parse(msg, "begin retry; end")
- assert_parse("begin rescue; retry; end")
- assert_invalid_parse(msg, "begin rescue; else; retry; end")
- assert_invalid_parse(msg, "begin rescue; ensure; retry; end")
- assert_parse("nil rescue retry")
- assert_invalid_parse(msg, "END {retry}")
- assert_invalid_parse(msg, "begin rescue; END {retry}; end")
-
- assert_parse("!defined?(retry)")
- assert_parse("def m; defined?(retry); end")
- assert_parse("!begin defined?(retry); end")
- assert_parse("begin rescue; else; defined?(retry); end")
- assert_parse("begin rescue; ensure; defined?(retry); end")
- assert_parse("END {defined?(retry)}")
- assert_parse("begin rescue; END {defined?(retry)}; end")
- assert_parse("!defined? retry")
-
- assert_parse("def m; defined? retry; end")
- assert_parse("!begin defined? retry; end")
- assert_parse("begin rescue; else; defined? retry; end")
- assert_parse("begin rescue; ensure; defined? retry; end")
- assert_parse("END {defined? retry}")
- assert_parse("begin rescue; END {defined? retry}; end")
-
- assert_parse("#{<<-"begin;"}\n#{<<-'end;'}")
- begin;
- def foo
- begin
- yield
- rescue StandardError => e
- begin
- puts "hi"
- retry
- rescue
- retry unless e
- raise e
- else
- retry
- ensure
- retry
- end
- end
- end
- end;
- end
-
- def test_invalid_yield
- msg = /Invalid yield/
- assert_invalid_parse(msg, "yield")
- assert_invalid_parse(msg, "class C; yield; end")
- assert_invalid_parse(msg, "BEGIN {yield}")
- assert_invalid_parse(msg, "END {yield}")
- assert_invalid_parse(msg, "-> {yield}")
-
- assert_invalid_parse(msg, "yield true")
- assert_invalid_parse(msg, "class C; yield true; end")
- assert_invalid_parse(msg, "BEGIN {yield true}")
- assert_invalid_parse(msg, "END {yield true}")
- assert_invalid_parse(msg, "-> {yield true}")
-
- assert_parse("!defined?(yield)")
- assert_parse("class C; defined?(yield); end")
- assert_parse("BEGIN {defined?(yield)}")
- assert_parse("END {defined?(yield)}")
-
- assert_parse("!defined?(yield true)")
- assert_parse("class C; defined?(yield true); end")
- assert_parse("BEGIN {defined?(yield true)}")
- assert_parse("END {defined?(yield true)}")
-
- assert_parse("!defined? yield")
- assert_parse("class C; defined? yield; end")
- assert_parse("BEGIN {defined? yield}")
- assert_parse("END {defined? yield}")
- end
-
- def test_node_id_for_location
- exception = begin
- raise
- rescue => e
- e
- end
- loc = exception.backtrace_locations.first
- node_id = RubyVM::AbstractSyntaxTree.node_id_for_backtrace_location(loc)
- node = RubyVM::AbstractSyntaxTree.of(loc, keep_script_lines: true)
-
- assert_equal node.node_id, node_id
- end
-
- def test_node_id_for_backtrace_location_raises_argument_error
- bug19262 = '[ruby-core:111435]'
-
- assert_raise(TypeError, bug19262) { RubyVM::AbstractSyntaxTree.node_id_for_backtrace_location(1) }
- end
-
def test_of_proc_and_method
proc = Proc.new { 1 + 2 }
method = self.method(__method__)
@@ -425,8 +255,6 @@ class TestAst < Test::Unit::TestCase
end
def test_of_proc_and_method_under_eval_with_keep_script_lines
- pend if ENV['RUBY_ISEQ_DUMP_DEBUG'] # TODO
-
keep_script_lines_back = RubyVM.keep_script_lines
RubyVM.keep_script_lines = true
@@ -474,8 +302,6 @@ class TestAst < Test::Unit::TestCase
end
def test_of_backtrace_location_under_eval_with_keep_script_lines
- pend if ENV['RUBY_ISEQ_DUMP_DEBUG'] # TODO
-
keep_script_lines_back = RubyVM.keep_script_lines
RubyVM.keep_script_lines = true
@@ -617,30 +443,6 @@ class TestAst < Test::Unit::TestCase
assert_not_equal(type1, type2)
end
- def test_rest_arg
- rest_arg = lambda do |arg_str|
- node = RubyVM::AbstractSyntaxTree.parse("def a(#{arg_str}) end")
- node = node.children.last.children.last.children[1].children[-4]
- end
-
- assert_equal(nil, rest_arg.call(''))
- assert_equal(:r, rest_arg.call('*r'))
- assert_equal(:r, rest_arg.call('a, *r'))
- assert_equal(:*, rest_arg.call('*'))
- assert_equal(:*, rest_arg.call('a, *'))
- end
-
- def test_block_arg
- block_arg = lambda do |arg_str|
- node = RubyVM::AbstractSyntaxTree.parse("def a(#{arg_str}) end")
- node = node.children.last.children.last.children[1].children[-1]
- end
-
- assert_equal(nil, block_arg.call(''))
- assert_equal(:block, block_arg.call('&block'))
- assert_equal(:&, block_arg.call('&'))
- end
-
def test_keyword_rest
kwrest = lambda do |arg_str|
node = RubyVM::AbstractSyntaxTree.parse("def a(#{arg_str}) end")
@@ -649,21 +451,11 @@ class TestAst < Test::Unit::TestCase
end
assert_equal(nil, kwrest.call(''))
- assert_equal([:**], kwrest.call('**'))
+ assert_equal([nil], kwrest.call('**'))
assert_equal(false, kwrest.call('**nil'))
assert_equal([:a], kwrest.call('**a'))
end
- def test_argument_forwarding
- forwarding = lambda do |arg_str|
- node = RubyVM::AbstractSyntaxTree.parse("def a(#{arg_str}) end")
- node = node.children.last.children.last.children[1]
- node ? [node.children[-4], node.children[-2]&.children, node.children[-1]] : []
- end
-
- assert_equal([:*, nil, :&], forwarding.call('...'))
- end
-
def test_ranges_numbered_parameter
helper = Helper.new(__FILE__, src: "1.times {_1}")
helper.validate_range
@@ -746,45 +538,7 @@ dummy
assert_equal("def test_keep_script_lines_for_of\n", node_method.source.lines.first)
end
- def test_source_with_multibyte_characters
- ast = RubyVM::AbstractSyntaxTree.parse(%{a("\u00a7");b("\u00a9")}, keep_script_lines: true)
- a_fcall, b_fcall = ast.children[2].children
-
- assert_equal(%{a("\u00a7")}, a_fcall.source)
- assert_equal(%{b("\u00a9")}, b_fcall.source)
- end
-
- def test_keep_tokens_for_parse
- node = RubyVM::AbstractSyntaxTree.parse(<<~END, keep_tokens: true)
- 1.times do
- end
- __END__
- dummy
- END
-
- expected = [
- [:tINTEGER, "1"],
- [:".", "."],
- [:tIDENTIFIER, "times"],
- [:tSP, " "],
- [:keyword_do, "do"],
- [:tIGNORED_NL, "\n"],
- [:keyword_end, "end"],
- [:nl, "\n"],
- ]
- assert_equal(expected, node.all_tokens.map { [_2, _3]})
- end
-
- def test_keep_tokens_unexpected_backslash
- assert_raise_with_message(SyntaxError, /unexpected backslash/) do
- RubyVM::AbstractSyntaxTree.parse("\\", keep_tokens: true)
- end
- end
-
def test_encoding_with_keep_script_lines
- # Stop a warning "possibly useless use of a literal in void context"
- verbose_bak, $VERBOSE = $VERBOSE, nil
-
enc = Encoding::EUC_JP
code = "__ENCODING__".encode(enc)
@@ -795,440 +549,10 @@ dummy
node = RubyVM::AbstractSyntaxTree.parse(code, keep_script_lines: true)
assert_equal(enc, node.children[2].children[0])
-
- ensure
- $VERBOSE = verbose_bak
end
def test_e_option
assert_in_out_err(["-e", "def foo; end; pp RubyVM::AbstractSyntaxTree.of(method(:foo)).type"],
"", [":SCOPE"], [])
end
-
- def test_error_tolerant
- verbose_bak, $VERBOSE = $VERBOSE, false
- node = RubyVM::AbstractSyntaxTree.parse(<<~STR, error_tolerant: true)
- class A
- def m
- if;
- a = 10
- end
- end
- STR
- assert_nil($!)
-
- assert_equal(:SCOPE, node.type)
- ensure
- $VERBOSE = verbose_bak
- end
-
- def test_error_tolerant_end_is_short_for_method_define
- assert_error_tolerant(<<~STR, <<~EXP)
- def m
- m2
- STR
- (SCOPE@1:0-2:4
- tbl: []
- args: nil
- body:
- (DEFN@1:0-2:4
- mid: :m
- body:
- (SCOPE@1:0-2:4
- tbl: []
- args:
- (ARGS@1:5-1:5
- pre_num: 0
- pre_init: nil
- opt: nil
- first_post: nil
- post_num: 0
- post_init: nil
- rest: nil
- kw: nil
- kwrest: nil
- block: nil)
- body: (VCALL@2:2-2:4 :m2))))
- EXP
- end
-
- def test_error_tolerant_end_is_short_for_singleton_method_define
- assert_error_tolerant(<<~STR, <<~EXP)
- def obj.m
- m2
- STR
- (SCOPE@1:0-2:4
- tbl: []
- args: nil
- body:
- (DEFS@1:0-2:4 (VCALL@1:4-1:7 :obj) :m
- (SCOPE@1:0-2:4
- tbl: []
- args:
- (ARGS@1:9-1:9
- pre_num: 0
- pre_init: nil
- opt: nil
- first_post: nil
- post_num: 0
- post_init: nil
- rest: nil
- kw: nil
- kwrest: nil
- block: nil)
- body: (VCALL@2:2-2:4 :m2))))
- EXP
- end
-
- def test_error_tolerant_end_is_short_for_begin
- assert_error_tolerant(<<~STR, <<~EXP)
- begin
- a = 1
- STR
- (SCOPE@1:0-2:7 tbl: [:a] args: nil body: (LASGN@2:2-2:7 :a (LIT@2:6-2:7 1)))
- EXP
- end
-
- def test_error_tolerant_end_is_short_for_if
- assert_error_tolerant(<<~STR, <<~EXP)
- if cond
- a = 1
- STR
- (SCOPE@1:0-2:7
- tbl: [:a]
- args: nil
- body:
- (IF@1:0-2:7 (VCALL@1:3-1:7 :cond) (LASGN@2:2-2:7 :a (LIT@2:6-2:7 1)) nil))
- EXP
-
- assert_error_tolerant(<<~STR, <<~EXP)
- if cond
- a = 1
- else
- STR
- (SCOPE@1:0-3:4
- tbl: [:a]
- args: nil
- body:
- (IF@1:0-3:4 (VCALL@1:3-1:7 :cond) (LASGN@2:2-2:7 :a (LIT@2:6-2:7 1))
- (BEGIN@3:4-3:4 nil)))
- EXP
- end
-
- def test_error_tolerant_end_is_short_for_unless
- assert_error_tolerant(<<~STR, <<~EXP)
- unless cond
- a = 1
- STR
- (SCOPE@1:0-2:7
- tbl: [:a]
- args: nil
- body:
- (UNLESS@1:0-2:7 (VCALL@1:7-1:11 :cond) (LASGN@2:2-2:7 :a (LIT@2:6-2:7 1))
- nil))
- EXP
-
- assert_error_tolerant(<<~STR, <<~EXP)
- unless cond
- a = 1
- else
- STR
- (SCOPE@1:0-3:4
- tbl: [:a]
- args: nil
- body:
- (UNLESS@1:0-3:4 (VCALL@1:7-1:11 :cond) (LASGN@2:2-2:7 :a (LIT@2:6-2:7 1))
- (BEGIN@3:4-3:4 nil)))
- EXP
- end
-
- def test_error_tolerant_end_is_short_for_while
- assert_error_tolerant(<<~STR, <<~EXP)
- while true
- m
- STR
- (SCOPE@1:0-2:3
- tbl: []
- args: nil
- body: (WHILE@1:0-2:3 (TRUE@1:6-1:10) (VCALL@2:2-2:3 :m) true))
- EXP
- end
-
- def test_error_tolerant_end_is_short_for_until
- assert_error_tolerant(<<~STR, <<~EXP)
- until true
- m
- STR
- (SCOPE@1:0-2:3
- tbl: []
- args: nil
- body: (UNTIL@1:0-2:3 (TRUE@1:6-1:10) (VCALL@2:2-2:3 :m) true))
- EXP
- end
-
- def test_error_tolerant_end_is_short_for_case
- assert_error_tolerant(<<~STR, <<~EXP)
- case a
- when 1
- STR
- (SCOPE@1:0-2:6
- tbl: []
- args: nil
- body:
- (CASE@1:0-2:6 (VCALL@1:5-1:6 :a)
- (WHEN@2:0-2:6 (LIST@2:5-2:6 (LIT@2:5-2:6 1) nil) (BEGIN@2:6-2:6 nil)
- nil)))
- EXP
-
-
- assert_error_tolerant(<<~STR, <<~EXP)
- case
- when a == 1
- STR
- (SCOPE@1:0-2:11
- tbl: []
- args: nil
- body:
- (CASE2@1:0-2:11 nil
- (WHEN@2:0-2:11
- (LIST@2:5-2:11
- (OPCALL@2:5-2:11 (VCALL@2:5-2:6 :a) :==
- (LIST@2:10-2:11 (LIT@2:10-2:11 1) nil)) nil)
- (BEGIN@2:11-2:11 nil) nil)))
- EXP
-
-
- assert_error_tolerant(<<~STR, <<~EXP)
- case a
- in {a: String}
- STR
- (SCOPE@1:0-2:14
- tbl: []
- args: nil
- body:
- (CASE3@1:0-2:14 (VCALL@1:5-1:6 :a)
- (IN@2:0-2:14
- (HSHPTN@2:4-2:13
- const: nil
- kw:
- (HASH@2:4-2:13
- (LIST@2:4-2:13 (LIT@2:4-2:6 :a) (CONST@2:7-2:13 :String) nil))
- kwrest: nil) (BEGIN@2:14-2:14 nil) nil)))
- EXP
- end
-
- def test_error_tolerant_end_is_short_for_for
- assert_error_tolerant(<<~STR, <<~EXP)
- for i in ary
- m
- STR
- (SCOPE@1:0-2:3
- tbl: [:i]
- args: nil
- body:
- (FOR@1:0-2:3 (VCALL@1:9-1:12 :ary)
- (SCOPE@1:0-2:3
- tbl: [nil]
- args:
- (ARGS@1:4-1:5
- pre_num: 1
- pre_init: (LASGN@1:4-1:5 :i (DVAR@1:4-1:5 nil))
- opt: nil
- first_post: nil
- post_num: 0
- post_init: nil
- rest: nil
- kw: nil
- kwrest: nil
- block: nil)
- body: (VCALL@2:2-2:3 :m))))
- EXP
- end
-
- def test_error_tolerant_end_is_short_for_class
- assert_error_tolerant(<<~STR, <<~EXP)
- class C
- STR
- (SCOPE@1:0-1:7
- tbl: []
- args: nil
- body:
- (CLASS@1:0-1:7 (COLON2@1:6-1:7 nil :C) nil
- (SCOPE@1:0-1:7 tbl: [] args: nil body: (BEGIN@1:7-1:7 nil))))
- EXP
- end
-
- def test_error_tolerant_end_is_short_for_module
- assert_error_tolerant(<<~STR, <<~EXP)
- module M
- STR
- (SCOPE@1:0-1:8
- tbl: []
- args: nil
- body:
- (MODULE@1:0-1:8 (COLON2@1:7-1:8 nil :M)
- (SCOPE@1:0-1:8 tbl: [] args: nil body: (BEGIN@1:8-1:8 nil))))
- EXP
- end
-
- def test_error_tolerant_end_is_short_for_do
- assert_error_tolerant(<<~STR, <<~EXP)
- m do
- a
- STR
- (SCOPE@1:0-2:3
- tbl: []
- args: nil
- body:
- (ITER@1:0-2:3 (FCALL@1:0-1:1 :m nil)
- (SCOPE@1:2-2:3 tbl: [] args: nil body: (VCALL@2:2-2:3 :a))))
- EXP
- end
-
- def test_error_tolerant_end_is_short_for_do_block
- assert_error_tolerant(<<~STR, <<~EXP)
- m 1 do
- a
- STR
- (SCOPE@1:0-2:3
- tbl: []
- args: nil
- body:
- (ITER@1:0-2:3 (FCALL@1:0-1:3 :m (LIST@1:2-1:3 (LIT@1:2-1:3 1) nil))
- (SCOPE@1:4-2:3 tbl: [] args: nil body: (VCALL@2:2-2:3 :a))))
- EXP
- end
-
- def test_error_tolerant_end_is_short_for_do_LAMBDA
- assert_error_tolerant(<<~STR, <<~EXP)
- -> do
- a
- STR
- (SCOPE@1:0-2:3
- tbl: []
- args: nil
- body:
- (LAMBDA@1:0-2:3
- (SCOPE@1:2-2:3
- tbl: []
- args:
- (ARGS@1:2-1:2
- pre_num: 0
- pre_init: nil
- opt: nil
- first_post: nil
- post_num: 0
- post_init: nil
- rest: nil
- kw: nil
- kwrest: nil
- block: nil)
- body: (VCALL@2:2-2:3 :a))))
- EXP
- end
-
- def test_error_tolerant_treat_end_as_keyword_based_on_indent
- assert_error_tolerant(<<~STR, <<~EXP)
- module Z
- class Foo
- foo.
- end
-
- def bar
- end
- end
- STR
- (SCOPE@1:0-8:3
- tbl: []
- args: nil
- body:
- (MODULE@1:0-8:3 (COLON2@1:7-1:8 nil :Z)
- (SCOPE@1:0-8:3
- tbl: []
- args: nil
- body:
- (BLOCK@1:8-7:5 (BEGIN@1:8-1:8 nil)
- (CLASS@2:2-4:5 (COLON2@2:8-2:11 nil :Foo) nil
- (SCOPE@2:2-4:5
- tbl: []
- args: nil
- body: (BLOCK@2:11-4:5 (BEGIN@2:11-2:11 nil) (ERROR@3:4-4:5))))
- (DEFN@6:2-7:5
- mid: :bar
- body:
- (SCOPE@6:2-7:5
- tbl: []
- args:
- (ARGS@6:9-6:9
- pre_num: 0
- pre_init: nil
- opt: nil
- first_post: nil
- post_num: 0
- post_init: nil
- rest: nil
- kw: nil
- kwrest: nil
- block: nil)
- body: nil))))))
- EXP
- end
-
- def test_error_tolerant_expr_value_can_be_error
- assert_error_tolerant(<<~STR, <<~EXP)
- def m
- if
- end
- STR
- (SCOPE@1:0-3:3
- tbl: []
- args: nil
- body:
- (DEFN@1:0-3:3
- mid: :m
- body:
- (SCOPE@1:0-3:3
- tbl: []
- args:
- (ARGS@1:5-1:5
- pre_num: 0
- pre_init: nil
- opt: nil
- first_post: nil
- post_num: 0
- post_init: nil
- rest: nil
- kw: nil
- kwrest: nil
- block: nil)
- body: (IF@2:2-3:3 (ERROR@3:0-3:3) nil nil))))
- EXP
- end
-
- def test_error_tolerant_unexpected_backslash
- node = assert_error_tolerant("\\", <<~EXP, keep_tokens: true)
- (SCOPE@1:0-1:1 tbl: [] args: nil body: (ERROR@1:0-1:1))
- EXP
- assert_equal([[0, :backslash, "\\", [1, 0, 1, 1]]], node.children.last.tokens)
- end
-
- def test_with_bom
- assert_error_tolerant("\u{feff}nil", <<~EXP)
- (SCOPE@1:0-1:3 tbl: [] args: nil body: (NIL@1:0-1:3))
- EXP
- end
-
- def assert_error_tolerant(src, expected, keep_tokens: false)
- begin
- verbose_bak, $VERBOSE = $VERBOSE, false
- node = RubyVM::AbstractSyntaxTree.parse(src, error_tolerant: true, keep_tokens: keep_tokens)
- ensure
- $VERBOSE = verbose_bak
- end
- assert_nil($!)
- str = ""
- PP.pp(node, str, 80)
- assert_equal(expected, str)
- node
- end
end
diff --git a/test/ruby/test_autoload.rb b/test/ruby/test_autoload.rb
index 1eb3551e57..7010645317 100644
--- a/test/ruby/test_autoload.rb
+++ b/test/ruby/test_autoload.rb
@@ -168,7 +168,6 @@ p Foo::Bar
end
def test_nameerror_when_autoload_did_not_define_the_constant
- verbose_bak, $VERBOSE = $VERBOSE, nil
Tempfile.create(['autoload', '.rb']) {|file|
file.puts ''
file.close
@@ -181,8 +180,6 @@ p Foo::Bar
remove_autoload_constant
end
}
- ensure
- $VERBOSE = verbose_bak
end
def test_override_autoload
@@ -274,11 +271,6 @@ p Foo::Bar
end
def test_bug_13526
- # Skip this on macOS 10.13 because of the following error:
- # http://rubyci.s3.amazonaws.com/osx1013/ruby-master/log/20231011T014505Z.fail.html.gz
- require "rbconfig"
- omit if RbConfig::CONFIG["target_os"] == "darwin17"
-
script = File.join(__dir__, 'bug-13526.rb')
assert_ruby_status([script], '', '[ruby-core:81016] [Bug #13526]')
end
@@ -469,23 +461,6 @@ p Foo::Bar
end
end
- def test_source_location_after_require
- bug = "Bug18624"
- Dir.mktmpdir('autoload') do |tmpdir|
- path = "#{tmpdir}/test-#{bug}.rb"
- File.write(path, "C::#{bug} = __FILE__\n")
- assert_separately(%W[-I #{tmpdir}], "#{<<-"begin;"}\n#{<<-"end;"}")
- begin;
- class C; end
- C.autoload(:Bug18624, #{path.dump})
- require #{path.dump}
- assert_equal [#{path.dump}, 1], C.const_source_location(#{bug.dump})
- assert_equal #{path.dump}, C.const_get(#{bug.dump})
- assert_equal [#{path.dump}, 1], C.const_source_location(#{bug.dump})
- end;
- end
- end
-
def test_no_memory_leak
assert_no_memory_leak([], '', "#{<<~"begin;"}\n#{<<~'end;'}", 'many autoloads', timeout: 60)
begin;
@@ -505,7 +480,6 @@ p Foo::Bar
File.write(autoload_path, '')
assert_separately(%W[-I #{tmpdir}], <<-RUBY)
- $VERBOSE = nil
path = #{File.realpath(autoload_path).inspect}
autoload :X, path
assert_equal(path, Object.autoload?(:X))
@@ -535,69 +509,4 @@ p Foo::Bar
::Object.class_eval {remove_const(:AutoloadTest)} if defined? Object::AutoloadTest
TestAutoload.class_eval {remove_const(:AutoloadTest)} if defined? TestAutoload::AutoloadTest
end
-
- def test_autoload_module_gc
- Dir.mktmpdir('autoload') do |tmpdir|
- autoload_path = File.join(tmpdir, "autoload_module_gc.rb")
- File.write(autoload_path, "X = 1; Y = 2;")
-
- x = Module.new
- x.autoload :X, "./feature.rb"
-
- 1000.times do
- y = Module.new
- y.autoload :Y, "./feature.rb"
- end
-
- x = y = nil
-
- # Ensure the internal data structures are cleaned up correctly / don't crash:
- GC.start
- end
- end
-
- def test_autoload_parallel_race
- Dir.mktmpdir('autoload') do |tmpdir|
- autoload_path = File.join(tmpdir, "autoload_parallel_race.rb")
- File.write(autoload_path, 'module Foo; end; module Bar; end')
-
- assert_separately([], <<-RUBY, timeout: 100)
- autoload_path = #{File.realpath(autoload_path).inspect}
-
- # This should work with no errors or failures.
- 1000.times do
- autoload :Foo, autoload_path
- autoload :Bar, autoload_path
-
- t1 = Thread.new {Foo}
- t2 = Thread.new {Bar}
-
- t1.join
- GC.start # force GC.
- t2.join
-
- Object.send(:remove_const, :Foo)
- Object.send(:remove_const, :Bar)
-
- $LOADED_FEATURES.delete(autoload_path)
- end
- RUBY
- end
- end
-
- def test_autoload_parent_namespace
- Dir.mktmpdir('autoload') do |tmpdir|
- autoload_path = File.join(tmpdir, "some_const.rb")
- File.write(autoload_path, 'class SomeConst; end')
-
- assert_separately(%W[-I #{tmpdir}], <<-RUBY)
- module SomeNamespace
- autoload :SomeConst, #{File.realpath(autoload_path).inspect}
- assert_warning(%r{/some_const\.rb to define SomeNamespace::SomeConst but it didn't}) do
- assert_not_nil SomeConst
- end
- end
- RUBY
- end
- end
end
diff --git a/test/ruby/test_backtrace.rb b/test/ruby/test_backtrace.rb
index d35dead95b..aa79db24cb 100644
--- a/test/ruby/test_backtrace.rb
+++ b/test/ruby/test_backtrace.rb
@@ -154,35 +154,6 @@ class TestBacktrace < Test::Unit::TestCase
assert_equal caller(0), caller(0, nil)
end
- def test_each_backtrace_location
- i = 0
- cl = caller_locations(1, 1)[0]; ecl = Thread.each_caller_location{|x| i+=1; break x if i == 1}
- assert_equal(cl.to_s, ecl.to_s)
- assert_kind_of(Thread::Backtrace::Location, ecl)
-
- i = 0
- ary = []
- cllr = caller_locations(1, 2); last = Thread.each_caller_location{|x| ary << x; i+=1; break x if i == 2}
- assert_equal(cllr.map(&:to_s), ary.map(&:to_s))
- assert_kind_of(Thread::Backtrace::Location, last)
-
- i = 0
- ary = []
- ->{->{
- cllr = caller_locations(1, 2); last = Thread.each_caller_location{|x| ary << x; i+=1; break x if i == 2}
- }.()}.()
- assert_equal(cllr.map(&:to_s), ary.map(&:to_s))
- assert_kind_of(Thread::Backtrace::Location, last)
-
- cllr = caller_locations(1, 2); ary = Thread.to_enum(:each_caller_location).to_a[2..3]
- assert_equal(cllr.map(&:to_s), ary.map(&:to_s))
-
- ecl = Thread.to_enum(:each_caller_location)
- assert_raise(StopIteration) {
- ecl.next
- }
- end
-
def test_caller_locations_first_label
def self.label
caller_locations.first.label
@@ -215,15 +186,15 @@ class TestBacktrace < Test::Unit::TestCase
@res = caller_locations(2, 1).inspect
end
@line = __LINE__ + 1
- [1].map.map { [1].map.map { foo } }
- assert_equal("[\"#{__FILE__}:#{@line}:in `map'\"]", @res)
+ 1.times.map { 1.times.map { foo } }
+ assert_equal("[\"#{__FILE__}:#{@line}:in `times'\"]", @res)
end
def test_caller_location_path_cfunc_iseq_no_pc
def self.foo
@res = caller_locations(2, 1)[0].path
end
- [1].map.map { [1].map.map { foo } }
+ 1.times.map { 1.times.map { foo } }
assert_equal(__FILE__, @res)
end
diff --git a/test/ruby/test_beginendblock.rb b/test/ruby/test_beginendblock.rb
index 301a746f4a..eb8394864f 100644
--- a/test/ruby/test_beginendblock.rb
+++ b/test/ruby/test_beginendblock.rb
@@ -14,11 +14,6 @@ class TestBeginEndBlock < Test::Unit::TestCase
assert_in_out_err(["-p", "-eBEGIN{p :begin}", "-eEND{p :end}"], "foo\nbar\n", %w(:begin foo bar :end))
end
- def test_endblock_variable
- assert_in_out_err(["-n", "-ea = :ok", "-eEND{p a}"], "foo\n", %w(:ok))
- assert_in_out_err(["-p", "-ea = :ok", "-eEND{p a}"], "foo\n", %w(foo :ok))
- end
-
def test_begininmethod
assert_raise_with_message(SyntaxError, /BEGIN is permitted only at toplevel/) do
eval("def foo; BEGIN {}; end")
@@ -45,9 +40,9 @@ class TestBeginEndBlock < Test::Unit::TestCase
end
def test_endblockwarn_in_eval
- assert_in_out_err([], "#{<<~"begin;"}\n#{<<~'end;'}", [], ['test.rb:1: warning: END in method; use at_exit'])
+ assert_in_out_err([], "#{<<~"begin;"}\n#{<<~'end;'}", [], ['(eval):2: warning: END in method; use at_exit'])
begin;
- eval <<-EOE, nil, "test.rb", 0
+ eval <<-EOE
def end2
END {}
end
diff --git a/test/ruby/test_bignum.rb b/test/ruby/test_bignum.rb
index 065a944853..3ffe7114b5 100644
--- a/test/ruby/test_bignum.rb
+++ b/test/ruby/test_bignum.rb
@@ -203,15 +203,6 @@ class TestBignum < Test::Unit::TestCase
assert_equal(00_02, '00_02'.to_i)
end
- def test_very_big_str_to_inum
- assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- digits = [["3", 700], ["0", 2700], ["1", 1], ["0", 26599]]
- num = digits.inject("") {|s,(c,n)|s << c*n}.to_i
- assert_equal digits.sum {|c,n|n}, num.to_s.size
- end;
- end
-
def test_to_s2
assert_raise(ArgumentError) { T31P.to_s(37) }
assert_equal("9" * 32768, (10**32768-1).to_s)
@@ -653,7 +644,7 @@ class TestBignum < Test::Unit::TestCase
thread.raise
thread.join
time = Time.now - time
- omit "too fast cpu" if end_flag
+ skip "too fast cpu" if end_flag
assert_operator(time, :<, 10)
end
@@ -684,7 +675,7 @@ class TestBignum < Test::Unit::TestCase
return
end
end
- omit "cannot create suitable test case"
+ skip "cannot create suitable test case"
ensure
Signal.trap(:INT, oldtrap) if oldtrap
end
diff --git a/test/ruby/test_call.rb b/test/ruby/test_call.rb
index 09146efa41..67b3a936d4 100644
--- a/test/ruby/test_call.rb
+++ b/test/ruby/test_call.rb
@@ -1,6 +1,5 @@
# frozen_string_literal: false
require 'test/unit'
-require '-test-/iter'
class TestCall < Test::Unit::TestCase
def aaa(a, b=100, *rest)
@@ -48,19 +47,12 @@ class TestCall < Test::Unit::TestCase
assert_equal(5, o.y)
o&.z ||= 6
assert_equal(6, o.z)
- o&.z &&= 7
- assert_equal(7, o.z)
o = nil
assert_nil(o&.x)
assert_nothing_raised(NoMethodError) {o&.x = raise}
- assert_nothing_raised(NoMethodError) {o&.x = raise; nil}
assert_nothing_raised(NoMethodError) {o&.x *= raise}
assert_nothing_raised(NoMethodError) {o&.x *= raise; nil}
- assert_nothing_raised(NoMethodError) {o&.x ||= raise}
- assert_nothing_raised(NoMethodError) {o&.x ||= raise; nil}
- assert_nothing_raised(NoMethodError) {o&.x &&= raise}
- assert_nothing_raised(NoMethodError) {o&.x &&= raise; nil}
end
def test_safe_call_evaluate_arguments_only_method_call_is_made
@@ -100,207 +92,6 @@ class TestCall < Test::Unit::TestCase
}
end
- def test_frozen_splat_and_keywords
- a = [1, 2].freeze
- def self.f(*a); a end
- assert_equal([1, 2, {kw: 3}], f(*a, kw: 3))
- end
-
- def test_call_bmethod_proc
- pr = proc{|sym| sym}
- define_singleton_method(:a, &pr)
- ary = [10]
- assert_equal(10, a(*ary))
- end
-
- def test_call_bmethod_proc_restarg
- pr = proc{|*sym| sym}
- define_singleton_method(:a, &pr)
- ary = [10]
- assert_equal([10], a(*ary))
- assert_equal([10], a(10))
- end
-
- def test_call_op_asgn_keywords
- h = Class.new do
- attr_reader :get, :set
- def v; yield; [*@get, *@set] end
- def [](*a, **b, &c) @get = [a, b, c]; @set = []; 3 end
- def []=(*a, **b, &c) @set = [a, b, c] end
- end.new
-
- a = []
- kw = {}
- b = lambda{}
-
- # +=, without block, non-popped
- assert_equal([[], {}, nil, [4], {}, nil], h.v{h[**kw] += 1})
- assert_equal([[0], {}, nil, [0, 4], {}, nil], h.v{h[0, **kw] += 1})
- assert_equal([[0], {}, nil, [0, 4], {}, nil], h.v{h[0, *a, **kw] += 1})
- assert_equal([[], {kw: 5}, nil, [4], {kw: 5}, nil], h.v{h[kw: 5] += 1})
- assert_equal([[], {kw: 5, a: 2}, nil, [4], {kw: 5, a: 2}, nil], h.v{h[kw: 5, a: 2] += 1})
- assert_equal([[], {kw: 5, a: 2}, nil, [4], {kw: 5, a: 2}, nil], h.v{h[kw: 5, a: 2] += 1})
- assert_equal([[0], {kw: 5, a: 2}, nil, [0, 4], {kw: 5, a: 2}, nil], h.v{h[0, kw: 5, a: 2] += 1})
- assert_equal([[0], {kw: 5, a: 2, nil: 3}, nil, [0, 4], {kw: 5, a: 2, nil: 3}, nil], h.v{h[0, *a, kw: 5, a: 2, nil: 3] += 1})
-
- # +=, with block, non-popped
- assert_equal([[], {}, b, [4], {}, b], h.v{h[**kw, &b] += 1})
- assert_equal([[0], {}, b, [0, 4], {}, b], h.v{h[0, **kw, &b] += 1})
- assert_equal([[0], {}, b, [0, 4], {}, b], h.v{h[0, *a, **kw, &b] += 1})
- assert_equal([[], {kw: 5}, b, [4], {kw: 5}, b], h.v{h[kw: 5, &b] += 1})
- assert_equal([[], {kw: 5, a: 2}, b, [4], {kw: 5, a: 2}, b], h.v{h[kw: 5, a: 2, &b] += 1})
- assert_equal([[], {kw: 5, a: 2}, b, [4], {kw: 5, a: 2}, b], h.v{h[kw: 5, a: 2, &b] += 1})
- assert_equal([[0], {kw: 5, a: 2}, b, [0, 4], {kw: 5, a: 2}, b], h.v{h[0, kw: 5, a: 2, &b] += 1})
- assert_equal([[0], {kw: 5, a: 2, b: 3}, b, [0, 4], {kw: 5, a: 2, b: 3}, b], h.v{h[0, *a, kw: 5, a: 2, b: 3, &b] += 1})
-
- # +=, without block, popped
- assert_equal([[], {}, nil, [4], {}, nil], h.v{h[**kw] += 1; nil})
- assert_equal([[0], {}, nil, [0, 4], {}, nil], h.v{h[0, **kw] += 1; nil})
- assert_equal([[0], {}, nil, [0, 4], {}, nil], h.v{h[0, *a, **kw] += 1; nil})
- assert_equal([[], {kw: 5}, nil, [4], {kw: 5}, nil], h.v{h[kw: 5] += 1; nil})
- assert_equal([[], {kw: 5, a: 2}, nil, [4], {kw: 5, a: 2}, nil], h.v{h[kw: 5, a: 2] += 1; nil})
- assert_equal([[], {kw: 5, a: 2}, nil, [4], {kw: 5, a: 2}, nil], h.v{h[kw: 5, a: 2] += 1; nil})
- assert_equal([[0], {kw: 5, a: 2}, nil, [0, 4], {kw: 5, a: 2}, nil], h.v{h[0, kw: 5, a: 2] += 1; nil})
- assert_equal([[0], {kw: 5, a: 2, nil: 3}, nil, [0, 4], {kw: 5, a: 2, nil: 3}, nil], h.v{h[0, *a, kw: 5, a: 2, nil: 3] += 1; nil})
-
- # +=, with block, popped
- assert_equal([[], {}, b, [4], {}, b], h.v{h[**kw, &b] += 1; nil})
- assert_equal([[0], {}, b, [0, 4], {}, b], h.v{h[0, **kw, &b] += 1; nil})
- assert_equal([[0], {}, b, [0, 4], {}, b], h.v{h[0, *a, **kw, &b] += 1; nil})
- assert_equal([[], {kw: 5}, b, [4], {kw: 5}, b], h.v{h[kw: 5, &b] += 1; nil})
- assert_equal([[], {kw: 5, a: 2}, b, [4], {kw: 5, a: 2}, b], h.v{h[kw: 5, a: 2, &b] += 1; nil})
- assert_equal([[], {kw: 5, a: 2}, b, [4], {kw: 5, a: 2}, b], h.v{h[kw: 5, a: 2, &b] += 1; nil})
- assert_equal([[0], {kw: 5, a: 2}, b, [0, 4], {kw: 5, a: 2}, b], h.v{h[0, kw: 5, a: 2, &b] += 1; nil})
- assert_equal([[0], {kw: 5, a: 2, b: 3}, b, [0, 4], {kw: 5, a: 2, b: 3}, b], h.v{h[0, *a, kw: 5, a: 2, b: 3, &b] += 1; nil})
-
- # &&=, without block, non-popped
- assert_equal([[], {}, nil, [1], {}, nil], h.v{h[**kw] &&= 1})
- assert_equal([[0], {}, nil, [0, 1], {}, nil], h.v{h[0, **kw] &&= 1})
- assert_equal([[0], {}, nil, [0, 1], {}, nil], h.v{h[0, *a, **kw] &&= 1})
- assert_equal([[], {kw: 5}, nil, [1], {kw: 5}, nil], h.v{h[kw: 5] &&= 1})
- assert_equal([[], {kw: 5, a: 2}, nil, [1], {kw: 5, a: 2}, nil], h.v{h[kw: 5, a: 2] &&= 1})
- assert_equal([[], {kw: 5, a: 2}, nil, [1], {kw: 5, a: 2}, nil], h.v{h[kw: 5, a: 2] &&= 1})
- assert_equal([[0], {kw: 5, a: 2}, nil, [0, 1], {kw: 5, a: 2}, nil], h.v{h[0, kw: 5, a: 2] &&= 1})
- assert_equal([[0], {kw: 5, a: 2, nil: 3}, nil, [0, 1], {kw: 5, a: 2, nil: 3}, nil], h.v{h[0, *a, kw: 5, a: 2, nil: 3] &&= 1})
-
- # &&=, with block, non-popped
- assert_equal([[], {}, b, [1], {}, b], h.v{h[**kw, &b] &&= 1})
- assert_equal([[0], {}, b, [0, 1], {}, b], h.v{h[0, **kw, &b] &&= 1})
- assert_equal([[0], {}, b, [0, 1], {}, b], h.v{h[0, *a, **kw, &b] &&= 1})
- assert_equal([[], {kw: 5}, b, [1], {kw: 5}, b], h.v{h[kw: 5, &b] &&= 1})
- assert_equal([[], {kw: 5, a: 2}, b, [1], {kw: 5, a: 2}, b], h.v{h[kw: 5, a: 2, &b] &&= 1})
- assert_equal([[], {kw: 5, a: 2}, b, [1], {kw: 5, a: 2}, b], h.v{h[kw: 5, a: 2, &b] &&= 1})
- assert_equal([[0], {kw: 5, a: 2}, b, [0, 1], {kw: 5, a: 2}, b], h.v{h[0, kw: 5, a: 2, &b] &&= 1})
- assert_equal([[0], {kw: 5, a: 2, b: 3}, b, [0, 1], {kw: 5, a: 2, b: 3}, b], h.v{h[0, *a, kw: 5, a: 2, b: 3, &b] &&= 1})
-
- # &&=, without block, popped
- assert_equal([[], {}, nil, [1], {}, nil], h.v{h[**kw] &&= 1; nil})
- assert_equal([[0], {}, nil, [0, 1], {}, nil], h.v{h[0, **kw] &&= 1; nil})
- assert_equal([[0], {}, nil, [0, 1], {}, nil], h.v{h[0, *a, **kw] &&= 1; nil})
- assert_equal([[], {kw: 5}, nil, [1], {kw: 5}, nil], h.v{h[kw: 5] &&= 1; nil})
- assert_equal([[], {kw: 5, a: 2}, nil, [1], {kw: 5, a: 2}, nil], h.v{h[kw: 5, a: 2] &&= 1; nil})
- assert_equal([[], {kw: 5, a: 2}, nil, [1], {kw: 5, a: 2}, nil], h.v{h[kw: 5, a: 2] &&= 1; nil})
- assert_equal([[0], {kw: 5, a: 2}, nil, [0, 1], {kw: 5, a: 2}, nil], h.v{h[0, kw: 5, a: 2] &&= 1; nil})
- assert_equal([[0], {kw: 5, a: 2, nil: 3}, nil, [0, 1], {kw: 5, a: 2, nil: 3}, nil], h.v{h[0, *a, kw: 5, a: 2, nil: 3] &&= 1; nil})
-
- # &&=, with block, popped
- assert_equal([[], {}, b, [1], {}, b], h.v{h[**kw, &b] &&= 1; nil})
- assert_equal([[0], {}, b, [0, 1], {}, b], h.v{h[0, **kw, &b] &&= 1; nil})
- assert_equal([[0], {}, b, [0, 1], {}, b], h.v{h[0, *a, **kw, &b] &&= 1; nil})
- assert_equal([[], {kw: 5}, b, [1], {kw: 5}, b], h.v{h[kw: 5, &b] &&= 1; nil})
- assert_equal([[], {kw: 5, a: 2}, b, [1], {kw: 5, a: 2}, b], h.v{h[kw: 5, a: 2, &b] &&= 1; nil})
- assert_equal([[], {kw: 5, a: 2}, b, [1], {kw: 5, a: 2}, b], h.v{h[kw: 5, a: 2, &b] &&= 1; nil})
- assert_equal([[0], {kw: 5, a: 2}, b, [0, 1], {kw: 5, a: 2}, b], h.v{h[0, kw: 5, a: 2, &b] &&= 1; nil})
- assert_equal([[0], {kw: 5, a: 2, b: 3}, b, [0, 1], {kw: 5, a: 2, b: 3}, b], h.v{h[0, *a, kw: 5, a: 2, b: 3, &b] &&= 1; nil})
-
- # ||=, without block, non-popped
- assert_equal([[], {}, nil], h.v{h[**kw] ||= 1})
- assert_equal([[0], {}, nil], h.v{h[0, **kw] ||= 1})
- assert_equal([[0], {}, nil], h.v{h[0, *a, **kw] ||= 1})
- assert_equal([[], {kw: 5}, nil], h.v{h[kw: 5] ||= 1})
- assert_equal([[], {kw: 5, a: 2}, nil], h.v{h[kw: 5, a: 2] ||= 1})
- assert_equal([[], {kw: 5, a: 2}, nil], h.v{h[kw: 5, a: 2] ||= 1})
- assert_equal([[0], {kw: 5, a: 2}, nil], h.v{h[0, kw: 5, a: 2] ||= 1})
- assert_equal([[0], {kw: 5, a: 2, nil: 3}, nil], h.v{h[0, *a, kw: 5, a: 2, nil: 3] ||= 1})
-
- # ||=, with block, non-popped
- assert_equal([[], {}, b], h.v{h[**kw, &b] ||= 1})
- assert_equal([[0], {}, b], h.v{h[0, **kw, &b] ||= 1})
- assert_equal([[0], {}, b], h.v{h[0, *a, **kw, &b] ||= 1})
- assert_equal([[], {kw: 5}, b], h.v{h[kw: 5, &b] ||= 1})
- assert_equal([[], {kw: 5, a: 2}, b], h.v{h[kw: 5, a: 2, &b] ||= 1})
- assert_equal([[], {kw: 5, a: 2}, b], h.v{h[kw: 5, a: 2, &b] ||= 1})
- assert_equal([[0], {kw: 5, a: 2}, b], h.v{h[0, kw: 5, a: 2, &b] ||= 1})
- assert_equal([[0], {kw: 5, a: 2, b: 3}, b], h.v{h[0, *a, kw: 5, a: 2, b: 3, &b] ||= 1})
-
- # ||=, without block, popped
- assert_equal([[], {}, nil], h.v{h[**kw] ||= 1; nil})
- assert_equal([[0], {}, nil], h.v{h[0, **kw] ||= 1; nil})
- assert_equal([[0], {}, nil], h.v{h[0, *a, **kw] ||= 1; nil})
- assert_equal([[], {kw: 5}, nil], h.v{h[kw: 5] ||= 1; nil})
- assert_equal([[], {kw: 5, a: 2}, nil], h.v{h[kw: 5, a: 2] ||= 1; nil})
- assert_equal([[], {kw: 5, a: 2}, nil], h.v{h[kw: 5, a: 2] ||= 1; nil})
- assert_equal([[0], {kw: 5, a: 2}, nil], h.v{h[0, kw: 5, a: 2] ||= 1; nil})
- assert_equal([[0], {kw: 5, a: 2, nil: 3}, nil], h.v{h[0, *a, kw: 5, a: 2, nil: 3] ||= 1; nil})
-
- # ||=, with block, popped
- assert_equal([[], {}, b], h.v{h[**kw, &b] ||= 1; nil})
- assert_equal([[0], {}, b], h.v{h[0, **kw, &b] ||= 1; nil})
- assert_equal([[0], {}, b], h.v{h[0, *a, **kw, &b] ||= 1; nil})
- assert_equal([[], {kw: 5}, b], h.v{h[kw: 5, &b] ||= 1; nil})
- assert_equal([[], {kw: 5, a: 2}, b], h.v{h[kw: 5, a: 2, &b] ||= 1; nil})
- assert_equal([[], {kw: 5, a: 2}, b], h.v{h[kw: 5, a: 2, &b] ||= 1; nil})
- assert_equal([[0], {kw: 5, a: 2}, b], h.v{h[0, kw: 5, a: 2, &b] ||= 1; nil})
- assert_equal([[0], {kw: 5, a: 2, b: 3}, b], h.v{h[0, *a, kw: 5, a: 2, b: 3, &b] ||= 1; nil})
-
- end
-
- def test_kwsplat_block_order_op_asgn
- o = Object.new
- ary = []
- o.define_singleton_method(:to_a) {ary << :to_a; []}
- o.define_singleton_method(:to_hash) {ary << :to_hash; {}}
- o.define_singleton_method(:to_proc) {ary << :to_proc; lambda{}}
-
- def o.[](...) 2 end
- def o.[]=(...) end
-
- o[kw: 1] += 1
- assert_equal([], ary)
-
- o[**o] += 1
- assert_equal([:to_hash], ary)
-
- ary.clear
- o[**o, &o] += 1
- # to_proc called twice because no VM instruction for coercing to proc
- assert_equal([:to_hash, :to_proc, :to_proc], ary)
-
- ary.clear
- o[*o, **o, &o] += 1
- assert_equal([:to_a, :to_hash, :to_proc, :to_proc], ary)
- end
-
- def test_call_op_asgn_keywords_mutable
- h = Class.new do
- attr_reader :get, :set
- def v; yield; [*@get, *@set] end
- def [](*a, **b)
- @get = [a.dup, b.dup]
- a << :splat_modified
- b[:kw_splat_modified] = true
- @set = []
- 3
- end
- def []=(*a, **b) @set = [a, b] end
- end.new
-
- a = []
- kw = {}
-
- assert_equal([[2], {b: 5}, [2, 4], {b: 5}], h.v{h[*a, 2, b: 5, **kw] += 1})
- end
-
def test_call_splat_order
bug12860 = '[ruby-core:77701] [Bug# 12860]'
ary = [1, 2]
@@ -317,1014 +108,4 @@ class TestCall < Test::Unit::TestCase
ary = [1, 2, b]
assert_equal([0, 1, 2, b], aaa(0, *ary, &ary.pop), bug16504)
end
-
- def test_call_args_splat_with_nonhash_keyword_splat
- o = Object.new
- def o.to_hash; {a: 1} end
- def self.f(*a, **kw)
- kw
- end
- assert_equal Hash, f(*[], **o).class
- end
-
- def test_kwsplat_block_order
- o = Object.new
- ary = []
- o.define_singleton_method(:to_a) {ary << :to_a; []}
- o.define_singleton_method(:to_hash) {ary << :to_hash; {}}
- o.define_singleton_method(:to_proc) {ary << :to_proc; lambda{}}
-
- def self.t(...) end
-
- t(**o, &o)
- assert_equal([:to_hash, :to_proc], ary)
-
- ary.clear
- t(*o, **o, &o)
- assert_equal([:to_a, :to_hash, :to_proc], ary)
- end
-
- def test_kwsplat_block_order_super
- def self.t(splat)
- o = Object.new
- ary = []
- o.define_singleton_method(:to_a) {ary << :to_a; []}
- o.define_singleton_method(:to_hash) {ary << :to_hash; {}}
- o.define_singleton_method(:to_proc) {ary << :to_proc; lambda{}}
- if splat
- super(*o, **o, &o)
- else
- super(**o, &o)
- end
- ary
- end
- extend Module.new{def t(...) end}
-
- assert_equal([:to_hash, :to_proc], t(false))
- assert_equal([:to_a, :to_hash, :to_proc], t(true))
- end
-
- OVER_STACK_LEN = (ENV['RUBY_OVER_STACK_LEN'] || 150).to_i # Greater than VM_ARGC_STACK_MAX
- OVER_STACK_ARGV = OVER_STACK_LEN.times.to_a.freeze
-
- def test_call_cfunc_splat_large_array_bug_4040
- a = OVER_STACK_ARGV
-
- assert_equal(a, [].push(*a))
- assert_equal(a, [].push(a[0], *a[1..]))
- assert_equal(a, [].push(a[0], a[1], *a[2..]))
- assert_equal(a, [].push(*a[0..1], *a[2..]))
- assert_equal(a, [].push(*a[...-1], a[-1]))
- assert_equal(a, [].push(a[0], *a[1...-1], a[-1]))
- assert_equal(a, [].push(a[0], a[1], *a[2...-1], a[-1]))
- assert_equal(a, [].push(*a[0..1], *a[2...-1], a[-1]))
- assert_equal(a, [].push(*a[...-2], a[-2], a[-1]))
- assert_equal(a, [].push(a[0], *a[1...-2], a[-2], a[-1]))
- assert_equal(a, [].push(a[0], a[1], *a[2...-2], a[-2], a[-1]))
- assert_equal(a, [].push(*a[0..1], *a[2...-2], a[-2], a[-1]))
-
- kw = {x: 1}
- a_kw = a + [kw]
-
- assert_equal(a_kw, [].push(*a, **kw))
- assert_equal(a_kw, [].push(a[0], *a[1..], **kw))
- assert_equal(a_kw, [].push(a[0], a[1], *a[2..], **kw))
- assert_equal(a_kw, [].push(*a[0..1], *a[2..], **kw))
- assert_equal(a_kw, [].push(*a[...-1], a[-1], **kw))
- assert_equal(a_kw, [].push(a[0], *a[1...-1], a[-1], **kw))
- assert_equal(a_kw, [].push(a[0], a[1], *a[2...-1], a[-1], **kw))
- assert_equal(a_kw, [].push(*a[0..1], *a[2...-1], a[-1], **kw))
- assert_equal(a_kw, [].push(*a[...-2], a[-2], a[-1], **kw))
- assert_equal(a_kw, [].push(a[0], *a[1...-2], a[-2], a[-1], **kw))
- assert_equal(a_kw, [].push(a[0], a[1], *a[2...-2], a[-2], a[-1], **kw))
- assert_equal(a_kw, [].push(*a[0..1], *a[2...-2], a[-2], a[-1], **kw))
-
- assert_equal(a_kw, [].push(*a, x: 1))
- assert_equal(a_kw, [].push(a[0], *a[1..], x: 1))
- assert_equal(a_kw, [].push(a[0], a[1], *a[2..], x: 1))
- assert_equal(a_kw, [].push(*a[0..1], *a[2..], x: 1))
- assert_equal(a_kw, [].push(*a[...-1], a[-1], x: 1))
- assert_equal(a_kw, [].push(a[0], *a[1...-1], a[-1], x: 1))
- assert_equal(a_kw, [].push(a[0], a[1], *a[2...-1], a[-1], x: 1))
- assert_equal(a_kw, [].push(*a[0..1], *a[2...-1], a[-1], x: 1))
- assert_equal(a_kw, [].push(*a[...-2], a[-2], a[-1], x: 1))
- assert_equal(a_kw, [].push(a[0], *a[1...-2], a[-2], a[-1], x: 1))
- assert_equal(a_kw, [].push(a[0], a[1], *a[2...-2], a[-2], a[-1], x: 1))
- assert_equal(a_kw, [].push(*a[0..1], *a[2...-2], a[-2], a[-1], x: 1))
-
- a_kw[-1][:y] = 2
- kw = {y: 2}
-
- assert_equal(a_kw, [].push(*a, x: 1, **kw))
- assert_equal(a_kw, [].push(a[0], *a[1..], x: 1, **kw))
- assert_equal(a_kw, [].push(a[0], a[1], *a[2..], x: 1, **kw))
- assert_equal(a_kw, [].push(*a[0..1], *a[2..], x: 1, **kw))
- assert_equal(a_kw, [].push(*a[...-1], a[-1], x: 1, **kw))
- assert_equal(a_kw, [].push(a[0], *a[1...-1], a[-1], x: 1, **kw))
- assert_equal(a_kw, [].push(a[0], a[1], *a[2...-1], a[-1], x: 1, **kw))
- assert_equal(a_kw, [].push(*a[0..1], *a[2...-1], a[-1], x: 1, **kw))
- assert_equal(a_kw, [].push(*a[...-2], a[-2], a[-1], x: 1, **kw))
- assert_equal(a_kw, [].push(a[0], *a[1...-2], a[-2], a[-1], x: 1, **kw))
- assert_equal(a_kw, [].push(a[0], a[1], *a[2...-2], a[-2], a[-1], x: 1, **kw))
- assert_equal(a_kw, [].push(*a[0..1], *a[2...-2], a[-2], a[-1], x: 1, **kw))
-
- kw = {}
-
- assert_equal(a, [].push(*a, **kw))
- assert_equal(a, [].push(a[0], *a[1..], **kw))
- assert_equal(a, [].push(a[0], a[1], *a[2..], **kw))
- assert_equal(a, [].push(*a[0..1], *a[2..], **kw))
- assert_equal(a, [].push(*a[...-1], a[-1], **kw))
- assert_equal(a, [].push(a[0], *a[1...-1], a[-1], **kw))
- assert_equal(a, [].push(a[0], a[1], *a[2...-1], a[-1], **kw))
- assert_equal(a, [].push(*a[0..1], *a[2...-1], a[-1], **kw))
- assert_equal(a, [].push(*a[...-2], a[-2], a[-1], **kw))
- assert_equal(a, [].push(a[0], *a[1...-2], a[-2], a[-1], **kw))
- assert_equal(a, [].push(a[0], a[1], *a[2...-2], a[-2], a[-1], **kw))
- assert_equal(a, [].push(*a[0..1], *a[2...-2], a[-2], a[-1], **kw))
-
- a_kw = a + [Hash.ruby2_keywords_hash({})]
- assert_equal(a, [].push(*a_kw))
-
- # Single test with value that would cause SystemStackError.
- # Not all tests use such a large array to reduce testing time.
- assert_equal(1380888, [].push(*1380888.times.to_a).size)
- end
-
- def test_call_iseq_large_array_splat_fail
- def self.a; end
- def self.b(a=1); end
- def self.c(k: 1); end
- def self.d(**kw); end
- def self.e(k: 1, **kw); end
- def self.f(a=1, k: 1); end
- def self.g(a=1, **kw); end
- def self.h(a=1, k: 1, **kw); end
-
- (:a..:h).each do |meth|
- assert_raise_with_message(ArgumentError, /wrong number of arguments \(given #{OVER_STACK_LEN}, expected 0(\.\.[12])?\)/) do
- instance_eval("#{meth}(*OVER_STACK_ARGV)", __FILE__, __LINE__)
- end
- end
- end
-
- def test_call_iseq_large_array_splat_pass
- def self.a(*a); a.length end
- assert_equal OVER_STACK_LEN, a(*OVER_STACK_ARGV)
-
- def self.b(_, *a); a.length end
- assert_equal (OVER_STACK_LEN - 1), b(*OVER_STACK_ARGV)
-
- def self.c(_, *a, _); a.length end
- assert_equal (OVER_STACK_LEN - 2), c(*OVER_STACK_ARGV)
-
- def self.d(b=1, *a); a.length end
- assert_equal (OVER_STACK_LEN - 1), d(*OVER_STACK_ARGV)
-
- def self.e(b=1, *a, _); a.length end
- assert_equal (OVER_STACK_LEN - 2), e(*OVER_STACK_ARGV)
-
- def self.f(b, *a); a.length end
- assert_equal (OVER_STACK_LEN - 1), f(*OVER_STACK_ARGV)
-
- def self.g(*a, k: 1); a.length end
- assert_equal OVER_STACK_LEN, g(*OVER_STACK_ARGV)
-
- def self.h(*a, **kw); a.length end
- assert_equal OVER_STACK_LEN, h(*OVER_STACK_ARGV)
-
- def self.i(*a, k: 1, **kw); a.length end
- assert_equal OVER_STACK_LEN, i(*OVER_STACK_ARGV)
-
- def self.j(b=1, *a, k: 1); a.length end
- assert_equal (OVER_STACK_LEN - 1), j(*OVER_STACK_ARGV)
-
- def self.k(b=1, *a, **kw); a.length end
- assert_equal (OVER_STACK_LEN - 1), k(*OVER_STACK_ARGV)
-
- def self.l(b=1, *a, k: 1, **kw); a.length end
- assert_equal (OVER_STACK_LEN - 1), l(*OVER_STACK_ARGV)
-
- def self.m(b=1, *a, _, k: 1); a.length end
- assert_equal (OVER_STACK_LEN - 2), m(*OVER_STACK_ARGV)
-
- def self.n(b=1, *a, _, **kw); a.length end
- assert_equal (OVER_STACK_LEN - 2), n(*OVER_STACK_ARGV)
-
- def self.o(b=1, *a, _, k: 1, **kw); a.length end
- assert_equal (OVER_STACK_LEN - 2), o(*OVER_STACK_ARGV)
- end
-
- def test_call_iseq_large_array_splat_with_large_number_of_parameters
- args = OVER_STACK_ARGV.map{|i| "a#{i}"}.join(',')
- args1 = (OVER_STACK_LEN-1).times.map{|i| "a#{i}"}.join(',')
-
- singleton_class.class_eval("def a(#{args}); [#{args}] end")
- assert_equal OVER_STACK_ARGV, a(*OVER_STACK_ARGV)
-
- singleton_class.class_eval("def b(#{args}, b=0); [#{args}, b] end")
- assert_equal(OVER_STACK_ARGV + [0], b(*OVER_STACK_ARGV))
-
- singleton_class.class_eval("def c(#{args}, *b); [#{args}, b] end")
- assert_equal(OVER_STACK_ARGV + [[]], c(*OVER_STACK_ARGV))
-
- singleton_class.class_eval("def d(#{args1}, *b); [#{args1}, b] end")
- assert_equal(OVER_STACK_ARGV[0...-1] + [[OVER_STACK_ARGV.last]], d(*OVER_STACK_ARGV))
- end if OVER_STACK_LEN < 200
-
- def test_call_proc_large_array_splat_pass
- [
- proc{0} ,
- proc{|a=1|a},
- proc{|k: 1|0},
- proc{|**kw| 0},
- proc{|k: 1, **kw| 0},
- proc{|a=1, k: 1| a},
- proc{|a=1, **kw| a},
- proc{|a=1, k: 1, **kw| a},
- ].each do |l|
- assert_equal 0, l.call(*OVER_STACK_ARGV)
- end
-
- assert_equal OVER_STACK_LEN, proc{|*a| a.length}.(*OVER_STACK_ARGV)
- assert_equal (OVER_STACK_LEN - 1), proc{|_, *a| a.length}.(*OVER_STACK_ARGV)
- assert_equal (OVER_STACK_LEN - 2), proc{|_, *a, _| a.length}.(*OVER_STACK_ARGV)
- assert_equal (OVER_STACK_LEN - 1), proc{|b=1, *a| a.length}.(*OVER_STACK_ARGV)
- assert_equal (OVER_STACK_LEN - 2), proc{|b=1, *a, _| a.length}.(*OVER_STACK_ARGV)
- assert_equal (OVER_STACK_LEN - 1), proc{|b=1, *a| a.length}.(*OVER_STACK_ARGV)
- assert_equal OVER_STACK_LEN, proc{|*a, k: 1| a.length}.(*OVER_STACK_ARGV)
- assert_equal OVER_STACK_LEN, proc{|*a, **kw| a.length}.(*OVER_STACK_ARGV)
- assert_equal OVER_STACK_LEN, proc{|*a, k: 1, **kw| a.length}.(*OVER_STACK_ARGV)
- assert_equal (OVER_STACK_LEN - 1), proc{|b=1, *a, k: 1| a.length}.(*OVER_STACK_ARGV)
- assert_equal (OVER_STACK_LEN - 1), proc{|b=1, *a, **kw| a.length}.(*OVER_STACK_ARGV)
- assert_equal (OVER_STACK_LEN - 1), proc{|b=1, *a, k: 1, **kw| a.length}.(*OVER_STACK_ARGV)
- assert_equal (OVER_STACK_LEN - 2), proc{|b=1, *a, _, k: 1| a.length}.(*OVER_STACK_ARGV)
- assert_equal (OVER_STACK_LEN - 2), proc{|b=1, *a, _, **kw| a.length}.(*OVER_STACK_ARGV)
- assert_equal (OVER_STACK_LEN - 2), proc{|b=1, *a, _, k: 1, **kw| a.length}.(*OVER_STACK_ARGV)
- end
-
- def test_call_proc_large_array_splat_with_large_number_of_parameters
- args = OVER_STACK_ARGV.map{|i| "a#{i}"}.join(',')
- args1 = (OVER_STACK_LEN-1).times.map{|i| "a#{i}"}.join(',')
-
- l = instance_eval("proc{|#{args}| [#{args}]}")
- assert_equal OVER_STACK_ARGV, l.(*OVER_STACK_ARGV)
-
- l = instance_eval("proc{|#{args}, b| [#{args}, b]}")
- assert_equal(OVER_STACK_ARGV + [nil], l.(*OVER_STACK_ARGV))
-
- l = instance_eval("proc{|#{args1}| [#{args1}]}")
- assert_equal(OVER_STACK_ARGV[0...-1], l.(*OVER_STACK_ARGV))
-
- l = instance_eval("proc{|#{args}, *b| [#{args}, b]}")
- assert_equal(OVER_STACK_ARGV + [[]], l.(*OVER_STACK_ARGV))
-
- l = instance_eval("proc{|#{args1}, *b| [#{args1}, b]}")
- assert_equal(OVER_STACK_ARGV[0...-1] + [[OVER_STACK_ARGV.last]], l.(*OVER_STACK_ARGV))
-
- l = instance_eval("proc{|#{args}, b, *c| [#{args}, b, c]}")
- assert_equal(OVER_STACK_ARGV + [nil, []], l.(*OVER_STACK_ARGV))
-
- l = instance_eval("proc{|#{args}, b, *c, d| [#{args}, b, c, d]}")
- assert_equal(OVER_STACK_ARGV + [nil, [], nil], l.(*OVER_STACK_ARGV))
- end if OVER_STACK_LEN < 200
-
- def test_call_lambda_large_array_splat_fail
- [
- ->{} ,
- ->(a=1){},
- ->(k: 1){},
- ->(**kw){},
- ->(k: 1, **kw){},
- ->(a=1, k: 1){},
- ->(a=1, **kw){},
- ->(a=1, k: 1, **kw){},
- ].each do |l|
- assert_raise_with_message(ArgumentError, /wrong number of arguments \(given #{OVER_STACK_LEN}, expected 0(\.\.[12])?\)/) do
- l.call(*OVER_STACK_ARGV)
- end
- end
- end
-
- def test_call_lambda_large_array_splat_pass
- assert_equal OVER_STACK_LEN, ->(*a){a.length}.(*OVER_STACK_ARGV)
- assert_equal (OVER_STACK_LEN - 1), ->(_, *a){a.length}.(*OVER_STACK_ARGV)
- assert_equal (OVER_STACK_LEN - 2), ->(_, *a, _){a.length}.(*OVER_STACK_ARGV)
- assert_equal (OVER_STACK_LEN - 1), ->(b=1, *a){a.length}.(*OVER_STACK_ARGV)
- assert_equal (OVER_STACK_LEN - 2), ->(b=1, *a, _){a.length}.(*OVER_STACK_ARGV)
- assert_equal (OVER_STACK_LEN - 1), ->(b, *a){a.length}.(*OVER_STACK_ARGV)
- assert_equal OVER_STACK_LEN, ->(*a, k: 1){a.length}.(*OVER_STACK_ARGV)
- assert_equal OVER_STACK_LEN, ->(*a, **kw){a.length}.(*OVER_STACK_ARGV)
- assert_equal OVER_STACK_LEN, ->(*a, k: 1, **kw){a.length}.(*OVER_STACK_ARGV)
- assert_equal (OVER_STACK_LEN - 1), ->(b=1, *a, k: 1){a.length}.(*OVER_STACK_ARGV)
- assert_equal (OVER_STACK_LEN - 1), ->(b=1, *a, **kw){a.length}.(*OVER_STACK_ARGV)
- assert_equal (OVER_STACK_LEN - 1), ->(b=1, *a, k: 1, **kw){a.length}.(*OVER_STACK_ARGV)
- assert_equal (OVER_STACK_LEN - 2), ->(b=1, *a, _, k: 1){a.length}.(*OVER_STACK_ARGV)
- assert_equal (OVER_STACK_LEN - 2), ->(b=1, *a, _, **kw){a.length}.(*OVER_STACK_ARGV)
- assert_equal (OVER_STACK_LEN - 2), ->(b=1, *a, _, k: 1, **kw){a.length}.(*OVER_STACK_ARGV)
- end
-
- def test_call_yield_block_large_array_splat_pass
- def self.a
- yield(*OVER_STACK_ARGV)
- end
-
- [
- proc{0} ,
- proc{|a=1|a},
- proc{|k: 1|0},
- proc{|**kw| 0},
- proc{|k: 1, **kw| 0},
- proc{|a=1, k: 1| a},
- proc{|a=1, **kw| a},
- proc{|a=1, k: 1, **kw| a},
- ].each do |l|
- assert_equal 0, a(&l)
- end
-
- assert_equal OVER_STACK_LEN, a{|*a| a.length}
- assert_equal (OVER_STACK_LEN - 1), a{|_, *a| a.length}
- assert_equal (OVER_STACK_LEN - 2), a{|_, *a, _| a.length}
- assert_equal (OVER_STACK_LEN - 1), a{|b=1, *a| a.length}
- assert_equal (OVER_STACK_LEN - 2), a{|b=1, *a, _| a.length}
- assert_equal (OVER_STACK_LEN - 1), a{|b, *a| a.length}
- assert_equal OVER_STACK_LEN, a{|*a, k: 1| a.length}
- assert_equal OVER_STACK_LEN, a{|*a, **kw| a.length}
- assert_equal OVER_STACK_LEN, a{|*a, k: 1, **kw| a.length}
- assert_equal (OVER_STACK_LEN - 1), a{|b=1, *a, k: 1| a.length}
- assert_equal (OVER_STACK_LEN - 1), a{|b=1, *a, **kw| a.length}
- assert_equal (OVER_STACK_LEN - 1), a{|b=1, *a, k: 1, **kw| a.length}
- assert_equal (OVER_STACK_LEN - 2), a{|b=1, *a, _, k: 1| a.length}
- assert_equal (OVER_STACK_LEN - 2), a{|b=1, *a, _, **kw| a.length}
- assert_equal (OVER_STACK_LEN - 2), a{|b=1, *a, _, k: 1, **kw| a.length}
- end
-
- def test_call_yield_large_array_splat_with_large_number_of_parameters
- def self.a
- yield(*OVER_STACK_ARGV)
- end
-
- args = OVER_STACK_ARGV.map{|i| "a#{i}"}.join(',')
- args1 = (OVER_STACK_LEN-1).times.map{|i| "a#{i}"}.join(',')
-
- assert_equal OVER_STACK_ARGV, instance_eval("a{|#{args}| [#{args}]}", __FILE__, __LINE__)
- assert_equal(OVER_STACK_ARGV + [nil], instance_eval("a{|#{args}, b| [#{args}, b]}", __FILE__, __LINE__))
- assert_equal(OVER_STACK_ARGV[0...-1], instance_eval("a{|#{args1}| [#{args1}]}", __FILE__, __LINE__))
- assert_equal(OVER_STACK_ARGV + [[]], instance_eval("a{|#{args}, *b| [#{args}, b]}", __FILE__, __LINE__))
- assert_equal(OVER_STACK_ARGV[0...-1] + [[OVER_STACK_ARGV.last]], instance_eval("a{|#{args1}, *b| [#{args1}, b]}", __FILE__, __LINE__))
- assert_equal(OVER_STACK_ARGV + [nil, []], instance_eval("a{|#{args}, b, *c| [#{args}, b, c]}", __FILE__, __LINE__))
- assert_equal(OVER_STACK_ARGV + [nil, [], nil], instance_eval("a{|#{args}, b, *c, d| [#{args}, b, c, d]}", __FILE__, __LINE__))
- end if OVER_STACK_LEN < 200
-
- def test_call_yield_lambda_large_array_splat_fail
- def self.a
- yield(*OVER_STACK_ARGV)
- end
- [
- ->{} ,
- ->(a=1){},
- ->(k: 1){},
- ->(**kw){},
- ->(k: 1, **kw){},
- ->(a=1, k: 1){},
- ->(a=1, **kw){},
- ->(a=1, k: 1, **kw){},
- ].each do |l|
- assert_raise_with_message(ArgumentError, /wrong number of arguments \(given #{OVER_STACK_LEN}, expected 0(\.\.[12])?\)/) do
- a(&l)
- end
- end
- end
-
- def test_call_yield_lambda_large_array_splat_pass
- def self.a
- yield(*OVER_STACK_ARGV)
- end
-
- assert_equal OVER_STACK_LEN, a(&->(*a){a.length})
- assert_equal (OVER_STACK_LEN - 1), a(&->(_, *a){a.length})
- assert_equal (OVER_STACK_LEN - 2), a(&->(_, *a, _){a.length})
- assert_equal (OVER_STACK_LEN - 1), a(&->(b=1, *a){a.length})
- assert_equal (OVER_STACK_LEN - 2), a(&->(b=1, *a, _){a.length})
- assert_equal (OVER_STACK_LEN - 1), a(&->(b, *a){a.length})
- assert_equal OVER_STACK_LEN, a(&->(*a, k: 1){a.length})
- assert_equal OVER_STACK_LEN, a(&->(*a, **kw){a.length})
- assert_equal OVER_STACK_LEN, a(&->(*a, k: 1, **kw){a.length})
- assert_equal (OVER_STACK_LEN - 1), a(&->(b=1, *a, k: 1){a.length})
- assert_equal (OVER_STACK_LEN - 1), a(&->(b=1, *a, **kw){a.length})
- assert_equal (OVER_STACK_LEN - 1), a(&->(b=1, *a, k: 1, **kw){a.length})
- assert_equal (OVER_STACK_LEN - 2), a(&->(b=1, *a, _, k: 1){a.length})
- assert_equal (OVER_STACK_LEN - 2), a(&->(b=1, *a, _, **kw){a.length})
- assert_equal (OVER_STACK_LEN - 2), a(&->(b=1, *a, _, k: 1, **kw){a.length})
- end
-
- def test_call_send_iseq_large_array_splat_fail
- def self.a; end
- def self.b(a=1); end
- def self.c(k: 1); end
- def self.d(**kw); end
- def self.e(k: 1, **kw); end
- def self.f(a=1, k: 1); end
- def self.g(a=1, **kw); end
- def self.h(a=1, k: 1, **kw); end
-
- (:a..:h).each do |meth|
- assert_raise_with_message(ArgumentError, /wrong number of arguments \(given #{OVER_STACK_LEN}, expected 0(\.\.[12])?\)/) do
- send(meth, *OVER_STACK_ARGV)
- end
- end
- end
-
- def test_call_send_iseq_large_array_splat_pass
- def self.a(*a); a.length end
- assert_equal OVER_STACK_LEN, send(:a, *OVER_STACK_ARGV)
-
- def self.b(_, *a); a.length end
- assert_equal (OVER_STACK_LEN - 1), send(:b, *OVER_STACK_ARGV)
-
- def self.c(_, *a, _); a.length end
- assert_equal (OVER_STACK_LEN - 2), send(:c, *OVER_STACK_ARGV)
-
- def self.d(b=1, *a); a.length end
- assert_equal (OVER_STACK_LEN - 1), send(:d, *OVER_STACK_ARGV)
-
- def self.e(b=1, *a, _); a.length end
- assert_equal (OVER_STACK_LEN - 2), send(:e, *OVER_STACK_ARGV)
-
- def self.f(b, *a); a.length end
- assert_equal (OVER_STACK_LEN - 1), send(:f, *OVER_STACK_ARGV)
-
- def self.g(*a, k: 1); a.length end
- assert_equal OVER_STACK_LEN, send(:g, *OVER_STACK_ARGV)
-
- def self.h(*a, **kw); a.length end
- assert_equal OVER_STACK_LEN, send(:h, *OVER_STACK_ARGV)
-
- def self.i(*a, k: 1, **kw); a.length end
- assert_equal OVER_STACK_LEN, send(:i, *OVER_STACK_ARGV)
-
- def self.j(b=1, *a, k: 1); a.length end
- assert_equal (OVER_STACK_LEN - 1), send(:j, *OVER_STACK_ARGV)
-
- def self.k(b=1, *a, **kw); a.length end
- assert_equal (OVER_STACK_LEN - 1), send(:k, *OVER_STACK_ARGV)
-
- def self.l(b=1, *a, k: 1, **kw); a.length end
- assert_equal (OVER_STACK_LEN - 1), send(:l, *OVER_STACK_ARGV)
-
- def self.m(b=1, *a, _, k: 1); a.length end
- assert_equal (OVER_STACK_LEN - 2), send(:m, *OVER_STACK_ARGV)
-
- def self.n(b=1, *a, _, **kw); a.length end
- assert_equal (OVER_STACK_LEN - 2), send(:n, *OVER_STACK_ARGV)
-
- def self.o(b=1, *a, _, k: 1, **kw); a.length end
- assert_equal (OVER_STACK_LEN - 2), send(:o, *OVER_STACK_ARGV)
- end
-
- def test_call_send_iseq_large_array_splat_with_large_number_of_parameters
- args = OVER_STACK_ARGV.map{|i| "a#{i}"}.join(',')
- args1 = (OVER_STACK_LEN-1).times.map{|i| "a#{i}"}.join(',')
-
- singleton_class.class_eval("def a(#{args}); [#{args}] end")
- assert_equal OVER_STACK_ARGV, send(:a, *OVER_STACK_ARGV)
-
- singleton_class.class_eval("def b(#{args}, b=0); [#{args}, b] end")
- assert_equal(OVER_STACK_ARGV + [0], send(:b, *OVER_STACK_ARGV))
-
- singleton_class.class_eval("def c(#{args}, *b); [#{args}, b] end")
- assert_equal(OVER_STACK_ARGV + [[]], send(:c, *OVER_STACK_ARGV))
-
- singleton_class.class_eval("def d(#{args1}, *b); [#{args1}, b] end")
- assert_equal(OVER_STACK_ARGV[0...-1] + [[OVER_STACK_ARGV.last]], send(:d, *OVER_STACK_ARGV))
- end if OVER_STACK_LEN < 200
-
- def test_call_send_cfunc_large_array_splat_fail
- assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN}, expected 0)") do
- send(:object_id, *OVER_STACK_ARGV)
- end
- end
-
- def test_call_send_cfunc_large_array_splat_pass
- assert_equal OVER_STACK_LEN, [].send(:push, *OVER_STACK_ARGV).length
- end
-
- def test_call_attr_reader_large_array_splat_fail
- singleton_class.send(:attr_reader, :a)
- assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN}, expected 0)") do
- a(*OVER_STACK_ARGV)
- end
- assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN}, expected 0)") do
- send(:a, *OVER_STACK_ARGV)
- end
- end
-
- def test_call_attr_writer_large_array_splat_fail
- singleton_class.send(:attr_writer, :a)
- singleton_class.send(:alias_method, :a, :a=)
-
- assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN}, expected 1)") do
- a(*OVER_STACK_ARGV)
- end
- assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN}, expected 1)") do
- send(:a, *OVER_STACK_ARGV)
- end
- end
-
- def test_call_struct_aref_large_array_splat_fail
- s = Struct.new(:a).new
- assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN}, expected 0)") do
- s.a(*OVER_STACK_ARGV)
- end
- assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN}, expected 0)") do
- s.send(:a, *OVER_STACK_ARGV)
- end
- end
-
- def test_call_struct_aset_large_array_splat_fail
- s = Struct.new(:a) do
- alias b a=
- end.new
- assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN}, expected 1)") do
- s.b(*OVER_STACK_ARGV)
- end
- assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN}, expected 1)") do
- s.send(:b, *OVER_STACK_ARGV)
- end
- end
-
- def test_call_alias_large_array_splat
- c = Class.new do
- def a; end
- def c(*a); a.length end
- attr_accessor :e
- end
- sc = Class.new(c) do
- alias b a
- alias d c
- alias f e
- alias g e=
- end
-
- obj = sc.new
- assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN}, expected 0)") do
- obj.b(*OVER_STACK_ARGV)
- end
- assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN}, expected 0)") do
- obj.f(*OVER_STACK_ARGV)
- end
- assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN}, expected 1)") do
- obj.g(*OVER_STACK_ARGV)
- end
-
- assert_equal OVER_STACK_LEN, obj.d(*OVER_STACK_ARGV)
- end
-
- def test_call_zsuper_large_array_splat
- c = Class.new do
- private
- def a; end
- def c(*a); a.length end
- attr_reader :e
- end
- sc = Class.new(c) do
- public :a
- public :c
- public :e
- end
-
- obj = sc.new
- assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN}, expected 0)") do
- obj.a(*OVER_STACK_ARGV)
- end
- assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN}, expected 0)") do
- obj.e(*OVER_STACK_ARGV)
- end
-
- assert_equal OVER_STACK_LEN, obj.c(*OVER_STACK_ARGV)
- end
-
- class RefinedModuleLargeArrayTest
- c = self
- using(Module.new do
- refine c do
- def a; end
- def c(*a) a.length end
- attr_reader :e
- end
- end)
-
- def b
- a(*OVER_STACK_ARGV)
- end
-
- def d
- c(*OVER_STACK_ARGV)
- end
-
- def f
- e(*OVER_STACK_ARGV)
- end
- end
-
- def test_call_refined_large_array_splat_fail
- assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN}, expected 0)") do
- RefinedModuleLargeArrayTest.new.b
- end
-
- assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN}, expected 0)") do
- RefinedModuleLargeArrayTest.new.f
- end
- end
-
- def test_call_refined_large_array_splat_pass
- assert_equal OVER_STACK_LEN, RefinedModuleLargeArrayTest.new.d
- end
-
- def test_call_method_missing_iseq_large_array_splat_fail
- def self.method_missing(_) end
- assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN+1}, expected 1)") do
- nonexistent_method(*OVER_STACK_ARGV)
- end
-
- assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN+1}, expected 1)") do
- send(:nonexistent_method, *OVER_STACK_ARGV)
- end
-
- assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN+1}, expected 1)") do
- send("nonexistent_method123", *OVER_STACK_ARGV)
- end
- end
-
- def test_call_method_missing_iseq_large_array_splat_pass
- def self.method_missing(m, *a)
- a.length
- end
- assert_equal OVER_STACK_LEN, nonexistent_method(*OVER_STACK_ARGV)
- assert_equal OVER_STACK_LEN, send(:nonexistent_method, *OVER_STACK_ARGV)
- assert_equal OVER_STACK_LEN, send("nonexistent_method123", *OVER_STACK_ARGV)
- end
-
- def test_call_bmethod_large_array_splat_fail
- define_singleton_method(:a){}
- define_singleton_method(:b){|a=1|}
- define_singleton_method(:c){|k: 1|}
- define_singleton_method(:d){|**kw|}
- define_singleton_method(:e){|k: 1, **kw|}
- define_singleton_method(:f){|a=1, k: 1|}
- define_singleton_method(:g){|a=1, **kw|}
- define_singleton_method(:h){|a=1, k: 1, **kw|}
-
- (:a..:h).each do |meth|
- assert_raise_with_message(ArgumentError, /wrong number of arguments \(given #{OVER_STACK_LEN}, expected 0(\.\.[12])?\)/) do
- instance_eval("#{meth}(*OVER_STACK_ARGV)", __FILE__, __LINE__)
- end
- end
- end
-
- def test_call_bmethod_large_array_splat_pass
- define_singleton_method(:a){|*a| a.length}
- assert_equal OVER_STACK_LEN, a(*OVER_STACK_ARGV)
-
- define_singleton_method(:b){|_, *a| a.length}
- assert_equal (OVER_STACK_LEN - 1), b(*OVER_STACK_ARGV)
-
- define_singleton_method(:c){|_, *a, _| a.length}
- assert_equal (OVER_STACK_LEN - 2), c(*OVER_STACK_ARGV)
-
- define_singleton_method(:d){|b=1, *a| a.length}
- assert_equal (OVER_STACK_LEN - 1), d(*OVER_STACK_ARGV)
-
- define_singleton_method(:e){|b=1, *a, _| a.length}
- assert_equal (OVER_STACK_LEN - 2), e(*OVER_STACK_ARGV)
-
- define_singleton_method(:f){|b, *a| a.length}
- assert_equal (OVER_STACK_LEN - 1), f(*OVER_STACK_ARGV)
-
- define_singleton_method(:g){|*a, k: 1| a.length}
- assert_equal OVER_STACK_LEN, g(*OVER_STACK_ARGV)
-
- define_singleton_method(:h){|*a, **kw| a.length}
- assert_equal OVER_STACK_LEN, h(*OVER_STACK_ARGV)
-
- define_singleton_method(:i){|*a, k: 1, **kw| a.length}
- assert_equal OVER_STACK_LEN, i(*OVER_STACK_ARGV)
-
- define_singleton_method(:j){|b=1, *a, k: 1| a.length}
- assert_equal (OVER_STACK_LEN - 1), j(*OVER_STACK_ARGV)
-
- define_singleton_method(:k){|b=1, *a, **kw| a.length}
- assert_equal (OVER_STACK_LEN - 1), k(*OVER_STACK_ARGV)
-
- define_singleton_method(:l){|b=1, *a, k: 1, **kw| a.length}
- assert_equal (OVER_STACK_LEN - 1), l(*OVER_STACK_ARGV)
-
- define_singleton_method(:m){|b=1, *a, _, k: 1| a.length}
- assert_equal (OVER_STACK_LEN - 2), m(*OVER_STACK_ARGV)
-
- define_singleton_method(:n){|b=1, *a, _, **kw| a.length}
- assert_equal (OVER_STACK_LEN - 2), n(*OVER_STACK_ARGV)
-
- define_singleton_method(:o){|b=1, *a, _, k: 1, **kw| a.length}
- assert_equal (OVER_STACK_LEN - 2), o(*OVER_STACK_ARGV)
- end
-
- def test_call_method_missing_bmethod_large_array_splat_fail
- define_singleton_method(:method_missing){|_|}
- assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN+1}, expected 1)") do
- nonexistent_method(*OVER_STACK_ARGV)
- end
-
- assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN+1}, expected 1)") do
- send(:nonexistent_method, *OVER_STACK_ARGV)
- end
-
- assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN+1}, expected 1)") do
- send("nonexistent_method123", *OVER_STACK_ARGV)
- end
- end
-
- def test_call_method_missing_bmethod_large_array_splat_pass
- define_singleton_method(:method_missing){|_, *a| a.length}
- assert_equal OVER_STACK_LEN, nonexistent_method(*OVER_STACK_ARGV)
- assert_equal OVER_STACK_LEN, send(:nonexistent_method, *OVER_STACK_ARGV)
- assert_equal OVER_STACK_LEN, send("nonexistent_method123", *OVER_STACK_ARGV)
- end
-
- def test_call_symproc_large_array_splat_fail
- define_singleton_method(:a){}
- define_singleton_method(:b){|a=1|}
- define_singleton_method(:c){|k: 1|}
- define_singleton_method(:d){|**kw|}
- define_singleton_method(:e){|k: 1, **kw|}
- define_singleton_method(:f){|a=1, k: 1|}
- define_singleton_method(:g){|a=1, **kw|}
- define_singleton_method(:h){|a=1, k: 1, **kw|}
-
- (:a..:h).each do |meth|
- assert_raise_with_message(ArgumentError, /wrong number of arguments \(given #{OVER_STACK_LEN}, expected 0(\.\.[12])?\)/) do
- instance_eval(":#{meth}.to_proc.(self, *OVER_STACK_ARGV)", __FILE__, __LINE__)
- end
- end
- end
-
- def test_call_symproc_large_array_splat_pass
- define_singleton_method(:a){|*a| a.length}
- assert_equal OVER_STACK_LEN, :a.to_proc.(self, *OVER_STACK_ARGV)
-
- define_singleton_method(:b){|_, *a| a.length}
- assert_equal (OVER_STACK_LEN - 1), :b.to_proc.(self, *OVER_STACK_ARGV)
-
- define_singleton_method(:c){|_, *a, _| a.length}
- assert_equal (OVER_STACK_LEN - 2), :c.to_proc.(self, *OVER_STACK_ARGV)
-
- define_singleton_method(:d){|b=1, *a| a.length}
- assert_equal (OVER_STACK_LEN - 1), :d.to_proc.(self, *OVER_STACK_ARGV)
-
- define_singleton_method(:e){|b=1, *a, _| a.length}
- assert_equal (OVER_STACK_LEN - 2), :e.to_proc.(self, *OVER_STACK_ARGV)
-
- define_singleton_method(:f){|b, *a| a.length}
- assert_equal (OVER_STACK_LEN - 1), :f.to_proc.(self, *OVER_STACK_ARGV)
-
- define_singleton_method(:g){|*a, k: 1| a.length}
- assert_equal OVER_STACK_LEN, :g.to_proc.(self, *OVER_STACK_ARGV)
-
- define_singleton_method(:h){|*a, **kw| a.length}
- assert_equal OVER_STACK_LEN, :h.to_proc.(self, *OVER_STACK_ARGV)
-
- define_singleton_method(:i){|*a, k: 1, **kw| a.length}
- assert_equal OVER_STACK_LEN, :i.to_proc.(self, *OVER_STACK_ARGV)
-
- define_singleton_method(:j){|b=1, *a, k: 1| a.length}
- assert_equal (OVER_STACK_LEN - 1), :j.to_proc.(self, *OVER_STACK_ARGV)
-
- define_singleton_method(:k){|b=1, *a, **kw| a.length}
- assert_equal (OVER_STACK_LEN - 1), :k.to_proc.(self, *OVER_STACK_ARGV)
-
- define_singleton_method(:l){|b=1, *a, k: 1, **kw| a.length}
- assert_equal (OVER_STACK_LEN - 1), :l.to_proc.(self, *OVER_STACK_ARGV)
-
- define_singleton_method(:m){|b=1, *a, _, k: 1| a.length}
- assert_equal (OVER_STACK_LEN - 2), :m.to_proc.(self, *OVER_STACK_ARGV)
-
- define_singleton_method(:n){|b=1, *a, _, **kw| a.length}
- assert_equal (OVER_STACK_LEN - 2), :n.to_proc.(self, *OVER_STACK_ARGV)
-
- define_singleton_method(:o){|b=1, *a, _, k: 1, **kw| a.length}
- assert_equal (OVER_STACK_LEN - 2), :o.to_proc.(self, *OVER_STACK_ARGV)
- end
-
- def test_call_rb_call_iseq_large_array_splat_fail
- extend Bug::Iter::Yield
- l = ->(*a){}
-
- def self.a; end
- def self.b(a=1) end
- def self.c(k: 1) end
- def self.d(**kw) end
- def self.e(k: 1, **kw) end
- def self.f(a=1, k: 1) end
- def self.g(a=1, **kw) end
- def self.h(a=1, k: 1, **kw) end
-
- (:a..:h).each do |meth|
- assert_raise_with_message(ArgumentError, /wrong number of arguments \(given #{OVER_STACK_LEN}, expected 0(\.\.[12])?\)/) do
- yield_block(meth, *OVER_STACK_ARGV, &l)
- end
- end
- end
-
- def test_call_rb_call_iseq_large_array_splat_pass
- extend Bug::Iter::Yield
- l = ->(*a){a.length}
-
- def self.a(*a) a.length end
- assert_equal OVER_STACK_LEN, yield_block(:a, *OVER_STACK_ARGV, &l)
-
- def self.b(_, *a) a.length end
- assert_equal (OVER_STACK_LEN - 1), yield_block(:b, *OVER_STACK_ARGV, &l)
-
- def self.c(_, *a, _) a.length end
- assert_equal (OVER_STACK_LEN - 2), yield_block(:c, *OVER_STACK_ARGV, &l)
-
- def self.d(b=1, *a) a.length end
- assert_equal (OVER_STACK_LEN - 1), yield_block(:d, *OVER_STACK_ARGV, &l)
-
- def self.e(b=1, *a, _) a.length end
- assert_equal (OVER_STACK_LEN - 2), yield_block(:e, *OVER_STACK_ARGV, &l)
-
- def self.f(b, *a) a.length end
- assert_equal (OVER_STACK_LEN - 1), yield_block(:f, *OVER_STACK_ARGV, &l)
-
- def self.g(*a, k: 1) a.length end
- assert_equal OVER_STACK_LEN, yield_block(:g, *OVER_STACK_ARGV, &l)
-
- def self.h(*a, **kw) a.length end
- assert_equal OVER_STACK_LEN, yield_block(:h, *OVER_STACK_ARGV, &l)
-
- def self.i(*a, k: 1, **kw) a.length end
- assert_equal OVER_STACK_LEN, yield_block(:h, *OVER_STACK_ARGV, &l)
-
- def self.j(b=1, *a, k: 1) a.length end
- assert_equal (OVER_STACK_LEN - 1), yield_block(:j, *OVER_STACK_ARGV, &l)
-
- def self.k(b=1, *a, **kw) a.length end
- assert_equal (OVER_STACK_LEN - 1), yield_block(:k, *OVER_STACK_ARGV, &l)
-
- def self.l(b=1, *a, k: 1, **kw) a.length end
- assert_equal (OVER_STACK_LEN - 1), yield_block(:l, *OVER_STACK_ARGV, &l)
-
- def self.m(b=1, *a, _, k: 1) a.length end
- assert_equal (OVER_STACK_LEN - 2), yield_block(:m, *OVER_STACK_ARGV, &l)
-
- def self.n(b=1, *a, _, **kw) a.length end
- assert_equal (OVER_STACK_LEN - 2), yield_block(:n, *OVER_STACK_ARGV, &l)
-
- def self.o(b=1, *a, _, k: 1, **kw) a.length end
- assert_equal (OVER_STACK_LEN - 2), yield_block(:o, *OVER_STACK_ARGV, &l)
- end
-
- def test_call_rb_call_bmethod_large_array_splat_fail
- extend Bug::Iter::Yield
- l = ->(*a){}
-
- define_singleton_method(:a){||}
- define_singleton_method(:b){|a=1|}
- define_singleton_method(:c){|k: 1|}
- define_singleton_method(:d){|**kw|}
- define_singleton_method(:e){|k: 1, **kw|}
- define_singleton_method(:f){|a=1, k: 1|}
- define_singleton_method(:g){|a=1, **kw|}
- define_singleton_method(:h){|a=1, k: 1, **kw|}
-
- (:a..:h).each do |meth|
- assert_raise_with_message(ArgumentError, /wrong number of arguments \(given #{OVER_STACK_LEN}, expected 0(\.\.[12])?\)/) do
- yield_block(meth, *OVER_STACK_ARGV, &l)
- end
- end
- end
-
- def test_call_rb_call_bmethod_large_array_splat_pass
- extend Bug::Iter::Yield
- l = ->(*a){a.length}
-
- define_singleton_method(:a){|*a| a.length}
- assert_equal OVER_STACK_LEN, yield_block(:a, *OVER_STACK_ARGV, &l)
-
- define_singleton_method(:b){|_, *a| a.length}
- assert_equal (OVER_STACK_LEN - 1), yield_block(:b, *OVER_STACK_ARGV, &l)
-
- define_singleton_method(:c){|_, *a, _| a.length}
- assert_equal (OVER_STACK_LEN - 2), yield_block(:c, *OVER_STACK_ARGV, &l)
-
- define_singleton_method(:d){|b=1, *a| a.length}
- assert_equal (OVER_STACK_LEN - 1), yield_block(:d, *OVER_STACK_ARGV, &l)
-
- define_singleton_method(:e){|b=1, *a, _| a.length}
- assert_equal (OVER_STACK_LEN - 2), yield_block(:e, *OVER_STACK_ARGV, &l)
-
- define_singleton_method(:f){|b, *a| a.length}
- assert_equal (OVER_STACK_LEN - 1), yield_block(:f, *OVER_STACK_ARGV, &l)
-
- define_singleton_method(:g){|*a, k: 1| a.length}
- assert_equal OVER_STACK_LEN, yield_block(:g, *OVER_STACK_ARGV, &l)
-
- define_singleton_method(:h){|*a, **kw| a.length}
- assert_equal OVER_STACK_LEN, yield_block(:h, *OVER_STACK_ARGV, &l)
-
- define_singleton_method(:i){|*a, k: 1, **kw| a.length}
- assert_equal OVER_STACK_LEN, yield_block(:h, *OVER_STACK_ARGV, &l)
-
- define_singleton_method(:j){|b=1, *a, k: 1| a.length}
- assert_equal (OVER_STACK_LEN - 1), yield_block(:j, *OVER_STACK_ARGV, &l)
-
- define_singleton_method(:k){|b=1, *a, **kw| a.length}
- assert_equal (OVER_STACK_LEN - 1), yield_block(:k, *OVER_STACK_ARGV, &l)
-
- define_singleton_method(:l){|b=1, *a, k: 1, **kw| a.length}
- assert_equal (OVER_STACK_LEN - 1), yield_block(:l, *OVER_STACK_ARGV, &l)
-
- define_singleton_method(:m){|b=1, *a, _, k: 1| a.length}
- assert_equal (OVER_STACK_LEN - 2), yield_block(:m, *OVER_STACK_ARGV, &l)
-
- define_singleton_method(:n){|b=1, *a, _, **kw| a.length}
- assert_equal (OVER_STACK_LEN - 2), yield_block(:n, *OVER_STACK_ARGV, &l)
-
- define_singleton_method(:o){|b=1, *a, _, k: 1, **kw| a.length}
- assert_equal (OVER_STACK_LEN - 2), yield_block(:o, *OVER_STACK_ARGV, &l)
- end
-
- def test_call_ifunc_iseq_large_array_splat_fail
- extend Bug::Iter::Yield
- def self.a(*a)
- yield(*a)
- end
- [
- ->(){},
- ->(a=1){},
- ->(k: 1){},
- ->(**kw){},
- ->(k: 1, **kw){},
- ->(a=1, k: 1){},
- ->(a=1, **kw){},
- ->(a=1, k: 1, **kw){},
- ].each do |l|
- assert_raise_with_message(ArgumentError, /wrong number of arguments \(given #{OVER_STACK_LEN}, expected 0(\.\.[12])?\)/) do
- yield_block(:a, *OVER_STACK_ARGV, &l)
- end
- end
- end
-
- def test_call_ifunc_iseq_large_array_splat_pass
- extend Bug::Iter::Yield
- def self.a(*a)
- yield(*a)
- end
-
- l = ->(*a) do a.length end
- assert_equal OVER_STACK_LEN, yield_block(:a, *OVER_STACK_ARGV, &l)
-
- l = ->(_, *a) do a.length end
- assert_equal (OVER_STACK_LEN - 1), yield_block(:a, *OVER_STACK_ARGV, &l)
-
- l = ->(_, *a, _) do a.length end
- assert_equal (OVER_STACK_LEN - 2), yield_block(:a, *OVER_STACK_ARGV, &l)
-
- l = ->(b=1, *a) do a.length end
- assert_equal (OVER_STACK_LEN - 1), yield_block(:a, *OVER_STACK_ARGV, &l)
-
- l = ->(b=1, *a, _) do a.length end
- assert_equal (OVER_STACK_LEN - 2), yield_block(:a, *OVER_STACK_ARGV, &l)
-
- l = ->(b, *a) do a.length end
- assert_equal (OVER_STACK_LEN - 1), yield_block(:a, *OVER_STACK_ARGV, &l)
-
- l = ->(*a, k: 1) do a.length end
- assert_equal OVER_STACK_LEN, yield_block(:a, *OVER_STACK_ARGV, &l)
-
- l = ->(*a, **kw) do a.length end
- assert_equal OVER_STACK_LEN, yield_block(:a, *OVER_STACK_ARGV, &l)
-
- l = ->(*a, k: 1, **kw) do a.length end
- assert_equal OVER_STACK_LEN, yield_block(:a, *OVER_STACK_ARGV, &l)
-
- l = ->(b=1, *a, k: 1) do a.length end
- assert_equal (OVER_STACK_LEN - 1), yield_block(:a, *OVER_STACK_ARGV, &l)
-
- l = ->(b=1, *a, **kw) do a.length end
- assert_equal (OVER_STACK_LEN - 1), yield_block(:a, *OVER_STACK_ARGV, &l)
-
- l = ->(b=1, *a, k: 1, **kw) do a.length end
- assert_equal (OVER_STACK_LEN - 1), yield_block(:a, *OVER_STACK_ARGV, &l)
-
- l = ->(b=1, *a, _, k: 1) do a.length end
- assert_equal (OVER_STACK_LEN - 2), yield_block(:a, *OVER_STACK_ARGV, &l)
-
- l = ->(b=1, *a, _, **kw) do a.length end
- assert_equal (OVER_STACK_LEN - 2), yield_block(:a, *OVER_STACK_ARGV, &l)
-
- l = ->(b=1, *a, _, k: 1, **kw) do a.length end
- assert_equal (OVER_STACK_LEN - 2), yield_block(:a, *OVER_STACK_ARGV, &l)
- end
end
diff --git a/test/ruby/test_class.rb b/test/ruby/test_class.rb
index a8a019cee2..07c34ce9d5 100644
--- a/test/ruby/test_class.rb
+++ b/test/ruby/test_class.rb
@@ -96,13 +96,6 @@ class TestClass < Test::Unit::TestCase
def test_superclass_of_basicobject
assert_equal(nil, BasicObject.superclass)
-
- assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- module Mod end
- BasicObject.include(Mod)
- assert_equal(nil, BasicObject.superclass)
- end;
end
def test_module_function
@@ -362,17 +355,6 @@ class TestClass < Test::Unit::TestCase
assert_equal(42, PrivateClass.new.foo)
end
- def test_private_const_access
- assert_raise_with_message NameError, /uninitialized/ do
- begin
- eval('class ::TestClass::PrivateClass; end')
- rescue NameError
- end
-
- Object.const_get "NOT_AVAILABLE_CONST_NAME_#{__LINE__}"
- end
- end
-
StrClone = String.clone
Class.new(StrClone)
@@ -777,31 +759,6 @@ class TestClass < Test::Unit::TestCase
end
end
- def test_attached_object
- c = Class.new
- sc = c.singleton_class
- obj = c.new
-
- assert_equal(obj, obj.singleton_class.attached_object)
- assert_equal(c, sc.attached_object)
-
- assert_raise_with_message(TypeError, /is not a singleton class/) do
- c.attached_object
- end
-
- assert_raise_with_message(TypeError, /`NilClass' is not a singleton class/) do
- nil.singleton_class.attached_object
- end
-
- assert_raise_with_message(TypeError, /`FalseClass' is not a singleton class/) do
- false.singleton_class.attached_object
- end
-
- assert_raise_with_message(TypeError, /`TrueClass' is not a singleton class/) do
- true.singleton_class.attached_object
- end
- end
-
def test_subclass_gc
c = Class.new
10_000.times do
@@ -827,13 +784,4 @@ PREP
3_000_000.times(&code)
CODE
end
-
- def test_instance_freeze_dont_freeze_the_class_bug_19164
- klass = Class.new
- klass.prepend(Module.new)
-
- klass.new.freeze
- klass.define_method(:bar) {}
- assert_equal klass, klass.remove_method(:bar), '[Bug #19164]'
- end
end
diff --git a/test/ruby/test_clone.rb b/test/ruby/test_clone.rb
index 775c9ed848..321feb07c7 100644
--- a/test/ruby/test_clone.rb
+++ b/test/ruby/test_clone.rb
@@ -27,59 +27,6 @@ class TestClone < Test::Unit::TestCase
assert_equal([M003, M002, M001], M003.ancestors)
end
- def test_frozen_properties_retained_on_clone
- obj = Object.new.freeze
- cloned_obj = obj.clone
-
- assert_predicate(obj, :frozen?)
- assert_predicate(cloned_obj, :frozen?)
- end
-
- def test_ivar_retained_on_clone
- obj = Object.new
- obj.instance_variable_set(:@a, 1)
- cloned_obj = obj.clone
-
- assert_equal(obj.instance_variable_get(:@a), 1)
- assert_equal(cloned_obj.instance_variable_get(:@a), 1)
- end
-
- def test_ivars_retained_on_extended_obj_clone
- ivars = { :@a => 1, :@b => 2, :@c => 3, :@d => 4 }
- obj = Object.new
- ivars.each do |ivar_name, val|
- obj.instance_variable_set(ivar_name, val)
- end
-
- cloned_obj = obj.clone
-
- ivars.each do |ivar_name, val|
- assert_equal(obj.instance_variable_get(ivar_name), val)
- assert_equal(cloned_obj.instance_variable_get(ivar_name), val)
- end
- end
-
- def test_frozen_properties_and_ivars_retained_on_clone_with_ivar
- obj = Object.new
- obj.instance_variable_set(:@a, 1)
- obj.freeze
-
- cloned_obj = obj.clone
-
- assert_predicate(obj, :frozen?)
- assert_equal(obj.instance_variable_get(:@a), 1)
-
- assert_predicate(cloned_obj, :frozen?)
- assert_equal(cloned_obj.instance_variable_get(:@a), 1)
- end
-
- def test_proc_obj_id_flag_reset
- # [Bug #20250]
- proc = Proc.new { }
- proc.object_id
- proc.clone.object_id # Would crash with RUBY_DEBUG=1
- end
-
def test_user_flags
assert_separately([], <<-EOS)
#
diff --git a/test/ruby/test_comparable.rb b/test/ruby/test_comparable.rb
index b689469d9e..b849217b7d 100644
--- a/test/ruby/test_comparable.rb
+++ b/test/ruby/test_comparable.rb
@@ -85,13 +85,7 @@ class TestComparable < Test::Unit::TestCase
assert_equal(1, @o.clamp(1, 1))
assert_equal(@o, @o.clamp(0, 0))
- assert_equal(@o, @o.clamp(nil, 2))
- assert_equal(-2, @o.clamp(nil, -2))
- assert_equal(@o, @o.clamp(-2, nil))
- assert_equal(2, @o.clamp(2, nil))
- assert_equal(@o, @o.clamp(nil, nil))
-
- assert_raise_with_message(ArgumentError, 'min argument must be less than or equal to max argument') {
+ assert_raise_with_message(ArgumentError, 'min argument must be smaller than max argument') {
@o.clamp(2, 1)
}
end
@@ -121,7 +115,7 @@ class TestComparable < Test::Unit::TestCase
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 less than or equal to max argument') {
+ assert_raise_with_message(ArgumentError, 'min argument must be smaller than max argument') {
@o.clamp(2..1)
}
end
diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb
deleted file mode 100644
index 5482a1529d..0000000000
--- a/test/ruby/test_compile_prism.rb
+++ /dev/null
@@ -1,2110 +0,0 @@
-# frozen_string_literal: true
-
-# This file is organized to match itemization in https://github.com/ruby/prism/issues/1335
-module Prism
- class TestCompilePrism < Test::Unit::TestCase
- # Subclass is used for tests which need it
- class Subclass; end
- ############################################################################
- # Literals #
- ############################################################################
-
- def test_FalseNode
- assert_prism_eval("false")
- end
-
- def test_FloatNode
- assert_prism_eval("1.2")
- assert_prism_eval("1.2e3")
- assert_prism_eval("+1.2e+3")
- assert_prism_eval("-1.2e-3")
- end
-
- def test_ImaginaryNode
- assert_prism_eval("1i")
- assert_prism_eval("+1.0i")
- assert_prism_eval("1ri")
- end
-
- def test_IntegerNode
- assert_prism_eval("1")
- assert_prism_eval("+1")
- assert_prism_eval("-1")
- assert_prism_eval("0x10")
- assert_prism_eval("0b10")
- assert_prism_eval("0o10")
- assert_prism_eval("010")
- assert_prism_eval("(0o00)")
- end
-
- def test_NilNode
- assert_prism_eval("nil")
- end
-
- def test_RationalNode
- assert_prism_eval("1.2r")
- assert_prism_eval("+1.2r")
- end
-
- def test_SelfNode
- assert_prism_eval("self")
- end
-
- def test_SourceEncodingNode
- assert_prism_eval("__ENCODING__")
- end
-
- def test_SourceFileNode
- assert_prism_eval("__FILE__")
- end
-
- def test_SourceLineNode
- ruby_eval = RubyVM::InstructionSequence.compile("__LINE__").eval
- prism_eval = RubyVM::InstructionSequence.compile_prism("__LINE__").eval
-
- assert_equal ruby_eval, prism_eval
- end
-
- def test_TrueNode
- assert_prism_eval("true")
- end
-
- ############################################################################
- # Reads #
- ############################################################################
-
- def test_BackReferenceReadNode
- assert_prism_eval("$+")
- end
-
- def test_ClassVariableReadNode
- assert_prism_eval("class Prism::TestCompilePrism; @@pit = 1; @@pit; end")
- end
-
- def test_ConstantPathNode
- assert_prism_eval("Prism::TestCompilePrism")
- end
-
- def test_ConstantReadNode
- assert_prism_eval("Prism")
- end
-
- Z = 1
-
- def test_DefinedNode
- assert_prism_eval("defined? nil")
- assert_prism_eval("defined? self")
- assert_prism_eval("defined? true")
- assert_prism_eval("defined? false")
- assert_prism_eval("defined? 1")
- assert_prism_eval("defined? 1i")
- assert_prism_eval("defined? 1.0")
- assert_prism_eval("defined? 1..2")
- assert_prism_eval("defined? [A, B, C]")
- assert_prism_eval("defined? [1, 2, 3]")
- assert_prism_eval("defined?({ a: 1 })")
- assert_prism_eval("defined? 'str'")
- assert_prism_eval('defined?("#{expr}")')
- assert_prism_eval("defined? :sym")
- assert_prism_eval("defined? /foo/")
- assert_prism_eval('defined?(/#{1}/)')
- assert_prism_eval("defined? -> { 1 + 1 }")
- assert_prism_eval("defined? a && b")
- assert_prism_eval("defined? a || b")
- assert_prism_eval("defined? __ENCODING__")
- assert_prism_eval("defined? __FILE__")
- assert_prism_eval("defined? __LINE__")
-
- assert_prism_eval("defined? %[1,2,3]")
- assert_prism_eval("defined? %q[1,2,3]")
- assert_prism_eval("defined? %Q[1,2,3]")
- assert_prism_eval("defined? %r[1,2,3]")
- assert_prism_eval("defined? %i[1,2,3]")
- assert_prism_eval("defined? %I[1,2,3]")
- assert_prism_eval("defined? %w[1,2,3]")
- assert_prism_eval("defined? %W[1,2,3]")
- assert_prism_eval("defined? %s[1,2,3]")
- assert_prism_eval("defined? %x[1,2,3]")
-
- assert_prism_eval("defined? [*b]")
- assert_prism_eval("defined? [[*1..2], 3, *4..5]")
- assert_prism_eval("defined? [a: [:b, :c]]")
- assert_prism_eval("defined? 1 in 1")
-
- assert_prism_eval("defined? @a")
- assert_prism_eval("defined? $a")
- assert_prism_eval("defined? @@a")
- assert_prism_eval("defined? A")
- assert_prism_eval("defined? ::A")
- assert_prism_eval("defined? A::B")
- assert_prism_eval("defined? A::B::C")
- assert_prism_eval("defined? #{self.class.name}::Z::A")
- assert_prism_eval("defined? yield")
- assert_prism_eval("defined? super")
-
- assert_prism_eval("defined? X = 1")
- assert_prism_eval("defined? X *= 1")
- assert_prism_eval("defined? X /= 1")
- assert_prism_eval("defined? X &= 1")
- assert_prism_eval("defined? X ||= 1")
-
- assert_prism_eval("defined? $1")
- assert_prism_eval("defined? $2")
- assert_prism_eval("defined? $`")
- assert_prism_eval("defined? $'")
- assert_prism_eval("defined? $+")
-
- assert_prism_eval("defined? $X = 1")
- assert_prism_eval("defined? $X *= 1")
- assert_prism_eval("defined? $X /= 1")
- assert_prism_eval("defined? $X &= 1")
- assert_prism_eval("defined? $X ||= 1")
-
- assert_prism_eval("defined? @@X = 1")
- assert_prism_eval("defined? @@X *= 1")
- assert_prism_eval("defined? @@X /= 1")
- assert_prism_eval("defined? @@X &= 1")
- assert_prism_eval("defined? @@X ||= 1")
-
- assert_prism_eval("defined? @X = 1")
- assert_prism_eval("defined? @X *= 1")
- assert_prism_eval("defined? @X /= 1")
- assert_prism_eval("defined? @X &= 1")
- assert_prism_eval("defined? @X ||= 1")
-
- assert_prism_eval("x = 1; defined? x = 1")
- assert_prism_eval("x = 1; defined? x *= 1")
- assert_prism_eval("x = 1; defined? x /= 1")
- assert_prism_eval("x = 1; defined? x &= 1")
- assert_prism_eval("x = 1; defined? x ||= 1")
-
- assert_prism_eval("if defined? A; end")
-
- assert_prism_eval("defined?(())")
- assert_prism_eval("defined?(('1'))")
-
- # method chain starting with self that's truthy
- assert_prism_eval("defined?(self.itself.itself.itself)")
-
- # method chain starting with self that's false (exception swallowed)
- assert_prism_eval("defined?(self.itself.itself.neat)")
-
- # single self with method, truthy
- assert_prism_eval("defined?(self.itself)")
-
- # single self with method, false
- assert_prism_eval("defined?(self.neat!)")
-
- # method chain implicit self that's truthy
- assert_prism_eval("defined?(itself.itself.itself)")
-
- # method chain implicit self that's false
- assert_prism_eval("defined?(itself.neat.itself)")
-
- ## single method implicit self that's truthy
- assert_prism_eval("defined?(itself)")
-
- ## single method implicit self that's false
- assert_prism_eval("defined?(neatneat)")
-
- assert_prism_eval("defined?(a(itself))")
- assert_prism_eval("defined?(itself(itself))")
- end
-
- def test_GlobalVariableReadNode
- assert_prism_eval("$pit = 1; $pit")
- end
-
- def test_InstanceVariableReadNode
- assert_prism_eval("class Prism::TestCompilePrism; @pit = 1; @pit; end")
- end
-
- def test_LocalVariableReadNode
- assert_prism_eval("pit = 1; pit")
- end
-
- def test_NumberedReferenceReadNode
- assert_prism_eval("$1")
- assert_prism_eval("$99999")
- end
-
- ############################################################################
- # Writes #
- ############################################################################
-
- def test_ClassVariableAndWriteNode
- assert_prism_eval("class Prism::TestCompilePrism; @@pit = 0; @@pit &&= 1; end")
- end
-
- def test_ClassVariableOperatorWriteNode
- assert_prism_eval("class Prism::TestCompilePrism; @@pit = 0; @@pit += 1; end")
- end
-
- def test_ClassVariableOrWriteNode
- assert_prism_eval("class Prism::TestCompilePrism; @@pit = 1; @@pit ||= 0; end")
- assert_prism_eval("class Prism::TestCompilePrism; @@pit = nil; @@pit ||= 1; end")
- end
-
- def test_ClassVariableWriteNode
- assert_prism_eval("class Prism::TestCompilePrism; @@pit = 1; end")
- end
-
- def test_ConstantAndWriteNode
- assert_prism_eval("Constant = 1; Constant &&= 1")
- end
-
- def test_ConstantOperatorWriteNode
- assert_prism_eval("Constant = 1; Constant += 1")
- end
-
- def test_ConstantOrWriteNode
- assert_prism_eval("Constant = 1; Constant ||= 1")
- end
-
- def test_ConstantWriteNode
- # We don't call assert_prism_eval directly in this case because we
- # don't want to assign the constant multiple times if we run
- # with `--repeat-count`
- # Instead, we eval manually here, and remove the constant to
- constant_name = "YCT"
- source = "#{constant_name} = 1"
- prism_eval = RubyVM::InstructionSequence.compile_prism(source).eval
- assert_equal prism_eval, 1
- Object.send(:remove_const, constant_name)
- end
-
- def test_ConstantPathWriteNode
- assert_prism_eval("Prism::CPWN = 1")
- assert_prism_eval("::CPWN = 1")
- end
-
- def test_ConstantPathAndWriteNode
- assert_prism_eval("Prism::CPAWN = 1; Prism::CPAWN &&= 2")
- assert_prism_eval("Prism::CPAWN &&= 1")
- assert_prism_eval("::CPAWN = 1; ::CPAWN &&= 2")
- end
-
- def test_ConstantPathOrWriteNode
- assert_prism_eval("Prism::CPOrWN = nil; Prism::CPOrWN ||= 1")
- assert_prism_eval("Prism::CPOrWN ||= 1")
- assert_prism_eval("::CPOrWN = nil; ::CPOrWN ||= 1")
- end
-
- def test_ConstantPathOperatorWriteNode
- assert_prism_eval("Prism::CPOWN = 0; Prism::CPOWN += 1")
- assert_prism_eval("::CPOWN = 0; ::CPOWN += 1")
- end
-
- def test_GlobalVariableAndWriteNode
- assert_prism_eval("$pit = 0; $pit &&= 1")
- end
-
- def test_GlobalVariableOperatorWriteNode
- assert_prism_eval("$pit = 0; $pit += 1")
- end
-
- def test_GlobalVariableOrWriteNode
- assert_prism_eval("$pit ||= 1")
- end
-
- def test_GlobalVariableWriteNode
- assert_prism_eval("$pit = 1")
- end
-
- def test_IndexAndWriteNode
- assert_prism_eval("[0][0] &&= 1")
- assert_prism_eval("[nil][0] &&= 1")
-
- # Testing `[]` with a block passed in
- assert_prism_eval(<<-CODE)
- class CustomHash < Hash
- def []=(key, value, &block)
- block ? super(block.call(key), value) : super(key, value)
- end
- end
-
- hash = CustomHash.new
-
- # Call the custom method with a block that modifies
- # the key before assignment
- hash["KEY"] = "test"
- hash["key", &(Proc.new { _1.upcase })] &&= "value"
- hash
- CODE
- end
-
- def test_IndexOrWriteNode
- assert_prism_eval("[0][0] ||= 1")
- assert_prism_eval("[nil][0] ||= 1")
-
- # Testing `[]` with a block passed in
- assert_prism_eval(<<-CODE)
- class CustomHash < Hash
- def []=(key, value, &block)
- super(block.call(key), value)
- end
- end
-
- hash = CustomHash.new
-
- # Call the custom method with a block that modifies
- # the key before assignment
- hash["key", &(Proc.new { _1.upcase })] ||= "value"
- hash
- CODE
- end
-
- def test_IndexOperatorWriteNode
- assert_prism_eval("[0][0] += 1")
-
- # Testing `[]` with a block passed in
- assert_prism_eval(<<-CODE)
- class CustomHash < Hash
- def [](key, &block)
- block ? super(block.call(key)) : super(key)
- end
-
- def []=(key, value, &block)
- block ? super(block.call(key), value) : super(key, value)
- end
- end
-
- hash = CustomHash.new
-
- # Call the custom method with a block that modifies
- # the key before assignment
- hash["KEY"] = "test"
- hash["key", &(Proc.new { _1.upcase })] &&= "value"
- hash
- CODE
- end
-
- def test_InstanceVariableAndWriteNode
- assert_prism_eval("@pit = 0; @pit &&= 1")
- end
-
- def test_InstanceVariableOperatorWriteNode
- assert_prism_eval("@pit = 0; @pit += 1")
- end
-
- def test_InstanceVariableOrWriteNode
- assert_prism_eval("@pit ||= 1")
- end
-
- def test_InstanceVariableWriteNode
- assert_prism_eval("class Prism::TestCompilePrism; @pit = 1; end")
- end
-
- def test_LocalVariableAndWriteNode
- assert_prism_eval("pit = 0; pit &&= 1")
- end
-
- def test_LocalVariableOperatorWriteNode
- assert_prism_eval("pit = 0; pit += 1")
- end
-
- def test_LocalVariableOrWriteNode
- assert_prism_eval("pit ||= 1")
- end
-
- def test_LocalVariableWriteNode
- assert_prism_eval("pit = 1")
- assert_prism_eval(<<-CODE)
- a = 0
- [].each do
- a = 1
- end
- a
- CODE
-
- assert_prism_eval(<<-CODE)
- a = 1
- d = 1
- [1].each do
- b = 2
- a = 2
- [2].each do
- c = 3
- d = 4
- a = 2
- end
- end
- [a, d]
- CODE
- end
-
- def test_MatchWriteNode
- assert_prism_eval("/(?<foo>bar)(?<baz>bar>)/ =~ 'barbar'")
- assert_prism_eval("/(?<foo>bar)/ =~ 'barbar'")
- end
-
- ############################################################################
- # Multi-writes #
- ############################################################################
-
- def test_ClassVariableTargetNode
- assert_prism_eval("class Prism::TestCompilePrism; @@pit, @@pit1 = 1; end")
- end
-
- def test_ConstantTargetNode
- # We don't call assert_prism_eval directly in this case because we
- # don't want to assign the constant multiple times if we run
- # with `--repeat-count`
- # Instead, we eval manually here, and remove the constant to
- constant_names = ["YCT", "YCT2"]
- source = "#{constant_names.join(",")} = 1"
- prism_eval = RubyVM::InstructionSequence.compile_prism(source).eval
- assert_equal prism_eval, 1
- constant_names.map { |name|
- Object.send(:remove_const, name)
- }
- end
-
- def test_ConstantPathTargetNode
- assert_separately([], <<~'RUBY')
- verbose = $VERBOSE
- # Create some temporary nested constants
- Object.send(:const_set, "MyFoo", Object)
- Object.const_get("MyFoo").send(:const_set, "Bar", Object)
-
- constant_names = ["MyBar", "MyFoo::Bar", "MyFoo::Bar::Baz"]
- source = "#{constant_names.join(",")} = Object"
- iseq = RubyVM::InstructionSequence.compile_prism(source)
- $VERBOSE = nil
- prism_eval = iseq.eval
- $VERBOSE = verbose
- assert_equal prism_eval, Object
- RUBY
- end
-
- def test_GlobalVariableTargetNode
- assert_prism_eval("$pit, $pit1 = 1")
- end
-
- def test_InstanceVariableTargetNode
- assert_prism_eval("class Prism::TestCompilePrism; @pit, @pit1 = 1; end")
- end
-
- def test_LocalVariableTargetNode
- assert_prism_eval("pit, pit1 = 1")
- assert_prism_eval(<<-CODE)
- a = 1
- [1].each do
- c = 2
- a, b = 2
- end
- a
- CODE
- end
-
- def test_MultiTargetNode
- assert_prism_eval("a, (b, c) = [1, 2, 3]")
- assert_prism_eval("a, (b, c) = [1, 2, 3]; a")
- assert_prism_eval("a, (b, c) = [1, 2, 3]; b")
- assert_prism_eval("a, (b, c) = [1, 2, 3]; c")
- assert_prism_eval("a, (b, c) = [1, [2, 3]]; c")
- assert_prism_eval("a, (b, *c) = [1, [2, 3]]; c")
- assert_prism_eval("a, (b, *c) = 1, [2, 3]; c")
- assert_prism_eval("a, (b, *) = 1, [2, 3]; b")
- assert_prism_eval("a, (b, *c, d) = 1, [2, 3, 4]; [a, b, c, d]")
- assert_prism_eval("(a, (b, c, d, e), f, g), h = [1, [2, 3]], 4, 5, [6, 7]; c")
- end
-
- def test_MultiWriteNode
- assert_prism_eval("foo, bar = [1, 2]")
- assert_prism_eval("foo, = [1, 2]")
- assert_prism_eval("foo, *, bar = [1, 2]")
- assert_prism_eval("foo, bar = 1, 2")
- assert_prism_eval("foo, *, bar = 1, 2")
- assert_prism_eval("foo, *, bar = 1, 2, 3, 4")
- assert_prism_eval("a, b, *, d = 1, 2, 3, 4")
- assert_prism_eval("a, b, *, d = 1, 2")
- assert_prism_eval("(a, b), *, c = [1, 3], 4, 5")
- assert_prism_eval("(a, b), *, c = [1, 3], 4, 5; a")
- assert_prism_eval("(a, b), *, c = [1, 3], 4, 5; b")
- assert_prism_eval("(a, b), *, c = [1, 3], 4, 5; c")
- assert_prism_eval("a, *, (c, d) = [1, 3], 4, 5; a")
- assert_prism_eval("a, *, (c, d) = [1, 3], 4, 5; c")
- assert_prism_eval("(a, b, c), *, (d, e) = [1, 3], 4, 5, [6, 7]")
- assert_prism_eval("(a, b, c), *, (d, e) = [1, 3], 4, 5, [6, 7]; b")
- assert_prism_eval("(a, b, c), *, (d, e) = [1, 3], 4, 5, [6, 7]; d")
- assert_prism_eval("((a, *, b), *, (c, *, (d, *, e, f, g))), *, ((h, i, *, j), *, (k, l, m, *, n, o, p), q, r) = 1; a")
- assert_prism_eval("_, {}[:foo] = 1")
- assert_prism_eval("_, {}[:foo], _ = 1")
- assert_prism_eval("_, {}[:foo], _ = 1")
- assert_prism_eval("_,{}[:foo], _, {}[:bar] = 1")
-
- assert_prism_eval(<<~CODE)
- class Foo
- def bar=(x); end
- def baz=(c); end
- end
- foo = Foo.new
- foo.bar, foo.baz = 1
- CODE
- assert_prism_eval(<<~CODE)
- class Foo
- def bar=(x); end
- def baz=(c); end
- end
- foo = Foo.new
- _, foo.bar, foo.baz = 1
- CODE
- assert_prism_eval(<<~CODE)
- class Foo
- def bar=(x); end
- def baz=(c); end
- end
- foo = Foo.new
- _, foo.bar, _, foo.baz = 1
- CODE
- end
-
- ############################################################################
- # String-likes #
- ############################################################################
-
- def test_EmbeddedStatementsNode
- assert_prism_eval('"foo #{to_s} baz"')
- end
-
- def test_EmbeddedVariableNode
- assert_prism_eval('class Prism::TestCompilePrism; @pit = 1; "#@pit"; end')
- assert_prism_eval('class Prism::TestCompilePrism; @@pit = 1; "#@@pit"; end')
- assert_prism_eval('$pit = 1; "#$pit"')
- end
-
- def test_InterpolatedMatchLastLineNode
- assert_prism_eval('$pit = ".oo"; if /"#{$pit}"/mix; end')
- end
-
- def test_InterpolatedRegularExpressionNode
- assert_prism_eval('$pit = 1; /1 #$pit 1/')
- assert_prism_eval('$pit = 1; /#$pit/i')
- assert_prism_eval('/1 #{1 + 2} 1/')
- assert_prism_eval('/1 #{"2"} #{1 + 2} 1/')
- end
-
- def test_InterpolatedStringNode
- assert_prism_eval('$pit = 1; "1 #$pit 1"')
- assert_prism_eval('"1 #{1 + 2} 1"')
- assert_prism_eval('"Prism" "::" "TestCompilePrism"')
- end
-
- def test_InterpolatedSymbolNode
- assert_prism_eval('$pit = 1; :"1 #$pit 1"')
- assert_prism_eval(':"1 #{1 + 2} 1"')
- end
-
- def test_InterpolatedXStringNode
- assert_prism_eval('`echo #{1}`')
- assert_prism_eval('`printf #{"100"}`')
- end
-
- def test_MatchLastLineNode
- assert_prism_eval("if /foo/; end")
- assert_prism_eval("if /foo/i; end")
- assert_prism_eval("if /foo/x; end")
- assert_prism_eval("if /foo/m; end")
- assert_prism_eval("if /foo/im; end")
- assert_prism_eval("if /foo/mx; end")
- assert_prism_eval("if /foo/xi; end")
- assert_prism_eval("if /foo/ixm; end")
- end
-
- def test_RegularExpressionNode
- assert_prism_eval('/pit/')
- assert_prism_eval('/pit/i')
- assert_prism_eval('/pit/x')
- assert_prism_eval('/pit/m')
- assert_prism_eval('/pit/im')
- assert_prism_eval('/pit/mx')
- assert_prism_eval('/pit/xi')
- assert_prism_eval('/pit/ixm')
-
- assert_prism_eval('/pit/u')
- assert_prism_eval('/pit/e')
- assert_prism_eval('/pit/s')
- assert_prism_eval('/pit/n')
-
- assert_prism_eval('/pit/me')
- assert_prism_eval('/pit/ne')
-
- assert_prism_eval('2.times.map { /#{1}/o }')
- assert_prism_eval('2.times.map { foo = 1; /#{foo}/o }')
- end
-
- def test_StringNode
- assert_prism_eval('"pit"')
- assert_prism_eval('"a".frozen?')
-
- frozen_source = <<-CODE
- # frozen_string_literal: true
- "a".frozen?
- CODE
- ruby_eval = RubyVM::InstructionSequence.compile(frozen_source).eval
- prism_eval = RubyVM::InstructionSequence.compile_prism(frozen_source).eval
-
- assert_equal ruby_eval, prism_eval
- end
-
- def test_SymbolNode
- assert_prism_eval(":pit")
- end
-
- def test_XStringNode
- assert_prism_eval(<<~RUBY)
- class Prism::TestCompilePrism
- def self.`(command) = command * 2
- `pit`
- end
- RUBY
- end
-
- ############################################################################
- # Structures #
- ############################################################################
-
- def test_ArrayNode
- assert_prism_eval("[]")
- assert_prism_eval("[1, 2, 3]")
- assert_prism_eval("%i[foo bar baz]")
- assert_prism_eval("%w[foo bar baz]")
- assert_prism_eval("[*1..2]")
- assert_prism_eval("[*1..2, 3, 4, *5..6, 7, 8]")
- assert_prism_eval("[*1..2, 3, 4, *5..6, 7, 8, *9..11]")
- assert_prism_eval("[0, *1..2, 3, 4, *5..6, 7, 8, *9..11]")
- assert_prism_eval("[-1, true, 0, *1..2, 3, 4, *5..6, 7, 8, *9..11]")
- assert_prism_eval("a = [1,2]; [0, *a, 3, 4, *5..6, 7, 8, *9..11]")
- assert_prism_eval("[[*1..2], 3, *4..5]")
- end
-
- def test_AssocNode
- assert_prism_eval("{ foo: :bar }")
- end
-
- def test_AssocSplatNode
- assert_prism_eval("foo = { a: 1 }; { **foo }")
- assert_prism_eval("foo = { a: 1 }; bar = foo; { **foo, b: 2, **bar, c: 3 }")
- assert_prism_eval("foo = { a: 1 }; { b: 2, **foo, c: 3}")
- end
-
- def test_HashNode
- assert_prism_eval("{}")
- assert_prism_eval("{ a: :a }")
- assert_prism_eval("{ a: :a, b: :b }")
- assert_prism_eval("a = 1; { a: a }")
- assert_prism_eval("a = 1; { a: }")
- assert_prism_eval("{ to_s: }")
- assert_prism_eval("{ Prism: }")
- assert_prism_eval("[ Prism: [:b, :c]]")
- assert_prism_eval("{ [] => 1}")
- end
-
- def test_ImplicitNode
- assert_prism_eval("{ to_s: }")
- end
-
- def test_RangeNode
- assert_prism_eval("1..2")
- assert_prism_eval("1...2")
- assert_prism_eval("..2")
- assert_prism_eval("...2")
- assert_prism_eval("1..")
- assert_prism_eval("1...")
- end
-
- def test_SplatNode
- assert_prism_eval("*b = []; b")
- assert_prism_eval("*b = [1, 2, 3]; b")
- assert_prism_eval("a, *b = [1, 2, 3]; a")
- assert_prism_eval("a, *b = [1, 2, 3]; b")
- assert_prism_eval("a, *b, c = [1, 2, 3]; a")
- assert_prism_eval("a, *b, c = [1, 2, 3]; b")
- assert_prism_eval("a, *b, c = [1, 2, 3]; c")
- assert_prism_eval("*b, c = [1, 2, 3]; b")
- assert_prism_eval("*b, c = [1, 2, 3]; c")
- assert_prism_eval("a, *, c = [1, 2, 3]; a")
- assert_prism_eval("a, *, c = [1, 2, 3]; c")
- end
-
- ############################################################################
- # Jumps #
- ############################################################################
-
- def test_AndNode
- assert_prism_eval("true && 1")
- assert_prism_eval("false && 1")
- end
-
- def test_CaseNode
- assert_prism_eval("case :a; when :a; 1; else; 2; end")
- assert_prism_eval("case :a; when :b; 1; else; 2; end")
- assert_prism_eval("case :a; when :a; 1; else; 2; end")
- assert_prism_eval("case :a; when :a; end")
- assert_prism_eval("case :a; when :b, :c; end")
- assert_prism_eval("case; when :a; end")
- assert_prism_eval("case; when :a, :b; 1; else; 2 end")
- assert_prism_eval("case :a; when :b; else; end")
- assert_prism_eval("b = 1; case :a; when b; else; end")
- assert_prism_eval(<<-CODE)
- def self.prism_test_case_node
- case :a
- when :b
- else
- return 2
- end
- 1
- end
- prism_test_case_node
- CODE
- end
-
- def test_ElseNode
- assert_prism_eval("if false; 0; else; 1; end")
- assert_prism_eval("if true; 0; else; 1; end")
- assert_prism_eval("true ? 1 : 0")
- assert_prism_eval("false ? 0 : 1")
- end
-
- def test_FlipFlopNode
- assert_prism_eval("not (1 == 1) .. (2 == 2)")
- assert_prism_eval("not (1 == 1) ... (2 == 2)")
- end
-
- def test_IfNode
- assert_prism_eval("if true; 1; end")
- assert_prism_eval("1 if true")
- assert_prism_eval('a = b = 1; if a..b; end')
- assert_prism_eval('if "a".."b"; end')
- assert_prism_eval('if "a"..; end')
- assert_prism_eval('if .."b"; end')
- assert_prism_eval('if ..1; end')
- assert_prism_eval('if 1..; end')
- assert_prism_eval('if 1..2; end')
- end
-
- def test_OrNode
- assert_prism_eval("true || 1")
- assert_prism_eval("false || 1")
- end
-
- def test_UnlessNode
- assert_prism_eval("1 unless true")
- assert_prism_eval("1 unless false")
- assert_prism_eval("unless true; 1; end")
- assert_prism_eval("unless false; 1; end")
- end
-
- def test_UntilNode
- assert_prism_eval("a = 0; until a == 1; a = a + 1; end")
- end
-
- def test_WhileNode
- assert_prism_eval("a = 0; while a != 1; a = a + 1; end")
- end
-
- def test_ForNode
- assert_prism_eval("for i in [1,2] do; i; end")
- assert_prism_eval("for @i in [1,2] do; @i; end")
- assert_prism_eval("for $i in [1,2] do; $i; end")
-
- assert_prism_eval("for foo, in [1,2,3] do end")
-
- assert_prism_eval("for i, j in {a: 'b'} do; i; j; end")
- end
-
- ############################################################################
- # Throws #
- ############################################################################
-
- def test_BeginNode
- assert_prism_eval("begin; 1; end")
- assert_prism_eval("begin; end; 1")
- end
-
- def test_BreakNode
- assert_prism_eval("while true; break; end")
- assert_prism_eval("while true; break 1; end")
- assert_prism_eval("while true; break 1, 2; end")
-
- assert_prism_eval("[].each { break }")
- assert_prism_eval("[true].map { break }")
- end
-
- def test_EnsureNode
- assert_prism_eval("begin; 1; ensure; 2; end")
- assert_prism_eval("begin; 1; begin; 3; ensure; 4; end; ensure; 2; end")
- assert_prism_eval(<<-CODE)
- begin
- a = 2
- ensure
- end
- CODE
- assert_prism_eval(<<-CODE)
- begin
- a = 2
- ensure
- a = 3
- end
- a
- CODE
- assert_prism_eval(<<-CODE)
- a = 1
- begin
- a = 2
- ensure
- a = 3
- end
- a
- CODE
- assert_prism_eval(<<-CODE)
- a = 1
- begin
- b = 2
- ensure
- c = 3
- end
- a + b + c
- CODE
- assert_prism_eval(<<~CODE)
- foo = 1
- begin
- ensure
- begin
- ensure
- foo.nil?
- end
- end
- CODE
- assert_prism_eval(<<~CODE)
- def test
- ensure
- {}.each do |key, value|
- {}[key] = value
- end
- end
- CODE
- assert_prism_eval(<<~CODE)
- def test
- a = 1
- ensure
- {}.each do |key, value|
- {}[key] = a
- end
- end
- CODE
- assert_prism_eval(<<-CODE)
- def self.prism_test_ensure_node
- begin
- ensure
- end
- return
- end
- prism_test_ensure_node
- CODE
- end
-
- def test_NextNode
- assert_prism_eval("2.times do |i|; next if i == 1; end")
-
- assert_prism_eval(<<-CODE)
- res = []
- i = 0
- while i < 5
- i += 1
- next if i == 3
- res << i
- end
- res
- CODE
-
- assert_prism_eval(<<-CODE)
- res = []
- (1..5).each do |i|
- next if i.even?
- res << i
- end
- res
- CODE
-
- assert_prism_eval(<<-CODE)
- (1..5).map do |i|
- next i, :even if i.even?
- i
- end
- CODE
-
- assert_prism_eval(<<-CODE)
- res = []
- i = 0
- begin
- i += 1
- next if i == 3
- res << i
- end while i < 5
- res
- CODE
-
- assert_prism_eval(<<-CODE)
- while false
- begin
- ensure
- end
- next
- end
- CODE
- end
-
- def test_RedoNode
- assert_prism_eval(<<-CODE)
- counter = 0
-
- 5.times do |i|
- counter += 1
- if i == 2 && counter < 3
- redo
- end
- end
- CODE
-
- assert_prism_eval(<<-CODE)
- for i in 1..5
- if i == 3
- i = 0
- redo
- end
- end
- CODE
-
- assert_prism_eval(<<-CODE)
- i = 0
- begin
- i += 1
- redo if i == 3
- end while i < 5
- CODE
- end
-
- def test_RescueNode
- assert_prism_eval("begin; 1; rescue; 2; end")
- assert_prism_eval(<<~CODE)
- begin
- 1
- rescue SyntaxError
- 2
- end
- CODE
- assert_prism_eval(<<~CODE)
- begin
- 1
- raise 'boom'
- rescue StandardError
- 2
- end
- CODE
- assert_prism_eval(<<~CODE)
- begin
- a = 1
- rescue StandardError => e
- end
- CODE
- assert_prism_eval(<<~CODE)
- begin
- raise StandardError
- rescue StandardError => e
- end
- CODE
- assert_prism_eval(<<~CODE)
- begin
- 1
- rescue StandardError => e
- e
- rescue SyntaxError => f
- f
- else
- 4
- end
- CODE
- assert_prism_eval(<<-CODE)
- begin
- a = 2
- rescue
- a = 3
- end
- a
- CODE
- assert_prism_eval(<<-CODE)
- a = 1
- begin
- a = 2
- rescue
- a = 3
- end
- a
- CODE
- assert_prism_eval(<<-CODE)
- a = 1
- begin
- b = 2
- raise "bang"
- rescue
- c = 3
- end
- a + b + c
- CODE
- assert_prism_eval("begin; rescue; end")
-
- assert_prism_eval(<<~CODE)
- begin
- rescue
- args.each do |key, value|
- tmp[key] = 1
- end
- end
- CODE
- assert_prism_eval(<<~CODE)
- 10.times do
- begin
- rescue
- break
- end
- end
- CODE
- end
-
- def test_RescueModiferNode
- assert_prism_eval("1.nil? rescue false")
- assert_prism_eval("1.nil? rescue 1")
- assert_prism_eval("raise 'bang' rescue nil")
- assert_prism_eval("raise 'bang' rescue a = 1; a.nil?")
- assert_prism_eval("a = 0 rescue (a += 1 && retry if a <= 1)")
- end
-
- def test_RetryNode
- assert_prism_eval(<<~CODE)
- a = 1
- begin
- a
- raise "boom"
- rescue
- a += 1
- retry unless a > 1
- ensure
- a = 3
- end
- CODE
-
- assert_prism_eval(<<~CODE)
- begin
- rescue
- foo = 2
- retry
- end
- CODE
-
- assert_prism_eval(<<~CODE)
- begin
- a = 2
- rescue
- retry
- end
- CODE
- end
-
- def test_ReturnNode
- assert_prism_eval(<<-CODE)
- def self.prism_test_return_node
- return 1
- end
- prism_test_return_node
- CODE
-
- assert_prism_eval(<<-CODE)
- def self.prism_test_return_node
- return 1, 2
- end
- prism_test_return_node
- CODE
-
- assert_prism_eval(<<-CODE)
- def self.prism_test_return_node
- [1].each do |e|
- return true
- end
- end
- prism_test_return_node
- CODE
-
- assert_prism_eval(<<-CODE)
- def self.prism_test_return_node
- [1].map do |i|
- return i if i == 1
- 2
- end
- end
- prism_test_return_node
- CODE
- end
-
- ############################################################################
- # Scopes/statements #
- ############################################################################
-
- def test_BlockNode
- assert_prism_eval("[1, 2, 3].each { |num| num }")
-
- assert_prism_eval("[].tap { _1 }")
-
- assert_prism_eval("[].each { |a,| }")
- assert_prism_eval("[[1, 2, 3]].map { |_, _, a| a }")
- assert_prism_eval("[[1, 2, 3]].map { |_, a| a }")
-
- assert_prism_eval("[[]].map { |a| a }")
- assert_prism_eval("[[]].map { |a| a }")
- assert_prism_eval("[[]].map { |a, &block| a }")
- assert_prism_eval("[[]].map { |a, &block| a }")
- assert_prism_eval("[{}].map { |a,| }")
- assert_prism_eval("[[]].map { |a,b=1| a }")
- assert_prism_eval("[{}].map { |a,| }")
- assert_prism_eval("[{}].map { |a| a }")
- end
-
- def test_ClassNode
- assert_prism_eval("class PrismClassA; end")
- assert_prism_eval("class PrismClassA; end; class PrismClassB < PrismClassA; end")
- assert_prism_eval("class PrismClassA; end; class PrismClassA::PrismClassC; end")
- assert_prism_eval(<<-HERE
- class PrismClassA; end
- class PrismClassA::PrismClassC; end
- class PrismClassB; end
- class PrismClassB::PrismClassD < PrismClassA::PrismClassC; end
- HERE
- )
- end
-
- # Many of these tests are versions of tests at bootstraptest/test_method.rb
- def test_DefNode
- assert_prism_eval("def prism_test_def_node; end")
- assert_prism_eval("a = Object.new; def a.prism_singleton; :ok; end; a.prism_singleton")
- assert_prism_eval("def self.prism_test_def_node() 1 end; prism_test_def_node()")
- assert_prism_eval("def self.prism_test_def_node(a,b) [a, b] end; prism_test_def_node(1,2)")
- assert_prism_eval("def self.prism_test_def_node(a,x=7,y=1) x end; prism_test_def_node(7,1)")
- assert_prism_eval("def self.prism_test_def_node(a = 1); x = 2; end; prism_test_def_node")
-
- # rest argument
- assert_prism_eval("def self.prism_test_def_node(*a) a end; prism_test_def_node().inspect")
- assert_prism_eval("def self.prism_test_def_node(*a) a end; prism_test_def_node(1).inspect")
- assert_prism_eval("def self.prism_test_def_node(x,y,*a) a end; prism_test_def_node(7,7,1,2).inspect")
- assert_prism_eval("def self.prism_test_def_node(x,y=7,*a) a end; prism_test_def_node(7).inspect")
- assert_prism_eval("def self.prism_test_def_node(x,y,z=7,*a) a end; prism_test_def_node(7,7).inspect")
- assert_prism_eval("def self.prism_test_def_node(x,y,z=7,zz=7,*a) a end; prism_test_def_node(7,7,7).inspect")
-
- # keyword arguments
- assert_prism_eval("def self.prism_test_def_node(a: 1, b: 2, c: 4) a + b + c; end; prism_test_def_node(a: 2)")
- assert_prism_eval("def self.prism_test_def_node(a: 1, b: 2, c: 4) a + b + c; end; prism_test_def_node(b: 3)")
- assert_prism_eval(<<-CODE)
- def self.prism_test_def_node(x = 1, y, a: 8, b: 2, c: 4)
- a + b + c + x + y
- end
- prism_test_def_node(10, b: 3)
- CODE
- assert_prism_eval(<<-CODE)
- def self.prism_test_def_node(a: [])
- a
- end
- prism_test_def_node
- CODE
-
- # block arguments
- assert_prism_eval("def self.prism_test_def_node(&block) block end; prism_test_def_node{}.class")
- assert_prism_eval("def self.prism_test_def_node(&block) block end; prism_test_def_node().inspect")
- assert_prism_eval("def self.prism_test_def_node(a,b=7,*c,&block) b end; prism_test_def_node(7,1).inspect")
- assert_prism_eval("def self.prism_test_def_node(a,b=7,*c,&block) c end; prism_test_def_node(7,7,1).inspect")
-
- # splat
- assert_prism_eval("def self.prism_test_def_node(a) a end; prism_test_def_node(*[1])")
- assert_prism_eval("def self.prism_test_def_node(x,a) a end; prism_test_def_node(7,*[1])")
- assert_prism_eval("def self.prism_test_def_node(x,y,a) a end; prism_test_def_node(7,7,*[1])")
- assert_prism_eval("def self.prism_test_def_node(x,y,a,b,c) a end; prism_test_def_node(7,7,*[1,7,7])")
-
- # recursive call
- assert_prism_eval("def self.prism_test_def_node(n) n == 0 ? 1 : prism_test_def_node(n-1) end; prism_test_def_node(5)")
-
- # instance method
- assert_prism_eval("class PrismTestDefNode; def prism_test_def_node() 1 end end; PrismTestDefNode.new.prism_test_def_node")
- assert_prism_eval("class PrismTestDefNode; def prism_test_def_node(*a) a end end; PrismTestDefNode.new.prism_test_def_node(1).inspect")
-
- # block argument
- assert_prism_eval(<<-CODE)
- def self.prism_test_def_node(&block) prism_test_def_node2(&block) end
- def self.prism_test_def_node2() yield 1 end
- prism_test_def_node2 {|a| a }
- CODE
-
- # multi argument
- assert_prism_eval(<<-CODE)
- def self.prism_test_def_node(a, (b, *c, d))
- [a, b, c, d]
- end
- prism_test_def_node("a", ["b", "c", "d"])
- CODE
- assert_prism_eval(<<-CODE)
- def self.prism_test_def_node(a, (b, c, *))
- [a, b, c]
- end
- prism_test_def_node("a", ["b", "c"])
- CODE
- assert_prism_eval(<<-CODE)
- def self.prism_test_def_node(a, (*, b, c))
- [a, b, c]
- end
- prism_test_def_node("a", ["b", "c"])
- CODE
-
- # recursive multis
- assert_prism_eval(<<-CODE)
- def self.prism_test_def_node(a, (b, *c, (d, *e, f)))
- [a, b, c, d, d, e, f]
- end
- prism_test_def_node("a", ["b", "c", ["d", "e", "f"]])
- CODE
-
- # Many arguments
- assert_prism_eval(<<-CODE)
- def self.prism_test_def_node(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m)
- [a, b, c, d, e, f, g, h, i, j, k, l, m]
- end
- prism_test_def_node(
- "a",
- ["b", "c1", "c2", "d"],
- "e",
- "f1", "f2",
- "g",
- ["h", "i1", "i2", "j"],
- k: "k",
- l: "l",
- m1: "m1",
- m2: "m2"
- )
- CODE
- end
-
- def test_method_parameters
- assert_prism_eval(<<-CODE)
- def self.prism_test_method_parameters(a, b=1, *c, d:, e: 2, **f, &g)
- end
-
- method(:prism_test_method_parameters).parameters
- CODE
-
- assert_prism_eval(<<-CODE)
- def self.prism_test_method_parameters(d:, e: 2, **f, &g)
- end
-
- method(:prism_test_method_parameters).parameters
- CODE
-
- assert_prism_eval(<<-CODE)
- def self.prism_test_method_parameters(**f, &g)
- end
-
- method(:prism_test_method_parameters).parameters
- CODE
-
- assert_prism_eval(<<-CODE)
- def self.prism_test_method_parameters(&g)
- end
-
- method(:prism_test_method_parameters).parameters
- CODE
- end
-
- def test_LambdaNode
- assert_prism_eval("-> { to_s }.call")
- end
-
- def test_ModuleNode
- assert_prism_eval("module M; end")
- assert_prism_eval("module M::N; end")
- assert_prism_eval("module ::O; end")
- end
-
- def test_ParenthesesNode
- assert_prism_eval("()")
- assert_prism_eval("(1)")
- end
-
- def test_PreExecutionNode
- # BEGIN {} must be defined at the top level, so we need to manually
- # call the evals here instead of calling `assert_prism_eval`
- ruby_eval = RubyVM::InstructionSequence.compile("BEGIN { a = 1 }; 2").eval
- prism_eval = RubyVM::InstructionSequence.compile_prism("BEGIN { a = 1 }; 2").eval
- assert_equal ruby_eval, prism_eval
-
- ruby_eval = RubyVM::InstructionSequence.compile("b = 2; BEGIN { a = 1 }; a + b").eval
- prism_eval = RubyVM::InstructionSequence.compile_prism("b = 2; BEGIN { a = 1 }; a + b").eval
- assert_equal ruby_eval, prism_eval
- end
-
- def test_PostExecutionNode
- assert_prism_eval("END { 1 }")
- assert_prism_eval("END { @b }; @b = 1")
- assert_prism_eval("END { @b; 0 }; @b = 1")
- assert_prism_eval("foo = 1; END { foo.nil? }")
- assert_prism_eval("foo = 1; END { END { foo.nil? }}")
- end
-
- def test_ProgramNode
- assert_prism_eval("")
- assert_prism_eval("1")
- end
-
- def test_SingletonClassNode
- assert_prism_eval("class << self; end")
- end
-
- def test_StatementsNode
- assert_prism_eval("1")
- end
-
- def test_YieldNode
- assert_prism_eval("def prism_test_yield_node; yield; end")
- assert_prism_eval("def prism_test_yield_node; yield 1, 2; end")
- assert_prism_eval("def prism_test_yield_node; yield **kw if condition; end")
-
- # Test case where there's a call directly after the yield call
- assert_prism_eval("def prism_test_yield_node; yield; 1; end")
- assert_prism_eval("def prism_test_yield_node; yield 1, 2; 1; end")
- end
-
- ############################################################################
- # Calls / arguments #
- ############################################################################
-
- def test_ArgumentsNode
- # assert_prism_eval("[].push 1")
- end
-
- def test_BlockArgumentNode
- assert_prism_eval("1.then(&:to_s)")
- end
-
- def test_BlockLocalVariableNode
- assert_prism_eval(<<-CODE
- pm_var = "outer scope variable"
-
- 1.times { |;pm_var| pm_var = "inner scope variable"; pm_var }
- CODE
- )
-
- assert_prism_eval(<<-CODE
- pm_var = "outer scope variable"
-
- 1.times { |;pm_var| pm_var = "inner scope variable"; pm_var }
- pm_var
- CODE
- )
- end
-
- def test_CallNode
- assert_prism_eval("to_s")
-
- # with arguments
- assert_prism_eval("eval '1'")
-
- # with arguments and popped
- assert_prism_eval("eval '1'; 1")
-
- # With different types of calling arguments
- assert_prism_eval(<<-CODE)
- def self.prism_test_call_node_double_splat(**); end
- prism_test_call_node_double_splat(b: 1, **{})
- CODE
- assert_prism_eval(<<-CODE)
- prism_test_call_node_double_splat(:b => 1)
- CODE
-
- assert_prism_eval(<<-CODE)
- def self.prism_test_call_node_splat(*); end
- prism_test_call_node_splat(*[], 1)
- CODE
-
- assert_prism_eval("prism_test_call_node_splat(*[], 1, 2)")
-
- assert_prism_eval(<<-CODE)
- class Foo
- def []=(a, b)
- 1234
- end
- end
-
- def self.foo(i, j)
- tbl = Foo.new
- tbl[i] = j
- end
- foo(1, 2)
- CODE
-
- assert_prism_eval(<<-CODE)
- class Foo
- def i=(a)
- 1234
- end
- end
-
- def self.foo(j)
- tbl = Foo.new
- tbl.i = j
- end
- foo(1)
- CODE
-
- assert_prism_eval(<<-CODE)
- foo = Object.new
- def foo.[]=(k,v); 42; end
- foo.[]=(1,2)
- CODE
-
- assert_prism_eval(<<-CODE)
- def self.prism_opt_var_trail_hash(a = nil, *b, c, **d); end
- prism_opt_var_trail_hash("a")
- prism_opt_var_trail_hash("a", c: 1)
- prism_opt_var_trail_hash("a", "b")
- prism_opt_var_trail_hash("a", "b", "c")
- prism_opt_var_trail_hash("a", "b", "c", c: 1)
- prism_opt_var_trail_hash("a", "b", "c", "c" => 0, c: 1)
- CODE
-
- assert_prism_eval(<<-CODE)
- def self.foo(*args, **kwargs) = [args, kwargs]
-
- [
- foo(2 => 3),
- foo([] => 42),
- foo(a: 42, b: 61),
- foo(1, 2, 3, a: 42, "b" => 61),
- foo(:a => 42, :b => 61),
- ]
- CODE
-
- assert_prism_eval(<<-CODE)
- class PrivateMethod
- def initialize
- self.instance_var
- end
- private
- attr_accessor :instance_var
- end
- pm = PrivateMethod.new
- pm.send(:instance_var)
- CODE
-
- # Testing safe navigation operator
- assert_prism_eval(<<-CODE)
- def self.test_prism_call_node
- if [][0]&.first
- 1
- end
- end
- test_prism_call_node
- CODE
- end
-
- def test_CallAndWriteNode
- assert_prism_eval(<<-CODE
- class PrismTestSubclass; end
- def PrismTestSubclass.test_call_and_write_node; end;
- PrismTestSubclass.test_call_and_write_node &&= 1
- CODE
- )
-
- assert_prism_eval(<<-CODE
- def PrismTestSubclass.test_call_and_write_node
- "str"
- end
- def PrismTestSubclass.test_call_and_write_node=(val)
- val
- end
- PrismTestSubclass.test_call_and_write_node &&= 1
- CODE
- )
-
- assert_prism_eval(<<-CODE
- def self.test_call_and_write_node; end;
- self.test_call_and_write_node &&= 1
- CODE
- )
-
- assert_prism_eval(<<-CODE
- def self.test_call_and_write_node
- "str"
- end
- def self.test_call_and_write_node=(val)
- val
- end
- self.test_call_and_write_node &&= 1
- CODE
- )
-
- assert_prism_eval(<<-CODE)
- def self.test_prism_call_node; end
- def self.test_prism_call_node=(val)
- val
- end
- self&.test_prism_call_node &&= 1
- CODE
-
- assert_prism_eval(<<-CODE)
- def self.test_prism_call_node
- 2
- end
- def self.test_prism_call_node=(val)
- val
- end
- self&.test_prism_call_node &&= 1
- CODE
- end
-
- def test_CallOrWriteNode
- assert_prism_eval(<<-CODE
- class PrismTestSubclass; end
- def PrismTestSubclass.test_call_or_write_node; end;
- def PrismTestSubclass.test_call_or_write_node=(val)
- val
- end
- PrismTestSubclass.test_call_or_write_node ||= 1
- CODE
- )
-
- assert_prism_eval(<<-CODE
- def PrismTestSubclass.test_call_or_write_node
- "str"
- end
- PrismTestSubclass.test_call_or_write_node ||= 1
- CODE
- )
-
- assert_prism_eval(<<-CODE
- def self.test_call_or_write_node; end;
- def self.test_call_or_write_node=(val)
- val
- end
- self.test_call_or_write_node ||= 1
- CODE
- )
-
- assert_prism_eval(<<-CODE
- def self.test_call_or_write_node
- "str"
- end
- self.test_call_or_write_node ||= 1
- CODE
- )
-
- assert_prism_eval(<<-CODE)
- def self.test_prism_call_node
- 2
- end
- def self.test_prism_call_node=(val)
- val
- end
- self&.test_prism_call_node ||= 1
- CODE
-
- assert_prism_eval(<<-CODE)
- def self.test_prism_call_node; end
- def self.test_prism_call_node=(val)
- val
- end
- self&.test_prism_call_node ||= 1
- CODE
- end
-
- def test_CallOperatorWriteNode
- assert_prism_eval(<<-CODE
- class PrismTestSubclass; end
- def PrismTestSubclass.test_call_operator_write_node
- 2
- end
- def PrismTestSubclass.test_call_operator_write_node=(val)
- val
- end
- PrismTestSubclass.test_call_operator_write_node += 1
- CODE
- )
- end
-
- def test_ForwardingArgumentsNode
- # http://ci.rvm.jp/results/trunk-iseq_binary@ruby-sp2-docker/4779277
- #
- # expected:
- # == disasm: #<ISeq:prism_test_forwarding_arguments_node1@<compiled>:2 (2,8)-(4,11)>
- # local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: 1])
- # [ 1] "..."@0
- # 0000 putself ( 3)
- # 0001 getlocal_WC_0 ?@-2
- # 0003 splatarray false
- # 0005 getblockparamproxy ?@-1, 0
- # 0008 send <calldata!mid:prism_test_forwarding_arguments_node, argc:1, ARGS_SPLAT|ARGS_BLOCKARG|FCALL>, nil
- # 0011 leave ( 2)
- # actual:
- # == disasm: #<ISeq:prism_test_forwarding_arguments_node1@<compiled>:2 (2,8)-(4,11)>
- # local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: 1])
- # [ 1] "..."@0
- # 0000 putself ( 3)
- # 0001 getlocal_WC_0 ?@-2
- # 0003 splatarray false
- # 0005 getblockparamproxy "!"@-1, 0
- # 0008 send <calldata!mid:prism_test_forwarding_arguments_node, argc:1, ARGS_SPLAT|ARGS_BLOCKARG|FCALL>, nil
- # 0011 leave ( 2)
-
- omit "fails on trunk-iseq_binary"
-
- assert_prism_eval(<<-CODE)
- def prism_test_forwarding_arguments_node(...); end;
- def prism_test_forwarding_arguments_node1(...)
- prism_test_forwarding_arguments_node(...)
- end
- CODE
-
- assert_prism_eval(<<-CODE)
- def prism_test_forwarding_arguments_node(...); end;
- def prism_test_forwarding_arguments_node1(a, ...)
- prism_test_forwarding_arguments_node(1,2, 3, ...)
- end
- CODE
- end
-
- def test_ForwardingSuperNode
- assert_prism_eval("class Forwarding; def to_s; super; end; end")
- assert_prism_eval("class Forwarding; def eval(code); super { code }; end; end")
- assert_prism_eval(<<-CODE)
- class A
- def initialize(a, b)
- end
- end
-
- class B < A
- attr_reader :res
- def initialize(a, b, *)
- super
- @res = [a, b]
- end
- end
-
- B.new(1, 2).res
- CODE
- end
-
- def test_KeywordHashNode
- assert_prism_eval("[a: [:b, :c]]")
- end
-
- def test_SuperNode
- assert_prism_eval("def to_s; super 1; end")
- assert_prism_eval("def to_s; super(); end")
- assert_prism_eval("def to_s; super('a', :b, [1,2,3]); end")
- assert_prism_eval("def to_s; super(1, 2, 3, &:foo); end")
- end
-
- ############################################################################
- # Methods / parameters #
- ############################################################################
-
- def test_AliasGlobalVariableNode
- assert_prism_eval("alias $prism_foo $prism_bar")
- end
-
- def test_AliasMethodNode
- assert_prism_eval("alias :prism_a :to_s")
- end
-
- def test_BlockParameterNode
- assert_prism_eval("def prism_test_block_parameter_node(&bar) end")
- assert_prism_eval("->(b, c=1, *d, e, &f){}")
- end
-
- def test_BlockParametersNode
- assert_prism_eval("Object.tap { || }")
- assert_prism_eval("[1].map { |num| num }")
- assert_prism_eval("[1].map { |a; b| b = 2; a + b}")
- end
-
- def test_FowardingParameterNode
- assert_prism_eval("def prism_test_forwarding_parameter_node(...); end")
- end
-
- def test_KeywordRestParameterNode
- assert_prism_eval("def prism_test_keyword_rest_parameter_node(a, **b); end")
- assert_prism_eval("Object.tap { |**| }")
- end
-
- def test_NoKeywordsParameterNode
- assert_prism_eval("def prism_test_no_keywords(**nil); end")
- assert_prism_eval("def prism_test_no_keywords(a, b = 2, **nil); end")
- end
-
- def test_OptionalParameterNode
- assert_prism_eval("def prism_test_optional_param_node(bar = nil); end")
- end
-
- def test_OptionalKeywordParameterNode
- assert_prism_eval("def prism_test_optional_keyword_param_node(bar: nil); end")
- end
-
- def test_ParametersNode
- assert_prism_eval("def prism_test_parameters_node(bar, baz); end")
- assert_prism_eval("def prism_test_parameters_node(a, b = 2); end")
- end
-
- def test_RequiredParameterNode
- assert_prism_eval("def prism_test_required_param_node(bar); end")
- assert_prism_eval("def prism_test_required_param_node(foo, bar); end")
- end
-
- def test_RequiredKeywordParameterNode
- assert_prism_eval("def prism_test_required_param_node(bar:); end")
- assert_prism_eval("def prism_test_required_param_node(foo:, bar:); end")
- assert_prism_eval("-> a, b = 1, c:, d:, &e { a }")
- end
-
- def test_RestParameterNode
- assert_prism_eval("def prism_test_rest_parameter_node(*a); end")
- end
-
- def test_UndefNode
- assert_prism_eval("def prism_undef_node_1; end; undef prism_undef_node_1")
- assert_prism_eval(<<-HERE
- def prism_undef_node_2
- end
- def prism_undef_node_3
- end
- undef prism_undef_node_2, prism_undef_node_3
- HERE
- )
- assert_prism_eval(<<-HERE
- def prism_undef_node_4
- end
- undef :'prism_undef_node_#{4}'
- HERE
- )
- end
-
- ############################################################################
- # Pattern matching #
- ############################################################################
-
- def test_AlternationPatternNode
- assert_prism_eval("1 in 1 | 2")
- assert_prism_eval("1 in 2 | 1")
- assert_prism_eval("1 in 2 | 3 | 4 | 1")
- assert_prism_eval("1 in 2 | 3")
- end
-
- def test_ArrayPatternNode
- assert_prism_eval("[] => []")
-
- ["in", "=>"].each do |operator|
- ["", "Array"].each do |constant|
- assert_prism_eval("[1, 2, 3] #{operator} #{constant}[1, 2, 3]")
-
- assert_prism_eval("[1, 2, 3] #{operator} #{constant}[*]")
- assert_prism_eval("[1, 2, 3] #{operator} #{constant}[1, *]")
- assert_prism_eval("[1, 2, 3] #{operator} #{constant}[1, 2, *]")
- assert_prism_eval("[1, 2, 3] #{operator} #{constant}[1, 2, 3, *]")
-
- assert_prism_eval("[1, 2, 3] #{operator} #{constant}[*foo]")
- assert_prism_eval("[1, 2, 3] #{operator} #{constant}[1, *foo]")
- assert_prism_eval("[1, 2, 3] #{operator} #{constant}[1, 2, *foo]")
- assert_prism_eval("[1, 2, 3] #{operator} #{constant}[1, 2, 3, *foo]")
-
- assert_prism_eval("[1, 2, 3] #{operator} #{constant}[*, 3]")
- assert_prism_eval("[1, 2, 3] #{operator} #{constant}[*, 2, 3]")
- assert_prism_eval("[1, 2, 3] #{operator} #{constant}[*, 1, 2, 3]")
-
- assert_prism_eval("[1, 2, 3] #{operator} #{constant}[*foo, 3]")
- assert_prism_eval("[1, 2, 3] #{operator} #{constant}[*foo, 2, 3]")
- assert_prism_eval("[1, 2, 3] #{operator} #{constant}[*foo, 1, 2, 3]")
- end
- end
-
- assert_prism_eval("begin; Object.new => [1, 2, 3]; rescue NoMatchingPatternError; true; end")
- assert_prism_eval("begin; [1, 2, 3] => Object[1, 2, 3]; rescue NoMatchingPatternError; true; end")
- end
-
- def test_CapturePatternNode
- assert_prism_eval("[1] => [Integer => foo]")
- end
-
- def test_CaseMatchNode
- assert_prism_eval(<<~RUBY)
- case [1, 2, 3]
- in [1, 2, 3]
- 4
- end
- RUBY
-
- assert_prism_eval(<<~RUBY)
- case { a: 5, b: 6 }
- in [1, 2, 3]
- 4
- in { a: 5, b: 6 }
- 7
- end
- RUBY
-
- assert_prism_eval(<<~RUBY)
- case [1, 2, 3, 4]
- in [1, 2, 3]
- 4
- in { a: 5, b: 6 }
- 7
- else
- end
- RUBY
-
- assert_prism_eval(<<~RUBY)
- case [1, 2, 3, 4]
- in [1, 2, 3]
- 4
- in { a: 5, b: 6 }
- 7
- else
- 8
- end
- RUBY
-
- assert_prism_eval(<<~RUBY)
- case [1, 2, 3]
- in [1, 2, 3] unless to_s
- in [1, 2, 3] if to_s.nil?
- in [1, 2, 3]
- true
- end
- RUBY
- end
-
- def test_FindPatternNode
- ["in", "=>"].each do |operator|
- ["", "Array"].each do |constant|
- assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*, 1, 2, 3, 4, 5, *]")
-
- assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*, 1, *]")
- assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*, 3, *]")
- assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*, 5, *]")
-
- assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*, 1, 2, *]")
- assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*, 2, 3, *]")
- assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*, 3, 4, *]")
- assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*, 4, 5, *]")
-
- assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*, 1, 2, 3, *]")
- assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*, 2, 3, 4, *]")
- assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*, 3, 4, 5, *]")
-
- assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*, 1, 2, 3, 4, *]")
- assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*, 2, 3, 4, 5, *]")
-
- assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*foo, 3, *]")
- assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*foo, 3, 4, *]")
- assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*foo, 3, 4, 5, *]")
- assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*foo, 1, 2, 3, 4, *]")
-
- assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*, 3, *foo]")
- assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*, 3, 4, *foo]")
- assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*, 3, 4, 5, *foo]")
- assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*, 1, 2, 3, 4, *foo]")
-
- assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*foo, 3, *bar]")
- assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*foo, 3, 4, *bar]")
- assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*foo, 3, 4, 5, *bar]")
- assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*foo, 1, 2, 3, 4, *bar]")
- end
- end
-
- assert_prism_eval("[1, [2, [3, [4, [5]]]]] => [*, [*, [*, [*, [*]]]]]")
- assert_prism_eval("[1, [2, [3, [4, [5]]]]] => [1, [2, [3, [4, [5]]]]]")
-
- assert_prism_eval("begin; Object.new => [*, 2, *]; rescue NoMatchingPatternError; true; end")
- assert_prism_eval("begin; [1, 2, 3] => Object[*, 2, *]; rescue NoMatchingPatternError; true; end")
- end
-
- def test_HashPatternNode
- assert_prism_eval("{} => {}")
-
- [["{ ", " }"], ["Hash[", "]"]].each do |(prefix, suffix)|
- assert_prism_eval("{} => #{prefix} **nil #{suffix}")
-
- assert_prism_eval("{ a: 1, b: 2, c: 3 } => #{prefix} a: 1 #{suffix}")
- assert_prism_eval("{ a: 1, b: 2, c: 3 } => #{prefix} a: 1, b: 2 #{suffix}")
- assert_prism_eval("{ a: 1, b: 2, c: 3 } => #{prefix} b: 2, c: 3 #{suffix}")
- assert_prism_eval("{ a: 1, b: 2, c: 3 } => #{prefix} a: 1, b: 2, c: 3 #{suffix}")
-
- assert_prism_eval("{ a: 1, b: 2, c: 3 } => #{prefix} ** #{suffix}")
- assert_prism_eval("{ a: 1, b: 2, c: 3 } => #{prefix} a: 1, ** #{suffix}")
- assert_prism_eval("{ a: 1, b: 2, c: 3 } => #{prefix} a: 1, b: 2, ** #{suffix}")
- assert_prism_eval("{ a: 1, b: 2, c: 3 } => #{prefix} b: 2, c: 3, ** #{suffix}")
- assert_prism_eval("{ a: 1, b: 2, c: 3 } => #{prefix} a: 1, b: 2, c: 3, ** #{suffix}")
-
- assert_prism_eval("{ a: 1, b: 2, c: 3 } => #{prefix} **foo #{suffix}")
- assert_prism_eval("{ a: 1, b: 2, c: 3 } => #{prefix} a: 1, **foo #{suffix}")
- assert_prism_eval("{ a: 1, b: 2, c: 3 } => #{prefix} a: 1, b: 2, **foo #{suffix}")
- assert_prism_eval("{ a: 1, b: 2, c: 3 } => #{prefix} b: 2, c: 3, **foo #{suffix}")
- assert_prism_eval("{ a: 1, b: 2, c: 3 } => #{prefix} a: 1, b: 2, c: 3, **foo #{suffix}")
-
- assert_prism_eval("{ a: 1 } => #{prefix} a: 1, **nil #{suffix}")
- assert_prism_eval("{ a: 1, b: 2, c: 3 } => #{prefix} a: 1, b: 2, c: 3, **nil #{suffix}")
- end
-
- assert_prism_eval("{ a: { b: { c: 1 } } } => { a: { b: { c: 1 } } }")
- end
-
- def test_MatchPredicateNode
- assert_prism_eval("1 in 1")
- assert_prism_eval("1.0 in 1.0")
- assert_prism_eval("1i in 1i")
- assert_prism_eval("1r in 1r")
-
- assert_prism_eval("\"foo\" in \"foo\"")
- assert_prism_eval("\"foo \#{1}\" in \"foo \#{1}\"")
-
- assert_prism_eval("false in false")
- assert_prism_eval("nil in nil")
- assert_prism_eval("self in self")
- assert_prism_eval("true in true")
-
- assert_prism_eval("5 in 0..10")
- assert_prism_eval("5 in 0...10")
-
- assert_prism_eval("[\"5\"] in %w[5]")
-
- assert_prism_eval("Prism in Prism")
- assert_prism_eval("Prism in ::Prism")
-
- assert_prism_eval(":prism in :prism")
- assert_prism_eval("%s[prism\#{1}] in %s[prism\#{1}]")
- assert_prism_eval("\"foo\" in /.../")
- assert_prism_eval("\"foo1\" in /...\#{1}/")
- assert_prism_eval("4 in ->(v) { v.even? }")
-
- assert_prism_eval("5 in foo")
-
- assert_prism_eval("1 in 2")
- end
-
- def test_MatchRequiredNode
- assert_prism_eval("1 => 1")
- assert_prism_eval("1.0 => 1.0")
- assert_prism_eval("1i => 1i")
- assert_prism_eval("1r => 1r")
-
- assert_prism_eval("\"foo\" => \"foo\"")
- assert_prism_eval("\"foo \#{1}\" => \"foo \#{1}\"")
-
- assert_prism_eval("false => false")
- assert_prism_eval("nil => nil")
- assert_prism_eval("true => true")
-
- assert_prism_eval("5 => 0..10")
- assert_prism_eval("5 => 0...10")
-
- assert_prism_eval("[\"5\"] => %w[5]")
-
- assert_prism_eval(":prism => :prism")
- assert_prism_eval("%s[prism\#{1}] => %s[prism\#{1}]")
- assert_prism_eval("\"foo\" => /.../")
- assert_prism_eval("\"foo1\" => /...\#{1}/")
- assert_prism_eval("4 => ->(v) { v.even? }")
-
- assert_prism_eval("5 => foo")
- end
-
- def test_PinnedExpressionNode
- assert_prism_eval("4 in ^(4)")
- end
-
- def test_PinnedVariableNode
- assert_prism_eval("module Prism; @@prism = 1; 1 in ^@@prism; end")
- assert_prism_eval("module Prism; @prism = 1; 1 in ^@prism; end")
- assert_prism_eval("$prism = 1; 1 in ^$prism")
- assert_prism_eval("prism = 1; 1 in ^prism")
- end
-
- ############################################################################
- # Miscellaneous #
- ############################################################################
-
- def test_ScopeNode
- assert_separately(%w[], "#{<<-'begin;'}\n#{<<-'end;'}")
- begin;
- def compare_eval(source)
- ruby_eval = RubyVM::InstructionSequence.compile("module A; " + source + "; end").eval
- prism_eval = RubyVM::InstructionSequence.compile_prism("module B; " + source + "; end").eval
-
- assert_equal ruby_eval, prism_eval
- end
-
- def assert_prism_eval(source)
- $VERBOSE, verbose_bak = nil, $VERBOSE
-
- begin
- compare_eval(source)
-
- # Test "popped" functionality
- compare_eval("#{source}; 1")
- ensure
- $VERBOSE = verbose_bak
- end
- end
- assert_prism_eval("a = 1; 1.times do; { a: }; end")
- assert_prism_eval("a = 1; def foo(a); a; end")
- end;
- end
-
- ############################################################################
- # Errors #
- ############################################################################
-
- def test_MissingNode
- # TODO
- end
-
- ############################################################################
- # Encoding #
- ############################################################################
-
- def test_encoding
- assert_prism_eval('"però"')
- assert_prism_eval(":però")
- end
-
- private
-
- def compare_eval(source)
- source = "class Prism::TestCompilePrism\n#{source}\nend"
-
- ruby_eval = RubyVM::InstructionSequence.compile(source).eval
- prism_eval = RubyVM::InstructionSequence.compile_prism(source).eval
-
- if ruby_eval.is_a? Proc
- assert_equal ruby_eval.class, prism_eval.class
- else
- assert_equal ruby_eval, prism_eval
- end
- end
-
- def assert_prism_eval(source)
- $VERBOSE, verbose_bak = nil, $VERBOSE
-
- begin
- compare_eval(source)
-
- # Test "popped" functionality
- compare_eval("#{source}; 1")
- ensure
- $VERBOSE = verbose_bak
- end
- end
- end
-end
diff --git a/test/ruby/test_complex.rb b/test/ruby/test_complex.rb
index 5cd17d9205..a3a7546575 100644
--- a/test/ruby/test_complex.rb
+++ b/test/ruby/test_complex.rb
@@ -221,16 +221,10 @@ class Complex_Test < Test::Unit::TestCase
assert_equal([1,2], Complex.polar(1,2).polar)
assert_equal(Complex.polar(1.0, Math::PI * 2 / 3), Complex.polar(1, Math::PI * 2 / 3))
- one = 1+0i
- c = Complex.polar(0, one)
- assert_equal(0, c)
- assert_predicate(c.real, :real?)
- c = Complex.polar(one, 0)
- assert_equal(1, c)
- assert_predicate(c.real, :real?)
- c = Complex.polar(one)
- assert_equal(1, c)
- assert_predicate(c.real, :real?)
+ assert_in_out_err([], <<-'end;', ['OK'], [])
+ Complex.polar(1, Complex(1, 0))
+ puts :OK
+ end;
end
def test_uplus
@@ -526,71 +520,6 @@ 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)
- end
-
- def test_expt_for_special_angle
- c = Complex(1, 0) ** 100000000000000000000000000000000
- assert_equal(Complex(1, 0), c)
-
- c = Complex(-1, 0) ** 10000000000000000000000000000000
- assert_equal(Complex(1, 0), c)
-
- c = Complex(-1, 0) ** 10000000000000000000000000000001
- assert_equal(Complex(-1, 0), c)
-
- c = Complex(0, 1) ** 100000000000000000000000000000000
- assert_equal(Complex(1, 0), c)
-
- c = Complex(0, 1) ** 100000000000000000000000000000001
- assert_equal(Complex(0, 1), c)
-
- c = Complex(0, 1) ** 100000000000000000000000000000002
- assert_equal(Complex(-1, 0), c)
-
- c = Complex(0, 1) ** 100000000000000000000000000000003
- assert_equal(Complex(0, -1), c)
-
- c = Complex(0, -1) ** 100000000000000000000000000000000
- assert_equal(Complex(1, 0), c)
-
- c = Complex(0, -1) ** 100000000000000000000000000000001
- assert_equal(Complex(0, -1), c)
-
- c = Complex(0, -1) ** 100000000000000000000000000000002
- assert_equal(Complex(-1, 0), c)
-
- c = Complex(0, -1) ** 100000000000000000000000000000003
- assert_equal(Complex(0, 1), c)
-
- c = Complex(1, 1) ** 1
- assert_equal(Complex(1, 1), c)
-
- c = Complex(1, 1) ** 2
- assert_equal(Complex(0, 2), c)
-
- c = Complex(1, 1) ** 3
- assert_equal(Complex(-2, 2), c)
-
- c = Complex(1, 1) ** 4
- assert_equal(Complex(-4, 0), c)
-
- c = Complex(1, 1) ** 5
- assert_equal(Complex(-4, -4), c)
-
- c = Complex(1, 1) ** 6
- assert_equal(Complex(0, -8), c)
-
- c = Complex(1, 1) ** 7
- assert_equal(Complex(8, -8), c)
-
- c = Complex(-2, -2) ** 3
- assert_equal(Complex(16, -16), c)
-
- c = Complex(2, -2) ** 3
- assert_equal(Complex(-16, -16), c)
-
- c = Complex(-2, 2) ** 3
- assert_equal(Complex(16, 16), c)
c = Complex(0.0, -888888888888888.0)**8888
assert_not_predicate(c.real, :nan?)
@@ -638,24 +567,20 @@ class Complex_Test < Test::Unit::TestCase
assert_raise_with_message(TypeError, /C\u{1f5ff}/) { Complex(1).coerce(obj) }
end
- class ObjectX < Numeric
- def initialize(real = true, n = 1) @n = n; @real = real; end
- def +(x) Rational(@n) end
+ class ObjectX
+ def +(x) Rational(1) end
alias - +
alias * +
alias / +
alias quo +
alias ** +
- def coerce(x) [x, Complex(@n)] end
- def real?; @real; end
+ def coerce(x) [x, Complex(1)] end
end
def test_coerce2
x = ObjectX.new
- y = ObjectX.new(false)
- %w(+ - * / quo ** <=>).each do |op|
- assert_kind_of(Numeric, Complex(1).__send__(op, x), op)
- assert_kind_of(Numeric, Complex(1).__send__(op, y), op)
+ %w(+ - * / quo **).each do |op|
+ assert_kind_of(Numeric, Complex(1).__send__(op, x))
end
end
@@ -918,42 +843,20 @@ class Complex_Test < Test::Unit::TestCase
assert_equal(Complex(0), '_5'.to_c)
assert_equal(Complex(5), '5_'.to_c)
assert_equal(Complex(5), '5x'.to_c)
- assert_equal(Complex(51), '5_1'.to_c)
- assert_equal(Complex(5), '5__1'.to_c)
assert_equal(Complex(5), '5+_3i'.to_c)
assert_equal(Complex(5), '5+3_i'.to_c)
assert_equal(Complex(5,3), '5+3i_'.to_c)
assert_equal(Complex(5,3), '5+3ix'.to_c)
- assert_equal(Complex(5,31), '5+3_1i'.to_c)
- assert_equal(Complex(5), '5+3__1i'.to_c)
- assert_equal(Complex(51), Complex('5_1'))
- assert_equal(Complex(5,31), Complex('5+3_1i'))
- assert_equal(Complex(5,31), Complex('5+3_1I'))
- assert_equal(Complex(5,31), Complex('5+3_1j'))
- assert_equal(Complex(5,31), Complex('5+3_1J'))
- assert_equal(Complex(0,31), Complex('3_1i'))
- assert_equal(Complex(0,31), Complex('3_1I'))
- assert_equal(Complex(0,31), Complex('3_1j'))
- assert_equal(Complex(0,31), Complex('3_1J'))
assert_raise(ArgumentError){ Complex('')}
assert_raise(ArgumentError){ Complex('_')}
assert_raise(ArgumentError){ Complex("\f\n\r\t\v5\0")}
assert_raise(ArgumentError){ Complex('_5')}
assert_raise(ArgumentError){ Complex('5_')}
- assert_raise(ArgumentError){ Complex('5__1')}
assert_raise(ArgumentError){ Complex('5x')}
assert_raise(ArgumentError){ Complex('5+_3i')}
assert_raise(ArgumentError){ Complex('5+3_i')}
assert_raise(ArgumentError){ Complex('5+3i_')}
assert_raise(ArgumentError){ Complex('5+3ix')}
- assert_raise(ArgumentError){ Complex('5+3__1i')}
- assert_raise(ArgumentError){ Complex('5+3__1I')}
- assert_raise(ArgumentError){ Complex('5+3__1j')}
- assert_raise(ArgumentError){ Complex('5+3__1J')}
- assert_raise(ArgumentError){ Complex('3__1i')}
- assert_raise(ArgumentError){ Complex('3__1I')}
- assert_raise(ArgumentError){ Complex('3__1j')}
- assert_raise(ArgumentError){ Complex('3__1J')}
assert_equal(Complex(Rational(1,5)), '1/5'.to_c)
assert_equal(Complex(Rational(-1,5)), '-1/5'.to_c)
@@ -1232,34 +1135,15 @@ class Complex_Test < Test::Unit::TestCase
end
def test_canonicalize_polar
- error = "not a real"
- assert_raise_with_message(TypeError, error) do
- Complex.polar(1i)
- end
- assert_raise_with_message(TypeError, error) do
- Complex.polar(1i, 0)
- end
- assert_raise_with_message(TypeError, error) do
- Complex.polar(0, 1i)
- end
- n = Class.new(Numeric) do
- def initialize(x = 1)
- @x = x
+ obj = Class.new(Numeric) do
+ def initialize
+ @x = 2
end
def real?
(@x -= 1) > 0
end
- end
- obj = n.new
- assert_raise_with_message(TypeError, error) do
- Complex.polar(obj)
- end
- obj = n.new
- assert_raise_with_message(TypeError, error) do
- Complex.polar(obj, 0)
- end
- obj = n.new
- assert_raise_with_message(TypeError, error) do
+ end.new
+ assert_raise(TypeError) do
Complex.polar(1, obj)
end
end
diff --git a/test/ruby/test_complex2.rb b/test/ruby/test_complex2.rb
index b89e83efb2..594fc3f45a 100644
--- a/test/ruby/test_complex2.rb
+++ b/test/ruby/test_complex2.rb
@@ -4,7 +4,7 @@ require 'test/unit'
class Complex_Test2 < Test::Unit::TestCase
def test_kumi
- omit unless defined?(Rational)
+ skip unless defined?(Rational)
assert_equal(Complex(1, 0), +Complex(1, 0))
assert_equal(Complex(-1, 0), -Complex(1, 0))
diff --git a/test/ruby/test_complexrational.rb b/test/ruby/test_complexrational.rb
index 31d11fe317..bf4e2b1809 100644
--- a/test/ruby/test_complexrational.rb
+++ b/test/ruby/test_complexrational.rb
@@ -4,7 +4,7 @@ require 'test/unit'
class ComplexRational_Test < Test::Unit::TestCase
def test_rat_srat
- omit unless defined?(Rational)
+ skip unless defined?(Rational)
c = SimpleRat(1,3)
cc = Rational(3,2)
@@ -89,7 +89,7 @@ class ComplexRational_Test < Test::Unit::TestCase
end
def test_comp_srat
- omit unless defined?(Rational)
+ skip unless defined?(Rational)
c = Complex(SimpleRat(2,3),SimpleRat(1,2))
cc = Complex(Rational(3,2),Rational(2,1))
diff --git a/test/ruby/test_data.rb b/test/ruby/test_data.rb
deleted file mode 100644
index bb38f8ec91..0000000000
--- a/test/ruby/test_data.rb
+++ /dev/null
@@ -1,283 +0,0 @@
-# -*- coding: us-ascii -*-
-# frozen_string_literal: false
-require 'test/unit'
-require 'timeout'
-
-class TestData < Test::Unit::TestCase
- def test_define
- klass = Data.define(:foo, :bar)
- assert_kind_of(Class, klass)
- assert_equal(%i[foo bar], klass.members)
-
- assert_raise(NoMethodError) { Data.new(:foo) }
- assert_raise(TypeError) { Data.define(0) }
-
- # Because some code is shared with Struct, check we don't share unnecessary functionality
- assert_raise(TypeError) { Data.define(:foo, keyword_init: true) }
-
- assert_not_respond_to(Data.define, :define, "Cannot define from defined Data class")
- end
-
- def test_define_edge_cases
- # non-ascii
- klass = Data.define(:"r\u{e9}sum\u{e9}")
- o = klass.new(1)
- assert_equal(1, o.send(:"r\u{e9}sum\u{e9}"))
-
- # junk string
- klass = Data.define(:"a\000")
- o = klass.new(1)
- assert_equal(1, o.send(:"a\000"))
-
- # special characters in attribute names
- klass = Data.define(:a, :b?)
- x = Object.new
- o = klass.new("test", x)
- assert_same(x, o.b?)
-
- klass = Data.define(:a, :b!)
- x = Object.new
- o = klass.new("test", x)
- assert_same(x, o.b!)
-
- assert_raise(ArgumentError) { Data.define(:x=) }
- assert_raise(ArgumentError, /duplicate member/) { Data.define(:x, :x) }
- end
-
- def test_define_with_block
- klass = Data.define(:a, :b) do
- def c
- a + b
- end
- end
-
- assert_equal(3, klass.new(1, 2).c)
- end
-
- def test_initialize
- klass = Data.define(:foo, :bar)
-
- # Regular
- test = klass.new(1, 2)
- assert_equal(1, test.foo)
- assert_equal(2, test.bar)
- assert_equal(test, klass.new(1, 2))
- assert_predicate(test, :frozen?)
-
- # Keywords
- test_kw = klass.new(foo: 1, bar: 2)
- assert_equal(1, test_kw.foo)
- assert_equal(2, test_kw.bar)
- assert_equal(test_kw, klass.new(foo: 1, bar: 2))
- assert_equal(test_kw, test)
-
- # Wrong protocol
- assert_raise(ArgumentError) { klass.new(1) }
- assert_raise(ArgumentError) { klass.new(1, 2, 3) }
- assert_raise(ArgumentError) { klass.new(foo: 1) }
- assert_raise(ArgumentError) { klass.new(foo: 1, bar: 2, baz: 3) }
- # Could be converted to foo: 1, bar: 2, but too smart is confusing
- assert_raise(ArgumentError) { klass.new(1, bar: 2) }
- end
-
- def test_initialize_redefine
- klass = Data.define(:foo, :bar) do
- attr_reader :passed
-
- def initialize(*args, **kwargs)
- @passed = [args, kwargs]
- super(foo: 1, bar: 2) # so we can experiment with passing wrong numbers of args
- end
- end
-
- assert_equal([[], {foo: 1, bar: 2}], klass.new(foo: 1, bar: 2).passed)
-
- # Positional arguments are converted to keyword ones
- assert_equal([[], {foo: 1, bar: 2}], klass.new(1, 2).passed)
-
- # Missing arguments can be fixed in initialize
- assert_equal([[], {foo: 1}], klass.new(foo: 1).passed)
- assert_equal([[], {foo: 42}], klass.new(42).passed)
-
- # Extra keyword arguments can be dropped in initialize
- assert_equal([[], {foo: 1, bar: 2, baz: 3}], klass.new(foo: 1, bar: 2, baz: 3).passed)
- end
-
- def test_instance_behavior
- klass = Data.define(:foo, :bar)
-
- test = klass.new(1, 2)
- assert_equal(1, test.foo)
- assert_equal(2, test.bar)
- assert_equal(%i[foo bar], test.members)
- assert_equal(1, test.public_send(:foo))
- assert_equal(0, test.method(:foo).arity)
- assert_equal([], test.method(:foo).parameters)
-
- assert_equal({foo: 1, bar: 2}, test.to_h)
- assert_equal({"foo"=>"1", "bar"=>"2"}, test.to_h { [_1.to_s, _2.to_s] })
-
- assert_equal([1, 2], test.deconstruct)
- assert_equal({foo: 1, bar: 2}, test.deconstruct_keys(nil))
- assert_equal({foo: 1}, test.deconstruct_keys(%i[foo]))
- assert_equal({foo: 1}, test.deconstruct_keys(%i[foo baz]))
- assert_equal({}, test.deconstruct_keys(%i[foo bar baz]))
- assert_raise(TypeError) { test.deconstruct_keys(0) }
-
- assert_kind_of(Integer, test.hash)
- end
-
- def test_hash
- measure = Data.define(:amount, :unit)
-
- assert_equal(measure[1, 'km'].hash, measure[1, 'km'].hash)
- assert_not_equal(measure[1, 'km'].hash, measure[10, 'km'].hash)
- assert_not_equal(measure[1, 'km'].hash, measure[1, 'm'].hash)
- assert_not_equal(measure[1, 'km'].hash, measure[1.0, 'km'].hash)
-
- # Structurally similar data class, but shouldn't be considered
- # the same hash key
- measurement = Data.define(:amount, :unit)
-
- assert_not_equal(measure[1, 'km'].hash, measurement[1, 'km'].hash)
- end
-
- def test_inspect
- klass = Data.define(:a)
- o = klass.new(1)
- assert_equal("#<data a=1>", o.inspect)
-
- Object.const_set(:Foo, klass)
- assert_equal("#<data Foo a=1>", o.inspect)
- Object.instance_eval { remove_const(:Foo) }
-
- klass = Data.define(:@a)
- o = klass.new(1)
- assert_equal("#<data :@a=1>", o.inspect)
- end
-
- def test_equal
- klass1 = Data.define(:a)
- klass2 = Data.define(:a)
- o1 = klass1.new(1)
- o2 = klass1.new(1)
- o3 = klass2.new(1)
- assert_equal(o1, o2)
- assert_not_equal(o1, o3)
- end
-
- def test_eql
- klass1 = Data.define(:a)
- klass2 = Data.define(:a)
- o1 = klass1.new(1)
- o2 = klass1.new(1)
- o3 = klass2.new(1)
- assert_operator(o1, :eql?, o2)
- assert_not_operator(o1, :eql?, o3)
- end
-
- def test_with
- klass = Data.define(:foo, :bar)
- source = klass.new(foo: 1, bar: 2)
-
- # Simple
- test = source.with
- assert_equal(source.object_id, test.object_id)
-
- # Changes
- test = source.with(foo: 10)
-
- assert_equal(1, source.foo)
- assert_equal(2, source.bar)
- assert_equal(source, klass.new(foo: 1, bar: 2))
-
- assert_equal(10, test.foo)
- assert_equal(2, test.bar)
- assert_equal(test, klass.new(foo: 10, bar: 2))
-
- test = source.with(foo: 10, bar: 20)
-
- assert_equal(1, source.foo)
- assert_equal(2, source.bar)
- assert_equal(source, klass.new(foo: 1, bar: 2))
-
- assert_equal(10, test.foo)
- assert_equal(20, test.bar)
- assert_equal(test, klass.new(foo: 10, bar: 20))
-
- # Keyword splat
- changes = { foo: 10, bar: 20 }
- test = source.with(**changes)
-
- assert_equal(1, source.foo)
- assert_equal(2, source.bar)
- assert_equal(source, klass.new(foo: 1, bar: 2))
-
- assert_equal(10, test.foo)
- assert_equal(20, test.bar)
- assert_equal(test, klass.new(foo: 10, bar: 20))
-
- # Wrong protocol
- assert_raise_with_message(ArgumentError, "wrong number of arguments (given 1, expected 0)") do
- source.with(10)
- end
- assert_raise_with_message(ArgumentError, "unknown keywords: :baz, :quux") do
- source.with(foo: 1, bar: 2, baz: 3, quux: 4)
- end
- assert_raise_with_message(ArgumentError, "wrong number of arguments (given 1, expected 0)") do
- source.with(1, bar: 2)
- end
- assert_raise_with_message(ArgumentError, "wrong number of arguments (given 2, expected 0)") do
- source.with(1, 2)
- end
- assert_raise_with_message(ArgumentError, "wrong number of arguments (given 1, expected 0)") do
- source.with({ bar: 2 })
- end
- end
-
- def test_with_initialize
- oddclass = Data.define(:odd) do
- def initialize(odd:)
- raise ArgumentError, "Not odd" unless odd.odd?
- super(odd: odd)
- end
- end
- assert_raise_with_message(ArgumentError, "Not odd") {
- oddclass.new(odd: 0)
- }
- odd = oddclass.new(odd: 1)
- assert_raise_with_message(ArgumentError, "Not odd") {
- odd.with(odd: 2)
- }
- end
-
- def test_memberless
- klass = Data.define
-
- test = klass.new
-
- assert_equal(klass.new, test)
- assert_not_equal(Data.define.new, test)
-
- assert_equal('#<data >', test.inspect)
- assert_equal([], test.members)
- assert_equal({}, test.to_h)
- end
-
- def test_dup
- klass = Data.define(:foo, :bar)
- test = klass.new(foo: 1, bar: 2)
- assert_equal(klass.new(foo: 1, bar: 2), test.dup)
- assert_predicate(test.dup, :frozen?)
- end
-
- Klass = Data.define(:foo, :bar)
-
- def test_marshal
- test = Klass.new(foo: 1, bar: 2)
- loaded = Marshal.load(Marshal.dump(test))
- assert_equal(test, loaded)
- assert_not_same(test, loaded)
- assert_predicate(loaded, :frozen?)
- end
-end
diff --git a/test/ruby/test_default_gems.rb b/test/ruby/test_default_gems.rb
index d8e8226253..3c4aea1561 100644
--- a/test/ruby/test_default_gems.rb
+++ b/test/ruby/test_default_gems.rb
@@ -2,26 +2,15 @@
require 'rubygems'
class TestDefaultGems < Test::Unit::TestCase
- def self.load(file)
- code = File.read(file, mode: "r:UTF-8:-", &:read)
-
- # - `git ls-files` is useless under ruby's repository
- # - `2>/dev/null` works only on Unix-like platforms
- code.gsub!(/`git.*?`/, '""')
-
- eval(code, binding, file)
- end
def test_validate_gemspec
+ skip "git not found" unless system("git", "rev-parse", %i[out err]=>IO::NULL)
srcdir = File.expand_path('../../..', __FILE__)
- specs = 0
- Dir.chdir(srcdir) do
- all_assertions_foreach(nil, *Dir["{lib,ext}/**/*.gemspec"]) do |src|
- specs += 1
- assert_kind_of(Gem::Specification, self.class.load(src), "invalid spec in #{src}")
+ 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
- assert_operator specs, :>, 0, "gemspecs not found"
end
end
diff --git a/test/ruby/test_defined.rb b/test/ruby/test_defined.rb
index b9bf939394..3324a09afe 100644
--- a/test/ruby/test_defined.rb
+++ b/test/ruby/test_defined.rb
@@ -303,20 +303,6 @@ class TestDefined < Test::Unit::TestCase
assert_equal("super", o.x, bug8367)
end
- def test_super_in_basic_object
- BasicObject.class_eval do
- def a
- defined?(super)
- end
- end
-
- assert_nil(a)
- ensure
- BasicObject.class_eval do
- undef_method :a if defined?(a)
- end
- end
-
def test_super_toplevel
assert_separately([], "assert_nil(defined?(super))")
end
diff --git a/test/ruby/test_dir.rb b/test/ruby/test_dir.rb
index 026338f567..39a1dae889 100644
--- a/test/ruby/test_dir.rb
+++ b/test/ruby/test_dir.rb
@@ -19,21 +19,11 @@ class TestDir < Test::Unit::TestCase
@dirs << File.join(i, "")
end
end
- @envs = nil
end
def teardown
$VERBOSE = @verbose
FileUtils.remove_entry_secure @root if File.directory?(@root)
- ENV.update(@envs) if @envs
- end
-
- def setup_envs(envs = %w"HOME LOGDIR")
- @envs ||= {}
- envs.each do |e, v|
- @envs[e] = ENV.delete(e)
- ENV[e] = v if v
- end
end
def test_seek
@@ -96,9 +86,12 @@ class TestDir < Test::Unit::TestCase
d.close
end
- def test_class_chdir
+ def test_chdir
pwd = Dir.pwd
- setup_envs
+ env_home = ENV["HOME"]
+ env_logdir = ENV["LOGDIR"]
+ ENV.delete("HOME")
+ ENV.delete("LOGDIR")
assert_raise(Errno::ENOENT) { Dir.chdir(@nodir) }
assert_raise(ArgumentError) { Dir.chdir }
@@ -132,51 +125,8 @@ class TestDir < Test::Unit::TestCase
rescue
abort("cannot return the original directory: #{ pwd }")
end
- end
-
- def test_instance_chdir
- pwd = Dir.pwd
- dir = Dir.new(pwd)
- root_dir = Dir.new(@root)
- setup_envs
-
- ENV["HOME"] = pwd
- ret = root_dir.chdir do |*a|
- assert_empty(a)
-
- assert_warning(/conflicting chdir during another chdir block/) { dir.chdir }
- assert_warning(/conflicting chdir during another chdir block/) { root_dir.chdir }
-
- assert_equal(@root, Dir.pwd)
-
- assert_raise(RuntimeError) { Thread.new { Thread.current.report_on_exception = false; dir.chdir }.join }
- assert_raise(RuntimeError) { Thread.new { Thread.current.report_on_exception = false; dir.chdir{} }.join }
-
- assert_warning(/conflicting chdir during another chdir block/) { dir.chdir }
- assert_equal(pwd, Dir.pwd)
-
- assert_warning(/conflicting chdir during another chdir block/) { root_dir.chdir }
- assert_equal(@root, Dir.pwd)
-
- assert_warning(/conflicting chdir during another chdir block/) { dir.chdir }
-
- root_dir.chdir do
- assert_equal(@root, Dir.pwd)
- end
- assert_equal(pwd, Dir.pwd)
-
- 42
- end
-
- assert_equal(42, ret)
- ensure
- begin
- assert_equal(0, dir.chdir)
- rescue
- abort("cannot return the original directory: #{ pwd }")
- end
- dir.close
- root_dir.close
+ ENV["HOME"] = env_home
+ ENV["LOGDIR"] = env_logdir
end
def test_chdir_conflict
@@ -202,7 +152,7 @@ class TestDir < Test::Unit::TestCase
end
def test_chroot_nodir
- omit if RUBY_PLATFORM =~ /android/
+ skip if RUBY_PLATFORM =~ /android/
assert_raise(NotImplementedError, Errno::ENOENT, Errno::EPERM
) { Dir.chroot(File.join(@nodir, "")) }
end
@@ -554,9 +504,9 @@ class TestDir < Test::Unit::TestCase
def test_glob_legacy_short_name
bug10819 = '[ruby-core:67954] [Bug #10819]'
bug11206 = '[ruby-core:69435] [Bug #11206]'
- omit unless /\A\w:/ =~ ENV["ProgramFiles"]
+ skip unless /\A\w:/ =~ ENV["ProgramFiles"]
short = "#$&/PROGRA~1"
- omit unless File.directory?(short)
+ skip unless File.directory?(short)
entries = Dir.glob("#{short}/Common*")
assert_not_empty(entries, bug10819)
long = File.expand_path(short)
@@ -566,62 +516,13 @@ class TestDir < Test::Unit::TestCase
assert_include(Dir.glob(wild, File::FNM_SHORTNAME), long, bug10819)
assert_empty(entries - Dir.glob("#{wild}/Common*", File::FNM_SHORTNAME), bug10819)
end
-
- def test_home_windows
- setup_envs(%w[HOME USERPROFILE HOMEDRIVE HOMEPATH])
-
- ENV['HOME'] = "C:\\ruby\\home"
- assert_equal("C:/ruby/home", Dir.home)
-
- ENV['USERPROFILE'] = "C:\\ruby\\userprofile"
- assert_equal("C:/ruby/home", Dir.home)
- ENV.delete('HOME')
- assert_equal("C:/ruby/userprofile", Dir.home)
-
- ENV['HOMEDRIVE'] = "C:"
- ENV['HOMEPATH'] = "\\ruby\\homepath"
- assert_equal("C:/ruby/userprofile", Dir.home)
- ENV.delete('USERPROFILE')
- assert_equal("C:/ruby/homepath", Dir.home)
- end
-
- def test_home_at_startup_windows
- env = {'HOME' => "C:\\ruby\\home"}
- args = [env]
- assert_separately(args, "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- assert_equal("C:/ruby/home", Dir.home)
- end;
-
- env['USERPROFILE'] = "C:\\ruby\\userprofile"
- assert_separately(args, "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- assert_equal("C:/ruby/home", Dir.home)
- end;
-
- env['HOME'] = nil
- assert_separately(args, "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- assert_equal("C:/ruby/userprofile", Dir.home)
- end;
-
- env['HOMEDRIVE'] = "C:"
- env['HOMEPATH'] = "\\ruby\\homepath"
- assert_separately(args, "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- assert_equal("C:/ruby/userprofile", Dir.home)
- end;
-
- env['USERPROFILE'] = nil
- assert_separately(args, "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- assert_equal("C:/ruby/homepath", Dir.home)
- end;
- end
end
def test_home
- setup_envs
+ env_home = ENV["HOME"]
+ env_logdir = ENV["LOGDIR"]
+ ENV.delete("HOME")
+ ENV.delete("LOGDIR")
ENV["HOME"] = @nodir
assert_nothing_raised(ArgumentError) do
@@ -639,16 +540,9 @@ class TestDir < Test::Unit::TestCase
%W[no:such:user \u{7559 5b88}:\u{756a}].each do |user|
assert_raise_with_message(ArgumentError, /#{user}/) {Dir.home(user)}
end
- end
-
- if Encoding.find("filesystem") == Encoding::UTF_8
- # On Windows and macOS, file system encoding is always UTF-8.
- def test_home_utf8
- setup_envs
-
- ENV["HOME"] = "/\u{e4}~\u{1f3e0}"
- assert_equal("/\u{e4}~\u{1f3e0}", Dir.home)
- end
+ ensure
+ ENV["HOME"] = env_home
+ ENV["LOGDIR"] = env_logdir
end
def test_symlinks_not_resolved
@@ -679,21 +573,6 @@ class TestDir < Test::Unit::TestCase
}
end
- def test_for_fd
- if Dir.respond_to? :for_fd
- begin
- new_dir = Dir.new('..')
- for_fd_dir = Dir.for_fd(new_dir.fileno)
- assert_equal(new_dir.chdir{Dir.pwd}, for_fd_dir.chdir{Dir.pwd})
- ensure
- new_dir&.close
- for_fd_dir&.close
- end
- else
- assert_raise(NotImplementedError) { Dir.for_fd(0) }
- end
- end
-
def test_empty?
assert_not_send([Dir, :empty?, @root])
a = File.join(@root, "a")
diff --git a/test/ruby/test_dup.rb b/test/ruby/test_dup.rb
deleted file mode 100644
index 75c4fc0339..0000000000
--- a/test/ruby/test_dup.rb
+++ /dev/null
@@ -1,110 +0,0 @@
-# frozen_string_literal: false
-require 'test/unit'
-
-class TestDup < Test::Unit::TestCase
- module M001; end
- module M002; end
- module M003; include M002; end
- module M002; include M001; end
- module M003; include M002; end
-
- def test_dup
- foo = Object.new
- def foo.test
- "test"
- end
- bar = foo.dup
- def bar.test2
- "test2"
- end
-
- assert_equal("test2", bar.test2)
- assert_raise(NoMethodError) { bar.test }
- assert_equal("test", foo.test)
-
- assert_raise(NoMethodError) {foo.test2}
-
- assert_equal([M003, M002, M001], M003.ancestors)
- end
-
- def test_frozen_properties_not_retained_on_dup
- obj = Object.new.freeze
- duped_obj = obj.dup
-
- assert_predicate(obj, :frozen?)
- refute_predicate(duped_obj, :frozen?)
- end
-
- def test_ivar_retained_on_dup
- obj = Object.new
- obj.instance_variable_set(:@a, 1)
- duped_obj = obj.dup
-
- assert_equal(obj.instance_variable_get(:@a), 1)
- assert_equal(duped_obj.instance_variable_get(:@a), 1)
- end
-
- def test_ivars_retained_on_extended_obj_dup
- ivars = { :@a => 1, :@b => 2, :@c => 3, :@d => 4 }
- obj = Object.new
- ivars.each do |ivar_name, val|
- obj.instance_variable_set(ivar_name, val)
- end
-
- duped_obj = obj.dup
-
- ivars.each do |ivar_name, val|
- assert_equal(obj.instance_variable_get(ivar_name), val)
- assert_equal(duped_obj.instance_variable_get(ivar_name), val)
- end
- end
-
- def test_frozen_properties_not_retained_on_dup_with_ivar
- obj = Object.new
- obj.instance_variable_set(:@a, 1)
- obj.freeze
-
- duped_obj = obj.dup
-
- assert_predicate(obj, :frozen?)
- assert_equal(obj.instance_variable_get(:@a), 1)
-
- refute_predicate(duped_obj, :frozen?)
- assert_equal(duped_obj.instance_variable_get(:@a), 1)
- end
-
- def test_user_flags
- assert_separately([], <<-EOS)
- #
- class Array
- undef initialize_copy
- def initialize_copy(*); end
- end
- x = [1, 2, 3].dup
- 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].dup
- 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.dup
- assert_equal nil, h[:not_exist], '[Bug #14847]'
- EOS
- end
-end
diff --git a/test/ruby/test_econv.rb b/test/ruby/test_econv.rb
index 1d0641e918..1aad0de347 100644
--- a/test/ruby/test_econv.rb
+++ b/test/ruby/test_econv.rb
@@ -931,7 +931,7 @@ class TestEncodingConverter < Test::Unit::TestCase
def test_default_external
Encoding.list.grep(->(enc) {/\AISO-8859-\d+\z/i =~ enc.name}) do |enc|
- assert_separately(%W[-d - #{enc.name}], <<-EOS, ignore_stderr: true)
+ assert_separately(%W[--disable=gems -d - #{enc.name}], <<-EOS, ignore_stderr: true)
Encoding.default_external = ext = ARGV[0]
Encoding.default_internal = int ='utf-8'
assert_nothing_raised do
diff --git a/test/ruby/test_encoding.rb b/test/ruby/test_encoding.rb
index f2c609a4cd..4a6dd932ed 100644
--- a/test/ruby/test_encoding.rb
+++ b/test/ruby/test_encoding.rb
@@ -55,6 +55,39 @@ class TestEncoding < Test::Unit::TestCase
assert_raise(TypeError, bug5150) {Encoding.find(1)}
end
+ def test_replicate
+ assert_separately([], "#{<<~'END;'}")
+ assert_instance_of(Encoding, Encoding::UTF_8.replicate("UTF-8-ANOTHER#{Time.now.to_f}"))
+ assert_instance_of(Encoding, Encoding::ISO_2022_JP.replicate("ISO-2022-JP-ANOTHER#{Time.now.to_f}"))
+ bug3127 = '[ruby-dev:40954]'
+ assert_raise(TypeError, bug3127) {Encoding::UTF_8.replicate(0)}
+ assert_raise_with_message(ArgumentError, /\bNUL\b/, bug3127) {Encoding::UTF_8.replicate("\0")}
+ END;
+ end
+
+ def test_extra_encoding
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ 200.times {|i|
+ Encoding::UTF_8.replicate("dummy#{i}")
+ }
+ e = Encoding.list.last
+ format = "%d".force_encoding(e)
+ assert_equal("0", format % 0)
+ assert_equal(e, format.dup.encoding)
+ assert_equal(e, (format*1).encoding)
+
+ assert_equal(e, (("x"*30).force_encoding(e)*1).encoding)
+ GC.start
+
+ name = "A" * 64
+ Encoding.list.each do |enc|
+ assert_raise(ArgumentError) {enc.replicate(name)}
+ name.succ!
+ end
+ end;
+ end
+
def test_dummy_p
assert_equal(true, Encoding::ISO_2022_JP.dummy?)
assert_equal(false, Encoding::UTF_8.dummy?)
@@ -106,7 +139,7 @@ class TestEncoding < Test::Unit::TestCase
end
def test_errinfo_after_autoload
- assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ 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) {
diff --git a/test/ruby/test_enum.rb b/test/ruby/test_enum.rb
index f7c8f012d8..b0c43b9a7f 100644
--- a/test/ruby/test_enum.rb
+++ b/test/ruby/test_enum.rb
@@ -234,8 +234,6 @@ class TestEnumerable < Test::Unit::TestCase
assert_equal(24, @obj.inject(2) {|z, x| z * x })
assert_equal(24, assert_warning(/given block not used/) {@obj.inject(2, :*) {|z, x| z * x }})
assert_equal(nil, @empty.inject() {9})
-
- assert_raise(ArgumentError) {@obj.inject}
end
FIXNUM_MIN = RbConfig::LIMITS['FIXNUM_MIN']
@@ -1334,16 +1332,4 @@ class TestEnumerable < Test::Unit::TestCase
assert_equal([], @obj.filter_map { nil })
assert_instance_of(Enumerator, @obj.filter_map)
end
-
- def test_ruby_svar
- klass = Class.new do
- include Enumerable
- def each
- %w(bar baz).each{|e| yield e}
- end
- end
- svars = []
- klass.new.grep(/(b.)/) { svars << $1 }
- assert_equal(["ba", "ba"], svars)
- end
end
diff --git a/test/ruby/test_enumerator.rb b/test/ruby/test_enumerator.rb
index 11cfe69864..c823b79c6d 100644
--- a/test/ruby/test_enumerator.rb
+++ b/test/ruby/test_enumerator.rb
@@ -127,16 +127,6 @@ class TestEnumerator < Test::Unit::TestCase
assert_equal([[1,5],[2,6],[3,7]], @obj.to_enum(:foo, 1, 2, 3).with_index(5).to_a)
end
- def test_with_index_under_gc_compact_stress
- EnvUtil.under_gc_compact_stress do
- assert_equal([[1, 0], [2, 1], [3, 2]], @obj.to_enum(:foo, 1, 2, 3).with_index.to_a)
- assert_equal([[1, 5], [2, 6], [3, 7]], @obj.to_enum(:foo, 1, 2, 3).with_index(5).to_a)
-
- s = 1 << (8 * 1.size - 2)
- assert_equal([[1, s], [2, s + 1], [3, s + 2]], @obj.to_enum(:foo, 1, 2, 3).with_index(s).to_a)
- end
- end
-
def test_with_index_large_offset
bug8010 = '[ruby-dev:47131] [Bug #8010]'
s = 1 << (8*1.size-2)
@@ -254,26 +244,6 @@ class TestEnumerator < Test::Unit::TestCase
assert_equal(res, exc.result)
end
- def test_stopiteration_rescue
- e = [1].each
- res = e.each {}
- e.next
- exc0 = assert_raise(StopIteration) { e.peek }
- assert_include(exc0.backtrace.first, "test_enumerator.rb:#{__LINE__-1}:")
- assert_nil(exc0.cause)
- assert_equal(res, exc0.result)
-
- exc1 = assert_raise(StopIteration) { e.next }
- assert_include(exc1.backtrace.first, "test_enumerator.rb:#{__LINE__-1}:")
- assert_same(exc0, exc1.cause)
- assert_equal(res, exc1.result)
-
- exc2 = assert_raise(StopIteration) { e.next }
- assert_include(exc2.backtrace.first, "test_enumerator.rb:#{__LINE__-1}:")
- assert_same(exc0, exc2.cause)
- assert_equal(res, exc2.result)
- end
-
def test_next_values
o = Object.new
def o.each
@@ -862,20 +832,6 @@ class TestEnumerator < Test::Unit::TestCase
assert_equal(33, chain.next)
end
- def test_lazy_chain_under_gc_compact_stress
- EnvUtil.under_gc_compact_stress do
- ea = (10..).lazy.select(&:even?).take(10)
- ed = (20..).lazy.select(&:odd?)
- chain = (ea + ed).select{|x| x % 3 == 0}
- assert_equal(12, chain.next)
- assert_equal(18, chain.next)
- assert_equal(24, chain.next)
- assert_equal(21, chain.next)
- assert_equal(27, chain.next)
- assert_equal(33, chain.next)
- end
- end
-
def test_chain_undef_methods
chain = [1].to_enum + [2].to_enum
meths = (chain.methods & [:feed, :next, :next_values, :peek, :peek_values])
@@ -950,96 +906,4 @@ class TestEnumerator < Test::Unit::TestCase
e.chain.each(&->{})
assert_equal(true, e.is_lambda)
end
-
- def test_product
- ##
- ## Enumerator::Product
- ##
-
- # 0-dimensional
- e = Enumerator::Product.new
- assert_instance_of(Enumerator::Product, e)
- assert_kind_of(Enumerator, e)
- assert_equal(1, e.size)
- elts = []
- e.each { |x| elts << x }
- assert_equal [[]], elts
- assert_equal elts, e.to_a
- heads = []
- e.each { |x,| heads << x }
- assert_equal [nil], heads
-
- # 1-dimensional
- e = Enumerator::Product.new(1..3)
- assert_instance_of(Enumerator::Product, e)
- assert_kind_of(Enumerator, e)
- assert_equal(3, e.size)
- elts = []
- e.each { |x| elts << x }
- assert_equal [[1], [2], [3]], elts
- assert_equal elts, e.to_a
-
- # 2-dimensional
- e = Enumerator::Product.new(1..3, %w[a b])
- assert_instance_of(Enumerator::Product, e)
- assert_kind_of(Enumerator, e)
- assert_equal(3 * 2, e.size)
- elts = []
- e.each { |x| elts << x }
- assert_equal [[1, "a"], [1, "b"], [2, "a"], [2, "b"], [3, "a"], [3, "b"]], elts
- assert_equal elts, e.to_a
- heads = []
- e.each { |x,| heads << x }
- assert_equal [1, 1, 2, 2, 3, 3], heads
-
- # Reject keyword arguments
- assert_raise(ArgumentError) {
- Enumerator::Product.new(1..3, foo: 1, bar: 2)
- }
-
- ##
- ## Enumerator.product
- ##
-
- # without a block
- e = Enumerator.product(1..3, %w[a b])
- assert_instance_of(Enumerator::Product, e)
-
- # with a block
- elts = []
- ret = Enumerator.product(1..3) { |x| elts << x }
- assert_equal(nil, ret)
- assert_equal [[1], [2], [3]], elts
- assert_equal elts, Enumerator.product(1..3).to_a
-
- # an infinite enumerator and a finite enumerable
- e = Enumerator.product(1.., 'a'..'c')
- assert_equal(Float::INFINITY, e.size)
- assert_equal [[1, "a"], [1, "b"], [1, "c"], [2, "a"]], e.take(4)
-
- # an infinite enumerator and an unknown enumerator
- e = Enumerator.product(1.., Enumerator.new { |y| y << 'a' << 'b' })
- assert_equal(Float::INFINITY, e.size)
- assert_equal [[1, "a"], [1, "b"], [2, "a"], [2, "b"]], e.take(4)
-
- # an infinite enumerator and an unknown enumerator
- e = Enumerator.product(1..3, Enumerator.new { |y| y << 'a' << 'b' })
- assert_equal(nil, e.size)
- assert_equal [[1, "a"], [1, "b"], [2, "a"], [2, "b"]], e.take(4)
-
- # Reject keyword arguments
- assert_raise(ArgumentError) {
- Enumerator.product(1..3, foo: 1, bar: 2)
- }
- end
-
- def test_freeze
- e = 3.times.freeze
- assert_raise(FrozenError) { e.next }
- assert_raise(FrozenError) { e.next_values }
- assert_raise(FrozenError) { e.peek }
- assert_raise(FrozenError) { e.peek_values }
- assert_raise(FrozenError) { e.feed 1 }
- assert_raise(FrozenError) { e.rewind }
- end
end
diff --git a/test/ruby/test_env.rb b/test/ruby/test_env.rb
index cdadeac148..87ccd5102b 100644
--- a/test/ruby/test_env.rb
+++ b/test/ruby/test_env.rb
@@ -69,20 +69,25 @@ class TestEnv < Test::Unit::TestCase
end
def test_clone
- message = /Cannot clone ENV/
- assert_raise_with_message(TypeError, message) {
+ warning = /ENV\.clone is deprecated; use ENV\.to_h instead/
+ clone = assert_deprecated_warning(warning) {
ENV.clone
}
- assert_raise_with_message(TypeError, message) {
+ assert_same(ENV, clone)
+
+ clone = assert_deprecated_warning(warning) {
ENV.clone(freeze: false)
}
- assert_raise_with_message(TypeError, message) {
+ assert_same(ENV, clone)
+
+ clone = assert_deprecated_warning(warning) {
ENV.clone(freeze: nil)
}
- assert_raise_with_message(TypeError, message) {
+ assert_same(ENV, clone)
+
+ assert_raise(TypeError) {
ENV.clone(freeze: true)
}
-
assert_raise(ArgumentError) {
ENV.clone(freeze: 1)
}
@@ -489,20 +494,12 @@ class TestEnv < Test::Unit::TestCase
ENV["baz"] = "qux"
ENV.update({"baz"=>"quux","a"=>"b"})
check(ENV.to_hash.to_a, [%w(foo bar), %w(baz quux), %w(a b)])
- ENV.update
- check(ENV.to_hash.to_a, [%w(foo bar), %w(baz quux), %w(a b)])
- ENV.update({"foo"=>"zot"}, {"c"=>"d"})
- check(ENV.to_hash.to_a, [%w(foo zot), %w(baz quux), %w(a b), %w(c d)])
ENV.clear
ENV["foo"] = "bar"
ENV["baz"] = "qux"
ENV.update({"baz"=>"quux","a"=>"b"}) {|k, v1, v2| k + "_" + v1 + "_" + v2 }
check(ENV.to_hash.to_a, [%w(foo bar), %w(baz baz_qux_quux), %w(a b)])
- ENV.update {|k, v1, v2| k + "_" + v1 + "_" + v2 }
- check(ENV.to_hash.to_a, [%w(foo bar), %w(baz baz_qux_quux), %w(a b)])
- ENV.update({"foo"=>"zot"}, {"c"=>"d"}) {|k, v1, v2| k + "_" + v1 + "_" + v2 }
- check(ENV.to_hash.to_a, [%w(foo foo_bar_zot), %w(baz baz_qux_quux), %w(a b), %w(c d)])
end
def test_huge_value
@@ -683,6 +680,37 @@ class TestEnv < Test::Unit::TestCase
end;
end
+ def test_clone_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ original_warning_state = Warning[:deprecated]
+ Warning[:deprecated] = false
+
+ begin
+ Ractor.yield ENV.clone.object_id
+ Ractor.yield ENV.clone(freeze: false).object_id
+ Ractor.yield ENV.clone(freeze: nil).object_id
+
+ #{str_for_yielding_exception_class("ENV.clone(freeze: true)")}
+ #{str_for_yielding_exception_class("ENV.clone(freeze: 1)")}
+ #{str_for_yielding_exception_class("ENV.clone(foo: false)")}
+ #{str_for_yielding_exception_class("ENV.clone(1)")}
+ #{str_for_yielding_exception_class("ENV.clone(1, foo: false)")}
+
+ ensure
+ Warning[:deprecated] = original_warning_state
+ end
+ end
+ assert_equal(ENV.object_id, r.take)
+ assert_equal(ENV.object_id, r.take)
+ assert_equal(ENV.object_id, r.take)
+ #{str_for_assert_raise_on_yielded_exception_class(TypeError, "r")}
+ 4.times do
+ #{str_for_assert_raise_on_yielded_exception_class(ArgumentError, "r")}
+ end
+ end;
+ end
+
def test_has_value_in_ractor
assert_ractor(<<-"end;")
r = Ractor.new do
diff --git a/test/ruby/test_eval.rb b/test/ruby/test_eval.rb
index 082d1dc03c..d55977c986 100644
--- a/test/ruby/test_eval.rb
+++ b/test/ruby/test_eval.rb
@@ -488,9 +488,6 @@ class TestEval < Test::Unit::TestCase
end
end
assert_equal(feature6609, feature6609_method)
- ensure
- Object.undef_method(:feature6609_block) rescue nil
- Object.undef_method(:feature6609_method) rescue nil
end
def test_eval_using_integer_as_binding
@@ -547,8 +544,8 @@ class TestEval < Test::Unit::TestCase
end
def test_eval_location_binding
- assert_equal(["(eval at #{__FILE__}:#{__LINE__})", 1], eval("[__FILE__, __LINE__]", nil))
- assert_equal(["(eval at #{__FILE__}:#{__LINE__})", 1], eval("[__FILE__, __LINE__]", binding))
+ assert_equal(['(eval)', 1], eval("[__FILE__, __LINE__]", nil))
+ assert_equal(['(eval)', 1], eval("[__FILE__, __LINE__]", binding))
assert_equal(['foo', 1], eval("[__FILE__, __LINE__]", nil, 'foo'))
assert_equal(['foo', 1], eval("[__FILE__, __LINE__]", binding, 'foo'))
assert_equal(['foo', 2], eval("[__FILE__, __LINE__]", nil, 'foo', 2))
diff --git a/test/ruby/test_exception.rb b/test/ruby/test_exception.rb
index 07b39d1217..ffca877f1e 100644
--- a/test/ruby/test_exception.rb
+++ b/test/ruby/test_exception.rb
@@ -265,7 +265,7 @@ class TestException < Test::Unit::TestCase
v = assert_throw(:extdep, bug18562) do
require t.path
- rescue rescue_all
+ rescue rescue_all => e
assert(false, "should not reach here")
end
@@ -444,7 +444,7 @@ class TestException < Test::Unit::TestCase
end
def test_thread_signal_location
- # pend('TODO: a known bug [Bug #14474]')
+ skip
_, stderr, _ = EnvUtil.invoke_ruby(%w"--disable-gems -d", <<-RUBY, false, true)
Thread.start do
Thread.current.report_on_exception = false
@@ -478,12 +478,6 @@ end.join
def to_s; ""; end
end
assert_equal(e.inspect, e.new.inspect)
-
- # https://bugs.ruby-lang.org/issues/18170#note-13
- assert_equal('#<Exception:"foo\nbar">', Exception.new("foo\nbar").inspect)
- assert_equal('#<Exception: foo bar>', Exception.new("foo bar").inspect)
- assert_equal('#<Exception: foo\bar>', Exception.new("foo\\bar").inspect)
- assert_equal('#<Exception: "foo\nbar">', Exception.new('"foo\nbar"').inspect)
end
def test_to_s
@@ -588,7 +582,7 @@ end.join
end
def test_ensure_after_nomemoryerror
- omit "Forcing NoMemoryError causes problems in some environments"
+ skip "Forcing NoMemoryError causes problems in some environments"
assert_separately([], "$_ = 'a' * 1_000_000_000_000_000_000")
rescue NoMemoryError
assert_raise(NoMemoryError) do
@@ -685,7 +679,7 @@ end.join
def test_machine_stackoverflow
bug9109 = '[ruby-dev:47804] [Bug #9109]'
- assert_separately([], <<-SRC)
+ assert_separately(%w[--disable-gem], <<-SRC)
assert_raise(SystemStackError, #{bug9109.dump}) {
h = {a: ->{h[:a].call}}
h[:a].call
@@ -696,7 +690,7 @@ end.join
def test_machine_stackoverflow_by_define_method
bug9454 = '[ruby-core:60113] [Bug #9454]'
- assert_separately([], <<-SRC)
+ assert_separately(%w[--disable-gem], <<-SRC)
assert_raise(SystemStackError, #{bug9454.dump}) {
define_method(:foo) {self.foo}
self.foo
@@ -813,7 +807,6 @@ end.join
cause = ArgumentError.new("foobar")
e = assert_raise(RuntimeError) {raise msg, cause: cause}
assert_same(cause, e.cause)
- assert_raise(TypeError) {raise msg, {cause: cause}}
end
def test_cause_with_no_arguments
@@ -998,12 +991,11 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status|
end
assert_not_nil(e)
assert_include(e.message, "\0")
- # Disabled by [Feature #18367]
- #assert_in_out_err([], src, [], [], *args, **opts) do |_, err,|
- # err.each do |e|
- # assert_not_include(e, "\0")
- # end
- #end
+ assert_in_out_err([], src, [], [], *args, **opts) do |_, err,|
+ err.each do |e|
+ assert_not_include(e, "\0")
+ end
+ end
e
end
@@ -1059,7 +1051,7 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status|
warning << [str, category]
end
else
- define_method(:warn) do |str, category: nil|
+ define_method(:warn) do |str|
warning << str
end
end
@@ -1093,17 +1085,25 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status|
end
def test_warn_deprecated_backwards_compatibility_category
- omit "no method to test"
-
- warning = capture_warning_warn { }
+ warning = capture_warning_warn { Dir.exists?("non-existent") }
assert_match(/deprecated/, warning[0])
end
def test_warn_deprecated_category
- omit "no method to test"
+ warning = capture_warning_warn(category: true) { Dir.exists?("non-existent") }
+
+ assert_equal :deprecated, warning[0][1]
+ end
+
+ def test_warn_deprecated_to_remove_backwards_compatibility_category
+ warning = capture_warning_warn { Object.new.tainted? }
+
+ assert_match(/deprecated/, warning[0])
+ end
- warning = capture_warning_warn(category: true) { }
+ def test_warn_deprecated_to_remove_category
+ warning = capture_warning_warn(category: true) { Object.new.tainted? }
assert_equal :deprecated, warning[0][1]
end
@@ -1266,7 +1266,7 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status|
begin;
class Bug < RuntimeError
def backtrace
- File.readlines(IO::NULL)
+ IO.readlines(IO::NULL)
end
end
bug = Bug.new '[ruby-core:85939] [Bug #14577]'
@@ -1310,7 +1310,7 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status|
def test_backtrace_in_eval
bug = '[ruby-core:84434] [Bug #14229]'
- assert_in_out_err(['-e', 'eval("raise")'], "", [], /^\(eval at .*\):1:/, bug)
+ assert_in_out_err(['-e', 'eval("raise")'], "", [], /^\(eval\):1:/, bug)
end
def test_full_message
@@ -1440,99 +1440,4 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status|
end
end;
end
-
- def test_detailed_message
- e = RuntimeError.new("message")
- assert_equal("message (RuntimeError)", e.detailed_message)
- assert_equal("\e[1mmessage (\e[1;4mRuntimeError\e[m\e[1m)\e[m", e.detailed_message(highlight: true))
-
- e = RuntimeError.new("foo\nbar\nbaz")
- assert_equal("foo (RuntimeError)\nbar\nbaz", e.detailed_message)
- assert_equal("\e[1mfoo (\e[1;4mRuntimeError\e[m\e[1m)\e[m\n\e[1mbar\e[m\n\e[1mbaz\e[m", e.detailed_message(highlight: true))
-
- e = RuntimeError.new("")
- assert_equal("unhandled exception", e.detailed_message)
- assert_equal("\e[1;4munhandled exception\e[m", e.detailed_message(highlight: true))
-
- e = RuntimeError.new
- assert_equal("RuntimeError (RuntimeError)", e.detailed_message)
- assert_equal("\e[1mRuntimeError (\e[1;4mRuntimeError\e[m\e[1m)\e[m", e.detailed_message(highlight: true))
- end
-
- def test_full_message_with_custom_detailed_message
- e = RuntimeError.new("message")
- opt_ = nil
- e.define_singleton_method(:detailed_message) do |**opt|
- opt_ = opt
- "BOO!"
- end
- assert_match("BOO!", e.full_message.lines.first)
- assert_equal({ highlight: Exception.to_tty? }, opt_)
- end
-
- def test_full_message_with_encoding
- message = "\u{dc}bersicht"
- begin
- begin
- raise message
- rescue => e
- raise "\n#{e.message}"
- end
- rescue => e
- end
- assert_include(e.full_message, message)
- end
-
- def test_syntax_error_detailed_message
- Dir.mktmpdir do |dir|
- File.write(File.join(dir, "detail.rb"), "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- class SyntaxError
- def detailed_message(**)
- Thread.new {}.join
- "<#{super}>\n""<#{File.basename(__FILE__)}>"
- rescue ThreadError => e
- e.message
- end
- end
- end;
- pattern = /^<detail\.rb>/
- assert_in_out_err(%W[-r#{dir}/detail -], "1+", [], pattern)
-
- File.write(File.join(dir, "main.rb"), "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- 1 +
- end;
- assert_in_out_err(%W[-r#{dir}/detail #{dir}/main.rb]) do |stdout, stderr,|
- assert_empty(stdout)
- assert_not_empty(stderr.grep(pattern))
- error, = stderr.grep(/unexpected end-of-input/)
- assert_not_nil(error)
- assert_match(/<.*unexpected end-of-input.*>/, error)
- end
- end
- end
-
- def test_syntax_error_path
- e = assert_raise(SyntaxError) {
- eval("1+", nil, "test_syntax_error_path.rb")
- }
- assert_equal("test_syntax_error_path.rb", e.path)
-
- Dir.mktmpdir do |dir|
- lib = File.join(dir, "syntax_error-path.rb")
- File.write(lib, "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- class SyntaxError
- def detailed_message(**)
- STDERR.puts "\n""path=#{path}\n"
- super
- end
- end
- end;
- main = File.join(dir, "syntax_error.rb")
- File.write(main, "1+\n")
- assert_in_out_err(%W[-r#{lib} #{main}], "", [], [:*, "\n""path=#{main}\n", :*])
- end
- end
end
diff --git a/test/ruby/test_fiber.rb b/test/ruby/test_fiber.rb
index cb6e846bc6..e4b7322bd9 100644
--- a/test/ruby/test_fiber.rb
+++ b/test/ruby/test_fiber.rb
@@ -34,7 +34,7 @@ class TestFiber < Test::Unit::TestCase
end
def test_many_fibers
- omit 'This is unstable on GitHub Actions --jit-wait. TODO: debug it' if defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled?
+ skip 'This is unstable on GitHub Actions --jit-wait. TODO: debug it' if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?
max = 1000
assert_equal(max, max.times{
Fiber.new{}
@@ -381,7 +381,7 @@ class TestFiber < Test::Unit::TestCase
def test_fork_from_fiber
- omit 'fork not supported' unless Process.respond_to?(:fork)
+ skip 'fork not supported' unless Process.respond_to?(:fork)
pid = nil
bug5700 = '[ruby-core:41456]'
assert_nothing_raised(bug5700) do
diff --git a/test/ruby/test_file.rb b/test/ruby/test_file.rb
index 409d21fc4e..d570b6f6fb 100644
--- a/test/ruby/test_file.rb
+++ b/test/ruby/test_file.rb
@@ -273,7 +273,7 @@ class TestFile < Test::Unit::TestCase
begin
File.symlink(tst, a)
rescue Errno::EACCES, Errno::EPERM
- omit "need privilege"
+ skip "need privilege"
end
assert_equal(File.join(realdir, tst), File.realpath(a))
File.unlink(a)
@@ -317,7 +317,7 @@ class TestFile < Test::Unit::TestCase
Dir.mktmpdir('rubytest-realpath') {|tmpdir|
Dir.chdir(tmpdir) do
Dir.mkdir('foo')
- omit "cannot run mklink" unless system('mklink /j bar foo > nul')
+ skip "cannot run mklink" unless system('mklink /j bar foo > nul')
assert_equal(File.realpath('foo'), File.realpath('bar'))
end
}
@@ -460,48 +460,6 @@ class TestFile < Test::Unit::TestCase
end
end
- def test_file_open_newline_option
- Dir.mktmpdir(__method__.to_s) do |tmpdir|
- path = File.join(tmpdir, "foo")
- test = lambda do |newline|
- File.open(path, "wt", newline: newline) do |f|
- f.write "a\n"
- f.puts "b"
- end
- File.binread(path)
- end
- assert_equal("a\nb\n", test.(:lf))
- assert_equal("a\nb\n", test.(:universal))
- assert_equal("a\r\nb\r\n", test.(:crlf))
- assert_equal("a\rb\r", test.(:cr))
-
- test = lambda do |newline|
- File.open(path, "rt", newline: newline) do |f|
- f.read
- end
- end
-
- File.binwrite(path, "a\nb\n")
- assert_equal("a\nb\n", test.(:lf))
- assert_equal("a\nb\n", test.(:universal))
- assert_equal("a\nb\n", test.(:crlf))
- assert_equal("a\nb\n", test.(:cr))
-
- File.binwrite(path, "a\r\nb\r\n")
- assert_equal("a\r\nb\r\n", test.(:lf))
- assert_equal("a\nb\n", test.(:universal))
- # Work on both Windows and non-Windows
- assert_include(["a\r\nb\r\n", "a\nb\n"], test.(:crlf))
- assert_equal("a\r\nb\r\n", test.(:cr))
-
- File.binwrite(path, "a\rb\r")
- assert_equal("a\rb\r", test.(:lf))
- assert_equal("a\nb\n", test.(:universal))
- assert_equal("a\rb\r", test.(:crlf))
- assert_equal("a\rb\r", test.(:cr))
- end
- end
-
def test_open_nul
Dir.mktmpdir(__method__.to_s) do |tmpdir|
path = File.join(tmpdir, "foo")
@@ -517,17 +475,17 @@ class TestFile < Test::Unit::TestCase
begin
io = File.open(tmpdir, File::RDWR | File::TMPFILE)
rescue Errno::EINVAL
- omit 'O_TMPFILE not supported (EINVAL)'
+ skip 'O_TMPFILE not supported (EINVAL)'
rescue Errno::EISDIR
- omit 'O_TMPFILE not supported (EISDIR)'
+ skip 'O_TMPFILE not supported (EISDIR)'
rescue Errno::EOPNOTSUPP
- omit 'O_TMPFILE not supported (EOPNOTSUPP)'
+ skip 'O_TMPFILE not supported (EOPNOTSUPP)'
end
io.write "foo"
io.flush
assert_equal 3, io.size
- assert_nil io.path
+ assert_raise(IOError) { io.path }
ensure
io&.close
end
diff --git a/test/ruby/test_file_exhaustive.rb b/test/ruby/test_file_exhaustive.rb
index fbb18f07f9..a960ef0d74 100644
--- a/test/ruby/test_file_exhaustive.rb
+++ b/test/ruby/test_file_exhaustive.rb
@@ -638,7 +638,7 @@ class TestFileExhaustive < Test::Unit::TestCase
end
def test_birthtime
- omit if RUBY_PLATFORM =~ /android/
+ skip if RUBY_PLATFORM =~ /android/
[regular_file, utf8_file].each do |file|
t1 = File.birthtime(file)
t2 = File.open(file) {|f| f.birthtime}
@@ -649,7 +649,7 @@ class TestFileExhaustive < Test::Unit::TestCase
# ignore unsupporting filesystems
rescue Errno::EPERM
# Docker prohibits statx syscall by the default.
- omit("statx(2) is prohibited by seccomp")
+ skip("statx(2) is prohibited by seccomp")
end
assert_raise(Errno::ENOENT) { File.birthtime(nofile) }
end if File.respond_to?(:birthtime)
@@ -771,7 +771,7 @@ class TestFileExhaustive < Test::Unit::TestCase
def test_readlink_junction
base = File.basename(nofile)
err = IO.popen(%W"cmd.exe /c mklink /j #{base} .", chdir: @dir, err: %i[child out], &:read)
- omit err unless $?.success?
+ skip err unless $?.success?
assert_equal(@dir, File.readlink(nofile))
end
@@ -870,10 +870,9 @@ class TestFileExhaustive < Test::Unit::TestCase
bug9934 = '[ruby-core:63114] [Bug #9934]'
require "objspace"
path = File.expand_path("/foo")
- assert_operator(ObjectSpace.memsize_of(path), :<=, path.bytesize + GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE], bug9934)
+ assert_operator(ObjectSpace.memsize_of(path), :<=, path.bytesize + GC::INTERNAL_CONSTANTS[:RVALUE_SIZE], bug9934)
path = File.expand_path("/a"*25)
- assert_operator(ObjectSpace.memsize_of(path), :<=,
- (path.bytesize + 1) * 2 + GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE], bug9934)
+ assert_equal(path.bytesize+1 + GC::INTERNAL_CONSTANTS[:RVALUE_SIZE], ObjectSpace.memsize_of(path), bug9934)
end
def test_expand_path_encoding
@@ -1118,7 +1117,7 @@ class TestFileExhaustive < Test::Unit::TestCase
def test_expand_path_for_existent_username
user = ENV['USER']
- omit "ENV['USER'] is not set" unless user
+ skip "ENV['USER'] is not set" unless user
assert_equal(ENV['HOME'], File.expand_path("~#{user}"))
end unless DRIVE
@@ -1407,8 +1406,6 @@ class TestFileExhaustive < Test::Unit::TestCase
end
def test_flock_exclusive
- omit "[Bug #18613]" if /freebsd/ =~ RUBY_PLATFORM
-
timeout = EnvUtil.apply_timeout_scale(0.1).to_s
File.open(regular_file, "r+") do |f|
f.flock(File::LOCK_EX)
@@ -1438,8 +1435,6 @@ class TestFileExhaustive < Test::Unit::TestCase
end
def test_flock_shared
- omit "[Bug #18613]" if /freebsd/ =~ RUBY_PLATFORM
-
timeout = EnvUtil.apply_timeout_scale(0.1).to_s
File.open(regular_file, "r+") do |f|
f.flock(File::LOCK_SH)
@@ -1517,32 +1512,29 @@ class TestFileExhaustive < Test::Unit::TestCase
assert_equal(File.zero?(f), test(?z, f), f)
stat = File.stat(f)
- unless stat.chardev?
- # null device may be accessed by other processes
- assert_equal(stat.atime, File.atime(f), f)
- assert_equal(stat.ctime, File.ctime(f), f)
- assert_equal(stat.mtime, File.mtime(f), f)
- end
- assert_bool_equal(stat.blockdev?, File.blockdev?(f), f)
- assert_bool_equal(stat.chardev?, File.chardev?(f), f)
- assert_bool_equal(stat.directory?, File.directory?(f), f)
- assert_bool_equal(stat.file?, File.file?(f), f)
- assert_bool_equal(stat.setgid?, File.setgid?(f), f)
- assert_bool_equal(stat.grpowned?, File.grpowned?(f), f)
- assert_bool_equal(stat.sticky?, File.sticky?(f), f)
- assert_bool_equal(File.lstat(f).symlink?, File.symlink?(f), f)
- assert_bool_equal(stat.owned?, File.owned?(f), f)
- assert_bool_equal(stat.pipe?, File.pipe?(f), f)
- assert_bool_equal(stat.readable?, File.readable?(f), f)
- assert_bool_equal(stat.readable_real?, File.readable_real?(f), f)
+ assert_equal(stat.atime, File.atime(f), f)
+ assert_equal(stat.ctime, File.ctime(f), f)
+ assert_equal(stat.mtime, File.mtime(f), f)
+ assert_equal(stat.blockdev?, File.blockdev?(f), f)
+ assert_equal(stat.chardev?, File.chardev?(f), f)
+ assert_equal(stat.directory?, File.directory?(f), f)
+ assert_equal(stat.file?, File.file?(f), f)
+ assert_equal(stat.setgid?, File.setgid?(f), f)
+ assert_equal(stat.grpowned?, File.grpowned?(f), f)
+ assert_equal(stat.sticky?, File.sticky?(f), f)
+ assert_equal(File.lstat(f).symlink?, File.symlink?(f), f)
+ assert_equal(stat.owned?, File.owned?(f), f)
+ assert_equal(stat.pipe?, File.pipe?(f), f)
+ assert_equal(stat.readable?, File.readable?(f), f)
+ assert_equal(stat.readable_real?, File.readable_real?(f), f)
assert_equal(stat.size?, File.size?(f), f)
- assert_bool_equal(stat.socket?, File.socket?(f), f)
- assert_bool_equal(stat.setuid?, File.setuid?(f), f)
- assert_bool_equal(stat.writable?, File.writable?(f), f)
- assert_bool_equal(stat.writable_real?, File.writable_real?(f), f)
- assert_bool_equal(stat.executable?, File.executable?(f), f)
- assert_bool_equal(stat.executable_real?, File.executable_real?(f), f)
- assert_bool_equal(stat.zero?, File.zero?(f), f)
+ assert_equal(stat.socket?, File.socket?(f), f)
+ assert_equal(stat.setuid?, File.setuid?(f), f)
+ assert_equal(stat.writable?, File.writable?(f), f)
+ assert_equal(stat.writable_real?, File.writable_real?(f), f)
+ assert_equal(stat.executable?, File.executable?(f), f)
+ assert_equal(stat.executable_real?, File.executable_real?(f), f)
+ assert_equal(stat.zero?, File.zero?(f), f)
end
assert_equal(false, test(?-, @dir, fn1))
assert_equal(true, test(?-, fn1, fn1))
@@ -1795,8 +1787,4 @@ class TestFileExhaustive < Test::Unit::TestCase
dir = File.expand_path("/bar")
assert_equal(File.join(dir, "~foo"), File.absolute_path("~foo", dir))
end
-
- def assert_bool_equal(expected, result, *messages)
- assert_equal(expected, true & result, *messages)
- end
end
diff --git a/test/ruby/test_float.rb b/test/ruby/test_float.rb
index b91b904d1e..57a46fce92 100644
--- a/test/ruby/test_float.rb
+++ b/test/ruby/test_float.rb
@@ -141,9 +141,6 @@ class TestFloat < Test::Unit::TestCase
assert_raise(ArgumentError){Float("1__1")}
assert_raise(ArgumentError){Float("1.")}
assert_raise(ArgumentError){Float("1.e+00")}
- assert_raise(ArgumentError){Float("0x.1")}
- assert_raise(ArgumentError){Float("0x1.")}
- assert_raise(ArgumentError){Float("0x1.0")}
assert_raise(ArgumentError){Float("0x1.p+0")}
# add expected behaviour here.
assert_equal(10, Float("1_0"))
@@ -227,12 +224,6 @@ class TestFloat < Test::Unit::TestCase
assert_equal(-3.5, (-11.5).remainder(-4))
assert_predicate(Float::NAN.remainder(4), :nan?)
assert_predicate(4.remainder(Float::NAN), :nan?)
-
- ten = Object.new
- def ten.coerce(other)
- [other, 10]
- end
- assert_equal(4, 14.0.remainder(ten))
end
def test_to_s
@@ -492,17 +483,6 @@ class TestFloat < Test::Unit::TestCase
assert_equal(-1.26, -1.255.round(2))
end
- def test_round_half_even_with_precision
- assert_equal(767573.18759, 767573.1875850001.round(5, half: :even))
- assert_equal(767573.18758, 767573.187585.round(5, half: :even))
- assert_equal(767573.18758, 767573.1875849998.round(5, half: :even))
- assert_equal(767573.18758, 767573.187575.round(5, half: :even))
- assert_equal(-767573.18759, -767573.1875850001.round(5, half: :even))
- assert_equal(-767573.18758, -767573.187585.round(5, half: :even))
- assert_equal(-767573.18758, -767573.1875849998.round(5, half: :even))
- assert_equal(-767573.18758, -767573.187575.round(5, half: :even))
- end
-
def test_floor_with_precision
assert_equal(+0.0, +0.001.floor(1))
assert_equal(-0.1, -0.001.floor(1))
diff --git a/test/ruby/test_frozen.rb b/test/ruby/test_frozen.rb
deleted file mode 100644
index 2918a2afd8..0000000000
--- a/test/ruby/test_frozen.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: false
-require 'test/unit'
-
-class TestFrozen < Test::Unit::TestCase
- def test_setting_ivar_on_frozen_obj
- obj = Object.new
- obj.freeze
- assert_raise(FrozenError) { obj.instance_variable_set(:@a, 1) }
- end
-
- def test_setting_ivar_on_frozen_obj_with_ivars
- obj = Object.new
- obj.instance_variable_set(:@a, 1)
- obj.freeze
- assert_raise(FrozenError) { obj.instance_variable_set(:@b, 1) }
- end
-
- def test_setting_ivar_on_frozen_string
- str = "str"
- str.freeze
- assert_raise(FrozenError) { str.instance_variable_set(:@a, 1) }
- end
-
- def test_setting_ivar_on_frozen_string_with_ivars
- str = "str"
- str.instance_variable_set(:@a, 1)
- str.freeze
- assert_raise(FrozenError) { str.instance_variable_set(:@b, 1) }
- end
-end
diff --git a/test/ruby/test_gc.rb b/test/ruby/test_gc.rb
index 39b001c3d0..fa81bcb1ad 100644
--- a/test/ruby/test_gc.rb
+++ b/test/ruby/test_gc.rb
@@ -54,7 +54,7 @@ class TestGc < Test::Unit::TestCase
def test_start_full_mark
return unless use_rgengc?
- omit 'stress' if GC.stress
+ skip 'stress' if GC.stress
3.times { GC.start } # full mark and next time it should be minor mark
GC.start(full_mark: false)
@@ -65,7 +65,7 @@ class TestGc < Test::Unit::TestCase
end
def test_start_immediate_sweep
- omit 'stress' if GC.stress
+ skip 'stress' if GC.stress
GC.start(immediate_sweep: false)
assert_equal false, GC.latest_gc_info(:immediate_sweep)
@@ -117,7 +117,7 @@ class TestGc < Test::Unit::TestCase
end
def test_stat_single
- omit 'stress' if GC.stress
+ skip 'stress' if GC.stress
stat = GC.stat
assert_equal stat[:count], GC.stat(:count)
@@ -125,11 +125,9 @@ class TestGc < Test::Unit::TestCase
end
def test_stat_constraints
- omit 'stress' if GC.stress
+ skip 'stress' if GC.stress
stat = GC.stat
- # marking_time + sweeping_time could differ from time by 1 because they're stored in nanoseconds
- assert_in_delta stat[:time], stat[:marking_time] + stat[:sweeping_time], 1
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
assert_equal stat[:heap_available_slots], stat[:heap_live_slots] + stat[:heap_free_slots] + stat[:heap_final_slots]
@@ -141,122 +139,15 @@ class TestGc < Test::Unit::TestCase
end
end
- def test_stat_heap
- omit 'stress' if GC.stress
-
- stat_heap = {}
- stat = {}
- # Initialize to prevent GC in future calls
- GC.stat_heap(0, stat_heap)
- GC.stat(stat)
-
- GC::INTERNAL_CONSTANTS[:SIZE_POOL_COUNT].times do |i|
- begin
- reenable_gc = !GC.disable
- GC.stat_heap(i, stat_heap)
- GC.stat(stat)
- ensure
- GC.enable if reenable_gc
- end
-
- assert_equal GC::INTERNAL_CONSTANTS[:RVALUE_SIZE] * (2**i), stat_heap[:slot_size]
- assert_operator stat_heap[:heap_allocatable_pages], :<=, stat[:heap_allocatable_pages]
- assert_operator stat_heap[:heap_eden_pages], :<=, stat[:heap_eden_pages]
- assert_operator stat_heap[:heap_eden_slots], :>=, 0
- assert_operator stat_heap[:heap_tomb_pages], :<=, stat[:heap_tomb_pages]
- assert_operator stat_heap[:heap_tomb_slots], :>=, 0
- assert_operator stat_heap[:total_allocated_pages], :>=, 0
- assert_operator stat_heap[:total_freed_pages], :>=, 0
- assert_operator stat_heap[:force_major_gc_count], :>=, 0
- assert_operator stat_heap[:force_incremental_marking_finish_count], :>=, 0
- assert_operator stat_heap[:total_allocated_objects], :>=, 0
- assert_operator stat_heap[:total_freed_objects], :>=, 0
- assert_operator stat_heap[:total_freed_objects], :<=, stat_heap[:total_allocated_objects]
- end
-
- GC.stat_heap(0, stat_heap)
- assert_equal stat_heap[:slot_size], GC.stat_heap(0, :slot_size)
- assert_equal stat_heap[:slot_size], GC.stat_heap(0)[:slot_size]
-
- assert_raise(ArgumentError) { GC.stat_heap(-1) }
- assert_raise(ArgumentError) { GC.stat_heap(GC::INTERNAL_CONSTANTS[:SIZE_POOL_COUNT]) }
- end
-
- def test_stat_heap_all
- omit "flaky with RJIT, which allocates objects itself" if defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled?
- stat_heap_all = {}
- stat_heap = {}
-
- 2.times do
- GC.stat_heap(0, stat_heap)
- GC.stat_heap(nil, stat_heap_all)
- end
-
- GC::INTERNAL_CONSTANTS[:SIZE_POOL_COUNT].times do |i|
- GC.stat_heap(i, stat_heap)
-
- # Remove keys that can vary between invocations
- %i(total_allocated_objects).each do |sym|
- stat_heap[sym] = stat_heap_all[i][sym] = 0
- end
-
- assert_equal stat_heap, stat_heap_all[i]
- end
-
- assert_raise(TypeError) { GC.stat_heap(nil, :slot_size) }
- end
-
- def test_stat_heap_constraints
- omit 'stress' if GC.stress
-
- stat = GC.stat
- stat_heap = GC.stat_heap
- 2.times do
- GC.stat(stat)
- GC.stat_heap(nil, stat_heap)
- end
-
- stat_heap_sum = Hash.new(0)
- stat_heap.values.each do |hash|
- hash.each { |k, v| stat_heap_sum[k] += v }
- end
-
- assert_equal stat[:heap_allocatable_pages], stat_heap_sum[:heap_allocatable_pages]
- assert_equal stat[:heap_eden_pages], stat_heap_sum[:heap_eden_pages]
- assert_equal stat[:heap_tomb_pages], stat_heap_sum[:heap_tomb_pages]
- assert_equal stat[:heap_available_slots], stat_heap_sum[:heap_eden_slots] + stat_heap_sum[:heap_tomb_slots]
- assert_equal stat[:total_allocated_pages], stat_heap_sum[:total_allocated_pages]
- assert_equal stat[:total_freed_pages], stat_heap_sum[:total_freed_pages]
- assert_equal stat[:total_allocated_objects], stat_heap_sum[:total_allocated_objects]
- assert_equal stat[:total_freed_objects], stat_heap_sum[:total_freed_objects]
- end
-
- def test_measure_total_time
- assert_separately([], __FILE__, __LINE__, <<~RUBY)
- GC.measure_total_time = false
-
- time_before = GC.stat(:time)
-
- # Generate some garbage
- Random.new.bytes(100 * 1024 * 1024)
- GC.start
-
- time_after = GC.stat(:time)
-
- # If time measurement is disabled, the time stat should not change
- assert_equal time_before, time_after
- RUBY
- end
-
def test_latest_gc_info
- omit 'stress' if GC.stress
+ skip 'stress' if GC.stress
- assert_separately([], __FILE__, __LINE__, <<-'RUBY')
- GC.start
- count = GC.stat(:heap_free_slots) + GC.stat(:heap_allocatable_pages) * GC::INTERNAL_CONSTANTS[:HEAP_PAGE_OBJ_LIMIT]
- count.times{ "a" + "b" }
- assert_equal :newobj, GC.latest_gc_info[:gc_by]
- RUBY
+ 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]
+ count.times{ "a" + "b" }
+ assert_equal :newobj, GC.latest_gc_info[:gc_by]
+ eom
GC.latest_gc_info(h = {}) # allocate hash and rehearsal
GC.start
@@ -267,7 +158,6 @@ class TestGc < Test::Unit::TestCase
assert_equal :force, h[:major_by] if use_rgengc?
assert_equal :method, h[:gc_by]
assert_equal true, h[:immediate_sweep]
- assert_equal true, h.key?(:need_major_by)
GC.stress = true
assert_equal :force, GC.latest_gc_info[:major_by]
@@ -285,82 +175,8 @@ class TestGc < Test::Unit::TestCase
assert_raise_with_message(ArgumentError, /\u{30eb 30d3 30fc}/) {GC.latest_gc_info(:"\u{30eb 30d3 30fc}")}
end
- def test_latest_gc_info_need_major_by
- return unless use_rgengc?
- omit 'stress' if GC.stress
-
- 3.times { GC.start }
- assert_nil GC.latest_gc_info(:need_major_by)
-
- # allocate objects until need_major_by is set or major GC happens
- objects = []
- while GC.latest_gc_info(:need_major_by).nil?
- objects.append(100.times.map { '*' })
- end
-
- # We need to ensure that no GC gets ran before the call to GC.start since
- # it would trigger a major GC. Assertions could allocate objects and
- # trigger a GC so we don't run assertions until we perform the major GC.
- need_major_by = GC.latest_gc_info(:need_major_by)
- GC.start(full_mark: false) # should be upgraded to major
- major_by = GC.latest_gc_info(:major_by)
-
- assert_not_nil(need_major_by)
- assert_not_nil(major_by)
- end
-
- def test_latest_gc_info_weak_references_count
- assert_separately([], __FILE__, __LINE__, <<~RUBY)
- count = 10_000
- # Some weak references may be created, so allow some margin of error
- error_tolerance = 100
-
- # Run full GC to clear out weak references
- GC.start
- # Run full GC again to collect stats about weak references
- GC.start
-
- before_weak_references_count = GC.latest_gc_info(:weak_references_count)
- before_retained_weak_references_count = GC.latest_gc_info(:retained_weak_references_count)
-
- # Create some objects and place it in a WeakMap
- wmap = ObjectSpace::WeakMap.new
- ary = Array.new(count)
- enum = count.times
- enum.each.with_index do |i|
- obj = Object.new
- ary[i] = obj
- wmap[obj] = nil
- end
-
- # Run full GC to collect stats about weak references
- GC.start
-
- assert_operator(GC.latest_gc_info(:weak_references_count), :>=, before_weak_references_count + count - error_tolerance)
- assert_operator(GC.latest_gc_info(:retained_weak_references_count), :>=, before_retained_weak_references_count + count - error_tolerance)
- assert_operator(GC.latest_gc_info(:retained_weak_references_count), :<=, GC.latest_gc_info(:weak_references_count))
-
- before_weak_references_count = GC.latest_gc_info(:weak_references_count)
- before_retained_weak_references_count = GC.latest_gc_info(:retained_weak_references_count)
-
- ary = nil
-
- # Free ary, which should empty out the wmap
- GC.start
- # Run full GC again to collect stats about weak references
- GC.start
-
- # Sometimes the WeakMap has one element, which might be held on by registers.
- assert_operator(wmap.size, :<=, 1)
-
- assert_operator(GC.latest_gc_info(:weak_references_count), :<=, before_weak_references_count - count + error_tolerance)
- assert_operator(GC.latest_gc_info(:retained_weak_references_count), :<=, before_retained_weak_references_count - count + error_tolerance)
- assert_operator(GC.latest_gc_info(:retained_weak_references_count), :<=, GC.latest_gc_info(:weak_references_count))
- RUBY
- end
-
def test_stress_compile_send
- assert_in_out_err([], <<-EOS, [], [], "")
+ assert_in_out_err(%w[--disable-gems], <<-EOS, [], [], "")
GC.stress = true
begin
eval("A::B.c(1, 1, d: 234)")
@@ -370,7 +186,7 @@ class TestGc < Test::Unit::TestCase
end
def test_singleton_method
- assert_in_out_err([], <<-EOS, [], [], "[ruby-dev:42832]")
+ assert_in_out_err(%w[--disable-gems], <<-EOS, [], [], "[ruby-dev:42832]")
GC.stress = true
10.times do
obj = Object.new
@@ -382,7 +198,7 @@ class TestGc < Test::Unit::TestCase
end
def test_singleton_method_added
- assert_in_out_err([], <<-EOS, [], [], "[ruby-dev:44436]")
+ assert_in_out_err(%w[--disable-gems], <<-EOS, [], [], "[ruby-dev:44436]")
class BasicObject
undef singleton_method_added
def singleton_method_added(mid)
@@ -400,21 +216,22 @@ class TestGc < Test::Unit::TestCase
env = {
"RUBY_GC_HEAP_INIT_SLOTS" => "100"
}
- assert_in_out_err([env, "-W0", "-e", "exit"], "", [], [])
- assert_in_out_err([env, "-W:deprecated", "-e", "exit"], "", [],
- /The environment variable RUBY_GC_HEAP_INIT_SLOTS is deprecated; use environment variables RUBY_GC_HEAP_%d_INIT_SLOTS instead/)
+ assert_in_out_err([env, "-W0", "-e", "exit"], "", [], [], "[Bug #19284]")
- env = {}
- GC.stat_heap.keys.each do |heap|
- env["RUBY_GC_HEAP_#{heap}_INIT_SLOTS"] = "200000"
- end
- assert_normal_exit("exit", "", :child_env => env)
+ env = {
+ "RUBY_GC_MALLOC_LIMIT" => "60000000",
+ "RUBY_GC_HEAP_INIT_SLOTS" => "100000"
+ }
+ assert_normal_exit("exit", "[ruby-core:39777]", :child_env => env)
- env = {}
- GC.stat_heap.keys.each do |heap|
- env["RUBY_GC_HEAP_#{heap}_INIT_SLOTS"] = "0"
- end
- assert_normal_exit("exit", "", :child_env => env)
+ env = {
+ "RUBYOPT" => "",
+ "RUBY_GC_HEAP_INIT_SLOTS" => "100000"
+ }
+ assert_in_out_err([env, "-e", "exit"], "", [], [], "[ruby-core:39795]")
+ assert_in_out_err([env, "-W0", "-e", "exit"], "", [], [], "[ruby-core:39795]")
+ assert_in_out_err([env, "-W1", "-e", "exit"], "", [], [], "[ruby-core:39795]")
+ assert_in_out_err([env, "-w", "-e", "exit"], "", [], /RUBY_GC_HEAP_INIT_SLOTS=100000/, "[ruby-core:39795]")
env = {
"RUBY_GC_HEAP_GROWTH_FACTOR" => "2.0",
@@ -424,13 +241,16 @@ class TestGc < Test::Unit::TestCase
assert_in_out_err([env, "-w", "-e", "exit"], "", [], /RUBY_GC_HEAP_GROWTH_FACTOR=2.0/, "")
assert_in_out_err([env, "-w", "-e", "exit"], "", [], /RUBY_GC_HEAP_GROWTH_MAX_SLOTS=10000/, "[ruby-core:57928]")
- if use_rgengc?
- env = {
- "RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR" => "0.4",
- }
- # always full GC when RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR < 1.0
- assert_in_out_err([env, "-e", "GC.start; 1000_000.times{Object.new}; p(GC.stat[:minor_gc_count] < GC.stat[:major_gc_count])"], "", ['true'], //, "")
- end
+ env = {
+ "RUBY_GC_HEAP_INIT_SLOTS" => "100000",
+ "RUBY_GC_HEAP_FREE_SLOTS" => "10000",
+ "RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR" => "0.9",
+ }
+ assert_normal_exit("exit", "", :child_env => env)
+ assert_in_out_err([env, "-w", "-e", "exit"], "", [], /RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR=0\.9/, "")
+
+ # always full GC when RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR < 1.0
+ assert_in_out_err([env, "-e", "1000_000.times{Object.new}; p(GC.stat[:minor_gc_count] < GC.stat[:major_gc_count])"], "", ['true'], //, "") if use_rgengc?
env = {
"RUBY_GC_MALLOC_LIMIT" => "60000000",
@@ -453,127 +273,6 @@ class TestGc < Test::Unit::TestCase
assert_in_out_err([env, "-w", "-e", "exit"], "", [], /RUBY_GC_OLDMALLOC_LIMIT_MAX=16000000/, "")
assert_in_out_err([env, "-w", "-e", "exit"], "", [], /RUBY_GC_OLDMALLOC_LIMIT_GROWTH_FACTOR=2.0/, "")
end
-
- ["0.01", "0.1", "1.0"].each do |i|
- env = {"RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR" => "0", "RUBY_GC_HEAP_REMEMBERED_WB_UNPROTECTED_OBJECTS_LIMIT_RATIO" => i}
- assert_separately([env, "-W0"], __FILE__, __LINE__, <<~RUBY)
- GC.disable
- GC.start
- assert_equal((GC.stat[:old_objects] * #{i}).to_i, GC.stat[:remembered_wb_unprotected_objects_limit])
- RUBY
- end
- end
-
- def test_gc_parameter_init_slots
- assert_separately([], __FILE__, __LINE__, <<~RUBY)
- # Constant from gc.c.
- GC_HEAP_INIT_SLOTS = 10_000
- GC.stat_heap.each do |_, s|
- multiple = s[:slot_size] / (GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE] + GC::INTERNAL_CONSTANTS[:RVALUE_OVERHEAD])
- # Allocatable pages are assumed to have lost 1 slot due to alignment.
- slots_per_page = (GC::INTERNAL_CONSTANTS[:HEAP_PAGE_OBJ_LIMIT] / multiple) - 1
-
- total_slots = s[:heap_eden_slots] + s[:heap_allocatable_pages] * slots_per_page
- assert_operator(total_slots, :>=, GC_HEAP_INIT_SLOTS, s)
- end
- RUBY
-
- env = {}
- # Make the heap big enough to ensure the heap never needs to grow.
- sizes = GC.stat_heap.keys.reverse.map { |i| (i + 1) * 100_000 }
- GC.stat_heap.keys.each do |heap|
- env["RUBY_GC_HEAP_#{heap}_INIT_SLOTS"] = sizes[heap].to_s
- end
- assert_separately([env, "-W0"], __FILE__, __LINE__, <<~RUBY)
- SIZES = #{sizes}
- GC.stat_heap.each do |i, s|
- multiple = s[:slot_size] / (GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE] + GC::INTERNAL_CONSTANTS[:RVALUE_OVERHEAD])
- # Allocatable pages are assumed to have lost 1 slot due to alignment.
- slots_per_page = (GC::INTERNAL_CONSTANTS[:HEAP_PAGE_OBJ_LIMIT] / multiple) - 1
-
- total_slots = s[:heap_eden_slots] + s[:heap_allocatable_pages] * slots_per_page
-
- # The delta is calculated as follows:
- # - For allocated pages, each page can vary by 1 slot due to alignment.
- # - For allocatable pages, we can end up with at most 1 extra page of slots.
- assert_in_delta(SIZES[i], total_slots, s[:heap_eden_pages] + slots_per_page, s)
- end
- RUBY
-
- # Check that the configured sizes are "remembered" across GC invocations.
- assert_separately([env, "-W0"], __FILE__, __LINE__, <<~RUBY)
- SIZES = #{sizes}
-
- # Fill size pool 0 with transient objects.
- ary = []
- while GC.stat_heap(0, :heap_allocatable_pages) != 0
- ary << Object.new
- end
- ary.clear
- ary = nil
-
- # Clear all the objects that were allocated.
- GC.start
-
- # Check that we still have the same number of slots as initially configured.
- GC.stat_heap.each do |i, s|
- multiple = s[:slot_size] / (GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE] + GC::INTERNAL_CONSTANTS[:RVALUE_OVERHEAD])
- # Allocatable pages are assumed to have lost 1 slot due to alignment.
- slots_per_page = (GC::INTERNAL_CONSTANTS[:HEAP_PAGE_OBJ_LIMIT] / multiple) - 1
-
- total_slots = s[:heap_eden_slots] + s[:heap_allocatable_pages] * slots_per_page
-
- # The delta is calculated as follows:
- # - For allocated pages, each page can vary by 1 slot due to alignment.
- # - For allocatable pages, we can end up with at most 1 extra page of slots.
- assert_in_delta(SIZES[i], total_slots, s[:heap_eden_pages] + slots_per_page, s)
- end
- RUBY
-
- # Check that we don't grow the heap in minor GC if we have alloctable pages.
- env["RUBY_GC_HEAP_FREE_SLOTS_MIN_RATIO"] = "0.3"
- env["RUBY_GC_HEAP_FREE_SLOTS_GOAL_RATIO"] = "0.99"
- env["RUBY_GC_HEAP_FREE_SLOTS_MAX_RATIO"] = "1.0"
- env["RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR"] = "100" # Large value to disable major GC
- assert_separately([env, "-W0"], __FILE__, __LINE__, <<~RUBY)
- SIZES = #{sizes}
-
- # Run a major GC to clear out dead objects.
- GC.start
-
- # Disable GC so we can control when GC is ran.
- GC.disable
-
- # Run minor GC enough times so that we don't grow the heap because we
- # haven't yet ran RVALUE_OLD_AGE minor GC cycles.
- GC::INTERNAL_CONSTANTS[:RVALUE_OLD_AGE].times { GC.start(full_mark: false) }
-
- # Fill size pool 0 to over 50% full so that the number of allocatable
- # pages that will be created will be over the number in heap_allocatable_pages
- # (calculated using RUBY_GC_HEAP_FREE_SLOTS_MIN_RATIO).
- # 70% was chosen here to guarantee that.
- ary = []
- while GC.stat_heap(0, :heap_allocatable_pages) >
- (GC.stat_heap(0, :heap_allocatable_pages) + GC.stat_heap(0, :heap_eden_pages)) * 0.3
- ary << Object.new
- end
-
- GC.start(full_mark: false)
-
- # Check that we still have the same number of slots as initially configured.
- GC.stat_heap.each do |i, s|
- multiple = s[:slot_size] / (GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE] + GC::INTERNAL_CONSTANTS[:RVALUE_OVERHEAD])
- # Allocatable pages are assumed to have lost 1 slot due to alignment.
- slots_per_page = (GC::INTERNAL_CONSTANTS[:HEAP_PAGE_OBJ_LIMIT] / multiple) - 1
-
- total_slots = s[:heap_eden_slots] + s[:heap_allocatable_pages] * slots_per_page
-
- # The delta is calculated as follows:
- # - For allocated pages, each page can vary by 1 slot due to alignment.
- # - For allocatable pages, we can end up with at most 1 extra page of slots.
- assert_in_delta(SIZES[i], total_slots, s[:heap_eden_pages] + slots_per_page, s)
- end
- RUBY
end
def test_profiler_enabled
@@ -586,28 +285,20 @@ class TestGc < Test::Unit::TestCase
end
def test_profiler_clear
- omit "for now"
- assert_separately([], __FILE__, __LINE__, <<-'RUBY', timeout: 30)
- GC::Profiler.enable
-
- GC.start
- assert_equal(1, GC::Profiler.raw_data.size)
- GC::Profiler.clear
- assert_equal(0, GC::Profiler.raw_data.size)
-
- 200.times{ GC.start }
- assert_equal(200, GC::Profiler.raw_data.size)
- GC::Profiler.clear
- assert_equal(0, GC::Profiler.raw_data.size)
- RUBY
- end
-
- def test_profiler_raw_data
+ skip "for now"
+ assert_separately %w[--disable-gem], __FILE__, __LINE__, <<-'eom', timeout: 30
GC::Profiler.enable
+
GC.start
- assert GC::Profiler.raw_data
- ensure
- GC::Profiler.disable
+ assert_equal(1, GC::Profiler.raw_data.size)
+ GC::Profiler.clear
+ assert_equal(0, GC::Profiler.raw_data.size)
+
+ 200.times{ GC.start }
+ assert_equal(200, GC::Profiler.raw_data.size)
+ GC::Profiler.clear
+ assert_equal(0, GC::Profiler.raw_data.size)
+ eom
end
def test_profiler_total_time
@@ -621,62 +312,28 @@ class TestGc < Test::Unit::TestCase
end
def test_finalizing_main_thread
- assert_in_out_err([], <<-EOS, ["\"finalize\""], [], "[ruby-dev:46647]")
+ assert_in_out_err(%w[--disable-gems], <<-EOS, ["\"finalize\""], [], "[ruby-dev:46647]")
ObjectSpace.define_finalizer(Thread.main) { p 'finalize' }
EOS
end
def test_expand_heap
- assert_separately([], __FILE__, __LINE__, <<~'RUBY')
- GC.start
- base_length = GC.stat[:heap_eden_pages]
- (base_length * 500).times{ 'a' }
- GC.start
- base_length = GC.stat[:heap_eden_pages]
- (base_length * 500).times{ 'a' }
- GC.start
- assert_in_epsilon base_length, (v = GC.stat[:heap_eden_pages]), 1/8r,
- "invalid heap expanding (base_length: #{base_length}, GC.stat[:heap_eden_pages]: #{v})"
-
- a = []
- (base_length * 500).times{ a << 'a'; nil }
- GC.start
- assert_operator base_length, :<, GC.stat[:heap_eden_pages] + 1
- RUBY
- end
-
- def test_thrashing_for_young_objects
- # This test prevents bugs like [Bug #18929]
-
- assert_separately([], __FILE__, __LINE__, <<-'RUBY')
- # Grow the heap
- @ary = 100_000.times.map { Object.new }
-
- # Warmup to make sure heap stabilizes
- 1_000_000.times { Object.new }
-
- before_stats = GC.stat
- before_stat_heap = GC.stat_heap
-
- 1_000_000.times { Object.new }
-
- # Previous loop may have caused GC to be in an intermediate state,
- # running a minor GC here will guarantee that GC will be complete
- GC.start(full_mark: false)
-
- after_stats = GC.stat
- after_stat_heap = GC.stat_heap
-
- # Debugging output to for failures in trunk-repeat50@phosphorus-docker
- debug_msg = "before_stats: #{before_stats}\nbefore_stat_heap: #{before_stat_heap}\nafter_stats: #{after_stats}\nafter_stat_heap: #{after_stat_heap}"
+ assert_separately %w[--disable-gem], __FILE__, __LINE__, <<-'eom'
+ GC.start
+ base_length = GC.stat[:heap_eden_pages]
+ (base_length * 500).times{ 'a' }
+ GC.start
+ base_length = GC.stat[:heap_eden_pages]
+ (base_length * 500).times{ 'a' }
+ GC.start
+ assert_in_epsilon base_length, (v = GC.stat[:heap_eden_pages]), 1/8r,
+ "invalid heap expanding (base_length: #{base_length}, GC.stat[:heap_eden_pages]: #{v})"
- # Should not be thrashing in page creation
- assert_equal before_stats[:heap_allocated_pages], after_stats[:heap_allocated_pages], debug_msg
- assert_equal 0, after_stats[:heap_tomb_pages], debug_msg
- assert_equal 0, after_stats[:total_freed_pages], debug_msg
- # Only young objects, so should not trigger major GC
- assert_equal before_stats[:major_gc_count], after_stats[:major_gc_count], debug_msg
- RUBY
+ a = []
+ (base_length * 500).times{ a << 'a'; nil }
+ GC.start
+ assert_operator base_length, :<, GC.stat[:heap_eden_pages] + 1
+ eom
end
def test_gc_internals
@@ -738,11 +395,11 @@ class TestGc < Test::Unit::TestCase
end
def test_finalizer_passed_object_id
- assert_in_out_err([], <<~RUBY, ["true"], [])
+ 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 })
- RUBY
+ EOS
end
def test_verify_internal_consistency
@@ -827,15 +484,6 @@ class TestGc < Test::Unit::TestCase
obj = nil
end
end;
-
- assert_normal_exit "#{<<~"begin;"}\n#{<<~'end;'}", '[Bug #20042]'
- begin;
- def (f = Object.new).call = nil # missing ID
- o = Object.new
- ObjectSpace.define_finalizer(o, f)
- o = nil
- GC.start
- end;
end
def test_object_ids_never_repeat
@@ -851,30 +499,4 @@ class TestGc < Test::Unit::TestCase
Module.new.class_eval( (["# shareable_constant_value: literal"] +
(0..100000).map {|i| "M#{ i } = {}" }).join("\n"))
end
-
- def test_old_to_young_reference
- original_gc_disabled = GC.disable
-
- require "objspace"
-
- old_obj = Object.new
- 4.times { GC.start }
-
- assert_include ObjectSpace.dump(old_obj), '"old":true'
-
- young_obj = Object.new
- old_obj.instance_variable_set(:@test, young_obj)
-
- # Not immediately promoted to old generation
- 3.times do
- assert_not_include ObjectSpace.dump(young_obj), '"old":true'
- GC.start
- end
-
- # Takes 4 GC to promote to old generation
- GC.start
- assert_include ObjectSpace.dump(young_obj), '"old":true'
- ensure
- GC.enable if !original_gc_disabled
- end
end
diff --git a/test/ruby/test_gc_compact.rb b/test/ruby/test_gc_compact.rb
index f8ebba84b8..42ad028530 100644
--- a/test/ruby/test_gc_compact.rb
+++ b/test/ruby/test_gc_compact.rb
@@ -9,25 +9,31 @@ if RUBY_PLATFORM =~ /s390x/
end
class TestGCCompact < Test::Unit::TestCase
- module CompactionSupportInspector
- def supports_auto_compact?
- GC::OPTS.include?("GC_COMPACTION_SUPPORTED")
+ module SupportsCompact
+ def setup
+ skip "autocompact not supported on this platform" unless supports_auto_compact?
+ super
end
- end
- module OmitUnlessCompactSupported
- include CompactionSupportInspector
+ private
- def setup
- omit "autocompact not supported on this platform" unless supports_auto_compact?
- super
+ def supports_auto_compact?
+ return true unless defined?(Etc::SC_PAGE_SIZE)
+
+ begin
+ return GC::INTERNAL_CONSTANTS[:HEAP_PAGE_SIZE] % Etc.sysconf(Etc::SC_PAGE_SIZE) == 0
+ rescue NotImplementedError
+ rescue ArgumentError
+ end
+
+ true
end
end
- include OmitUnlessCompactSupported
+ include SupportsCompact
class AutoCompact < Test::Unit::TestCase
- include OmitUnlessCompactSupported
+ include SupportsCompact
def test_enable_autocompact
before = GC.auto_compact
@@ -72,7 +78,7 @@ class TestGCCompact < Test::Unit::TestCase
n.times do
break if count < GC.stat(:compact_count)
list2 << Object.new
- end and omit "implicit compaction didn't happen within #{n} objects"
+ end and skip "implicit compaction didn't happen within #{n} objects"
compact_stats = GC.latest_compact_info
refute_predicate compact_stats[:considered], :empty?
refute_predicate compact_stats[:moved], :empty?
@@ -81,41 +87,15 @@ class TestGCCompact < Test::Unit::TestCase
end
end
- class CompactMethodsNotImplemented < Test::Unit::TestCase
- include CompactionSupportInspector
-
- def assert_not_implemented(method, *args)
- omit "autocompact is supported on this platform" if supports_auto_compact?
-
- assert_raise(NotImplementedError) { GC.send(method, *args) }
- refute(GC.respond_to?(method), "GC.#{method} should be defined as rb_f_notimplement")
- end
-
- def test_gc_compact_not_implemented
- assert_not_implemented(:compact)
- end
-
- def test_gc_auto_compact_get_not_implemented
- assert_not_implemented(:auto_compact)
- end
-
- def test_gc_auto_compact_set_not_implemented
- assert_not_implemented(:auto_compact=, true)
- end
-
- def test_gc_latest_compact_info_not_implemented
- assert_not_implemented(:latest_compact_info)
- end
-
- def test_gc_verify_compaction_references_not_implemented
- assert_not_implemented(:verify_compaction_references)
- end
- end
-
def os_page_size
return true unless defined?(Etc::SC_PAGE_SIZE)
end
+ def setup
+ skip "autocompact not supported on this platform" unless supports_auto_compact?
+ super
+ end
+
def test_gc_compact_stats
list = []
@@ -166,7 +146,7 @@ class TestGCCompact < Test::Unit::TestCase
hash = list_of_objects.hash
GC.verify_compaction_references(toward: :empty)
assert_equal hash, list_of_objects.hash
- GC.verify_compaction_references(expand_heap: false)
+ GC.verify_compaction_references(double_heap: false)
assert_equal hash, list_of_objects.hash
end
@@ -191,290 +171,4 @@ class TestGCCompact < Test::Unit::TestCase
GC.compact
assert_equal count + 1, GC.stat(:compact_count)
end
-
- def test_compacting_from_trace_point
- obj = Object.new
- def obj.tracee
- :ret # expected to emit both line and call event from one instruction
- end
-
- results = []
- TracePoint.new(:call, :line) do |tp|
- results << tp.event
- GC.verify_compaction_references
- end.enable(target: obj.method(:tracee)) do
- obj.tracee
- end
-
- assert_equal([:call, :line], results)
- end
-
- def test_updating_references_for_heap_allocated_shared_arrays
- assert_separately(%w[-robjspace], "#{<<~"begin;"}\n#{<<~"end;"}", timeout: 10, signal: :SEGV)
- begin;
- ary = []
- 50.times { |i| ary << i }
-
- # Pointer in slice should point to buffer of ary
- slice = ary[10..40]
-
- # Check that slice is pointing to buffer of ary
- assert_include(ObjectSpace.dump(slice), '"shared":true')
-
- # Run compaction to re-embed ary
- GC.verify_compaction_references(expand_heap: true, toward: :empty)
-
- # Assert that slice is pointer to updated buffer in ary
- assert_equal(10, slice[0])
- # Check that slice is still pointing to buffer of ary
- assert_include(ObjectSpace.dump(slice), '"shared":true')
- end;
- end
-
- def test_updating_references_for_embed_shared_arrays
- omit if GC::INTERNAL_CONSTANTS[:SIZE_POOL_COUNT] == 1
-
- assert_separately(%w[-robjspace], "#{<<~"begin;"}\n#{<<~"end;"}", timeout: 10, signal: :SEGV)
- begin;
- ary = Array.new(50)
- 50.times { |i| ary[i] = i }
-
- # Ensure ary is embedded
- assert_include(ObjectSpace.dump(ary), '"embedded":true')
-
- slice = ary[10..40]
-
- # Check that slice is pointing to buffer of ary
- assert_include(ObjectSpace.dump(slice), '"shared":true')
-
- # Run compaction to re-embed ary
- GC.verify_compaction_references(expand_heap: true, toward: :empty)
-
- # Assert that slice is pointer to updated buffer in ary
- assert_equal(10, slice[0])
- # Check that slice is still pointing to buffer of ary
- assert_include(ObjectSpace.dump(slice), '"shared":true')
- end;
- end
-
- def test_updating_references_for_heap_allocated_frozen_shared_arrays
- assert_separately(%w[-robjspace], "#{<<~"begin;"}\n#{<<~"end;"}", timeout: 10, signal: :SEGV)
- begin;
- ary = []
- 50.times { |i| ary << i }
- # Frozen arrays can become shared root without RARRAY_SHARED_ROOT_FLAG
- ary.freeze
-
- slice = ary[10..40]
-
- # Check that slice is pointing to buffer of ary
- assert_include(ObjectSpace.dump(slice), '"shared":true')
-
- # Run compaction to re-embed ary
- GC.verify_compaction_references(expand_heap: true, toward: :empty)
-
- # Assert that slice is pointer to updated buffer in ary
- assert_equal(10, slice[0])
- # Check that slice is still pointing to buffer of ary
- assert_include(ObjectSpace.dump(slice), '"shared":true')
- end;
- end
-
- def test_updating_references_for_embed_frozen_shared_arrays
- omit if GC::INTERNAL_CONSTANTS[:SIZE_POOL_COUNT] == 1
-
- assert_separately(%w[-robjspace], "#{<<~"begin;"}\n#{<<~"end;"}", timeout: 10, signal: :SEGV)
- begin;
- ary = Array.new(50)
- 50.times { |i| ary[i] = i }
- # Frozen arrays can become shared root without RARRAY_SHARED_ROOT_FLAG
- ary.freeze
-
- # Ensure ary is embedded
- assert_include(ObjectSpace.dump(ary), '"embedded":true')
-
- slice = ary[10..40]
-
- # Check that slice is pointing to buffer of ary
- assert_include(ObjectSpace.dump(slice), '"shared":true')
-
- # Run compaction to re-embed ary
- GC.verify_compaction_references(expand_heap: true, toward: :empty)
-
- # Assert that slice is pointer to updated buffer in ary
- assert_equal(10, slice[0])
- # Check that slice is still pointing to buffer of ary
- assert_include(ObjectSpace.dump(slice), '"shared":true')
- end;
- end
-
- def test_moving_arrays_down_size_pools
- omit if GC::INTERNAL_CONSTANTS[:SIZE_POOL_COUNT] == 1
-
- assert_separately(%w[-robjspace], "#{<<~"begin;"}\n#{<<~"end;"}", timeout: 10, signal: :SEGV)
- begin;
- ARY_COUNT = 50000
-
- GC.verify_compaction_references(expand_heap: true, toward: :empty)
-
- Fiber.new {
- $arys = ARY_COUNT.times.map do
- ary = "abbbbbbbbbb".chars
- ary.uniq!
- end
- }.resume
-
- stats = GC.verify_compaction_references(expand_heap: true, toward: :empty)
- assert_operator(stats.dig(:moved_down, :T_ARRAY) || 0, :>=, ARY_COUNT - 10)
- refute_empty($arys.keep_if { |o| ObjectSpace.dump(o).include?('"embedded":true') })
- end;
- end
-
- def test_moving_arrays_up_size_pools
- omit if GC::INTERNAL_CONSTANTS[:SIZE_POOL_COUNT] == 1
-
- assert_separately(%w[-robjspace], "#{<<~"begin;"}\n#{<<~"end;"}", timeout: 10, signal: :SEGV)
- begin;
- ARY_COUNT = 50000
-
- GC.verify_compaction_references(expand_heap: true, toward: :empty)
-
- Fiber.new {
- ary = "hello".chars
- $arys = ARY_COUNT.times.map do
- x = []
- ary.each { |e| x << e }
- x
- end
- }.resume
-
- stats = GC.verify_compaction_references(expand_heap: true, toward: :empty)
- assert_operator(stats.dig(:moved_up, :T_ARRAY) || 0, :>=, ARY_COUNT - 10)
- refute_empty($arys.keep_if { |o| ObjectSpace.dump(o).include?('"embedded":true') })
- end;
- end
-
- def test_moving_objects_between_size_pools
- omit if GC::INTERNAL_CONSTANTS[:SIZE_POOL_COUNT] == 1
-
- assert_separately(%w[-robjspace], "#{<<~"begin;"}\n#{<<~"end;"}", timeout: 10, signal: :SEGV)
- begin;
- class Foo
- def add_ivars
- 10.times do |i|
- instance_variable_set("@foo" + i.to_s, 0)
- end
- end
- end
-
- OBJ_COUNT = 50000
-
- GC.verify_compaction_references(expand_heap: true, toward: :empty)
-
- Fiber.new {
- $ary = OBJ_COUNT.times.map { Foo.new }
- $ary.each(&:add_ivars)
-
- GC.start
- Foo.new.add_ivars
- }.resume
-
- stats = GC.verify_compaction_references(expand_heap: true, toward: :empty)
-
- assert_operator(stats.dig(:moved_up, :T_OBJECT) || 0, :>=, OBJ_COUNT - 10)
- refute_empty($ary.keep_if { |o| ObjectSpace.dump(o).include?('"embedded":true') })
- end;
- end
-
- def test_moving_strings_up_size_pools
- omit if GC::INTERNAL_CONSTANTS[:SIZE_POOL_COUNT] == 1
-
- assert_separately(%w[-robjspace], "#{<<~"begin;"}\n#{<<~"end;"}", timeout: 30, signal: :SEGV)
- begin;
- STR_COUNT = 50000
-
- GC.verify_compaction_references(expand_heap: true, toward: :empty)
-
- Fiber.new {
- str = "a" * GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE] * 4
- $ary = STR_COUNT.times.map { "" << str }
- }.resume
-
- stats = GC.verify_compaction_references(expand_heap: true, toward: :empty)
-
- assert_operator(stats[:moved_up][:T_STRING], :>=, STR_COUNT - 10)
- refute_empty($ary.keep_if { |o| ObjectSpace.dump(o).include?('"embedded":true') })
- end;
- end
-
- def test_moving_strings_down_size_pools
- omit if GC::INTERNAL_CONSTANTS[:SIZE_POOL_COUNT] == 1
-
- assert_separately(%w[-robjspace], "#{<<~"begin;"}\n#{<<~"end;"}", timeout: 30, signal: :SEGV)
- begin;
- STR_COUNT = 50000
-
- GC.verify_compaction_references(expand_heap: true, toward: :empty)
-
- Fiber.new {
- $ary = STR_COUNT.times.map { ("a" * GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE] * 4).squeeze! }
- }.resume
-
- stats = GC.verify_compaction_references(expand_heap: true, toward: :empty)
-
- assert_operator(stats[:moved_down][:T_STRING], :>=, STR_COUNT - 10)
- refute_empty($ary.keep_if { |o| ObjectSpace.dump(o).include?('"embedded":true') })
- end;
- end
-
- def test_moving_hashes_down_size_pools
- omit if GC::INTERNAL_CONSTANTS[:SIZE_POOL_COUNT] == 1
- # AR and ST hashes are in the same size pool on 32 bit
- omit unless RbConfig::SIZEOF["uint64_t"] <= RbConfig::SIZEOF["void*"]
-
- assert_separately(%w[-robjspace], "#{<<~"begin;"}\n#{<<~"end;"}", timeout: 30, signal: :SEGV)
- begin;
- HASH_COUNT = 50000
-
- GC.verify_compaction_references(expand_heap: true, toward: :empty)
-
- Fiber.new {
- base_hash = { a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8 }
- $ary = HASH_COUNT.times.map { base_hash.dup }
- $ary.each_with_index { |h, i| h[:i] = 9 }
- }.resume
-
- stats = GC.verify_compaction_references(expand_heap: true, toward: :empty)
-
- assert_operator(stats[:moved_down][:T_HASH], :>=, HASH_COUNT - 10)
- end;
- end
-
- def test_moving_objects_between_size_pools_keeps_shape_frozen_status
- # [Bug #19536]
- assert_separately([], "#{<<~"begin;"}\n#{<<~"end;"}")
- begin;
- class A
- def add_ivars
- @a = @b = @c = @d = 1
- end
-
- def set_a
- @a = 10
- end
- end
-
- a = A.new
- a.add_ivars
- a.freeze
-
- b = A.new
- b.add_ivars
- b.set_a # Set the inline cache in set_a
-
- GC.verify_compaction_references(expand_heap: true, toward: :empty)
-
- assert_raise(FrozenError) { a.set_a }
- end;
- end
end
diff --git a/test/ruby/test_hash.rb b/test/ruby/test_hash.rb
index c72b256bab..683ec3855d 100644
--- a/test/ruby/test_hash.rb
+++ b/test/ruby/test_hash.rb
@@ -4,6 +4,7 @@ require 'test/unit'
EnvUtil.suppress_warning {require 'continuation'}
class TestHash < Test::Unit::TestCase
+
def test_hash
x = @cls[1=>2, 2=>4, 3=>6]
y = @cls[1=>2, 2=>4, 3=>6] # y = {1, 2, 2, 4, 3, 6} # 1.9 doesn't support
@@ -84,9 +85,20 @@ class TestHash < Test::Unit::TestCase
self => 'self', true => 'true', nil => 'nil',
'nil' => nil
]
+ @verbose = $VERBOSE
end
def teardown
+ $VERBOSE = @verbose
+ end
+
+ def test_bad_initialize_copy
+ h = Class.new(Hash) {
+ def initialize_copy(h)
+ super(Object.new)
+ end
+ }.new
+ assert_raise(TypeError) { h.dup }
end
def test_clear_initialize_copy
@@ -101,6 +113,35 @@ class TestHash < Test::Unit::TestCase
assert_equal(2, h[1])
end
+ def test_dup_will_not_rehash
+ assert_hash_does_not_rehash(&:dup)
+ end
+
+ def assert_hash_does_not_rehash
+ obj = Object.new
+ class << obj
+ attr_accessor :hash_calls
+ def hash
+ @hash_calls += 1
+ super
+ end
+ end
+ obj.hash_calls = 0
+ hash = {obj => 42}
+ assert_equal(1, obj.hash_calls)
+ yield hash
+ assert_equal(1, obj.hash_calls)
+ end
+
+ def test_select_reject_will_not_rehash
+ assert_hash_does_not_rehash do |hash|
+ hash.select { true }
+ end
+ assert_hash_does_not_rehash do |hash|
+ hash.reject { false }
+ end
+ end
+
def test_s_AREF_from_hash
h = @cls["a" => 100, "b" => 200]
assert_equal(100, h['a'])
@@ -178,16 +219,6 @@ class TestHash < Test::Unit::TestCase
assert_equal('default', h['spurious'])
end
- def test_st_literal_memory_leak
- assert_no_memory_leak([], "", "#{<<~"begin;"}\n#{<<~'end;'}", rss: true)
- begin;
- 1_000_000.times do
- # >8 element hashes are ST allocated rather than AR allocated
- {a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9}
- end
- end;
- end
-
def test_try_convert
assert_equal({1=>2}, Hash.try_convert({1=>2}))
assert_equal(nil, Hash.try_convert("1=>2"))
@@ -263,6 +294,64 @@ class TestHash < Test::Unit::TestCase
assert_equal(256, h[z])
end
+ def test_AREF_fstring_key
+ # warmup ObjectSpace.count_objects
+ ObjectSpace.count_objects
+
+ h = {"abc" => 1}
+ before = ObjectSpace.count_objects[:T_STRING]
+ 5.times{ h["abc"] }
+ assert_equal before, ObjectSpace.count_objects[:T_STRING]
+ end
+
+ def test_ASET_fstring_key
+ a, b = {}, {}
+ assert_equal 1, a["abc"] = 1
+ assert_equal 1, b["abc"] = 1
+ 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
+ h['abc'] = 2
+ assert_equal 2, h.size, '[ruby-core:78783] [Bug #12855]'
+ end
+
+ def test_hash_aref_fstring_identity
+ h = {}.compare_by_identity
+ h['abc'] = 1
+ assert_nil h['abc'], '[ruby-core:78783] [Bug #12855]'
+ end
+
+ def test_NEWHASH_fstring_key
+ a = {"ABC" => :t}
+ 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_EQUAL # '=='
h1 = @cls[ "a" => 1, "c" => 2 ]
h2 = @cls[ "a" => 1, "c" => 2, 7 => 35 ]
@@ -369,10 +458,6 @@ class TestHash < Test::Unit::TestCase
end
end
assert_equal(base.dup, h)
-
- h = base.dup
- assert_same h, h.delete_if {h.assoc(nil); true}
- assert_empty h
end
def test_keep_if
@@ -743,6 +828,14 @@ 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
@@ -858,6 +951,13 @@ class TestHash < Test::Unit::TestCase
assert_instance_of(Hash, h)
end
+ def test_nil_to_h
+ h = nil.to_h
+ assert_equal({}, h)
+ assert_nil(h.default)
+ assert_nil(h.default_proc)
+ end
+
def test_to_s
h = @cls[ 1 => 2, "cat" => "dog", 1.5 => :fred ]
assert_equal(h.inspect, h.to_s)
@@ -904,6 +1004,12 @@ class TestHash < Test::Unit::TestCase
assert_equal([], expected - vals)
end
+ def test_initialize_wrong_arguments
+ assert_raise(ArgumentError) do
+ Hash.new(0) { }
+ end
+ end
+
def test_create
assert_equal({1=>2, 3=>4}, @cls[[[1,2],[3,4]]])
assert_raise(ArgumentError) { @cls[0, 1, 2] }
@@ -942,14 +1048,14 @@ class TestHash < Test::Unit::TestCase
h = @cls.new {|hh, k| :foo }
h[1] = 2
assert_equal([1, 2], h.shift)
- assert_nil(h.shift)
- assert_nil(h.shift)
+ assert_equal(:foo, h.shift)
+ assert_equal(:foo, h.shift)
h = @cls.new(:foo)
h[1] = 2
assert_equal([1, 2], h.shift)
- assert_nil(h.shift)
- assert_nil(h.shift)
+ assert_equal(:foo, h.shift)
+ assert_equal(:foo, h.shift)
h =@cls[1=>2]
h.each { assert_equal([1, 2], h.shift) }
@@ -960,7 +1066,7 @@ class TestHash < Test::Unit::TestCase
def h.default(k = nil)
super.upcase
end
- assert_nil(h.shift)
+ assert_equal("FOO", h.shift)
end
def test_shift_for_empty_hash
@@ -1185,6 +1291,15 @@ class TestHash < Test::Unit::TestCase
assert_raise(FrozenError) { h2.replace(42) }
end
+ def test_replace_memory_leak
+ assert_no_memory_leak([], "#{<<-"begin;"}", "#{<<-'end;'}")
+ h = ("aa".."zz").each_with_index.to_h
+ 10_000.times {h.dup}
+ begin;
+ 500_000.times {h.dup.replace(h)}
+ end;
+ end
+
def test_size2
assert_equal(0, @cls[].size)
end
@@ -1458,16 +1573,6 @@ class TestHash < Test::Unit::TestCase
assert_predicate(h.dup, :compare_by_identity?, bug8703)
end
- def test_compare_by_identy_memory_leak
- assert_no_memory_leak([], "", "#{<<~"begin;"}\n#{<<~'end;'}", "[Bug #20145]", rss: true)
- begin;
- h = { 1 => 2 }.compare_by_identity
- 1_000_000.times do
- h.select { false }
- end
- end;
- end
-
def test_same_key
bug9646 = '[ruby-dev:48047] [Bug #9646] Infinite loop at Hash#each'
h = @cls[a=[], 1]
@@ -1598,6 +1703,124 @@ class TestHash < Test::Unit::TestCase
end
end
+ def test_exception_in_rehash_memory_leak
+ return unless @cls == Hash
+
+ bug9187 = '[ruby-core:58728] [Bug #9187]'
+
+ prepare = <<-EOS
+ class Foo
+ def initialize
+ @raise = false
+ end
+
+ def hash
+ raise if @raise
+ @raise = true
+ return 0
+ end
+ end
+ h = {Foo.new => true}
+ EOS
+
+ code = <<-EOS
+ 10_0000.times do
+ h.rehash rescue nil
+ end
+ GC.start
+ EOS
+
+ assert_no_memory_leak([], prepare, code, bug9187)
+ end
+
+ def test_memory_size_after_delete
+ require 'objspace'
+ h = {}
+ 1000.times {|i| h[i] = true}
+ big = ObjectSpace.memsize_of(h)
+ 1000.times {|i| h.delete(i)}
+ assert_operator ObjectSpace.memsize_of(h), :<, big/10
+ end
+
+ def test_wrapper
+ bug9381 = '[ruby-core:59638] [Bug #9381]'
+
+ wrapper = Class.new do
+ def initialize(obj)
+ @obj = obj
+ end
+
+ def hash
+ @obj.hash
+ end
+
+ def eql?(other)
+ @obj.eql?(other)
+ end
+ end
+
+ bad = [
+ 5, true, false, nil,
+ 0.0, 1.72723e-77,
+ :foo, "dsym_#{self.object_id.to_s(16)}_#{Time.now.to_i.to_s(16)}".to_sym,
+ "str",
+ ].select do |x|
+ hash = {x => bug9381}
+ hash[wrapper.new(x)] != bug9381
+ end
+ assert_empty(bad, bug9381)
+ end
+
+ def assert_hash_random(obj, dump = obj.inspect)
+ a = [obj.hash.to_s]
+ 3.times {
+ assert_in_out_err(["-e", "print (#{dump}).hash"], "") do |r, e|
+ a += r
+ assert_equal([], e)
+ end
+ }
+ assert_not_equal([obj.hash.to_s], a.uniq)
+ assert_operator(a.uniq.size, :>, 2, proc {a.inspect})
+ end
+
+ def test_string_hash_random
+ assert_hash_random('abc')
+ end
+
+ def test_symbol_hash_random
+ assert_hash_random(:-)
+ assert_hash_random(:foo)
+ assert_hash_random("dsym_#{self.object_id.to_s(16)}_#{Time.now.to_i.to_s(16)}".to_sym)
+ end
+
+ def test_integer_hash_random
+ assert_hash_random(0)
+ assert_hash_random(+1)
+ assert_hash_random(-1)
+ assert_hash_random(+(1<<100))
+ assert_hash_random(-(1<<100))
+ end
+
+ def test_float_hash_random
+ assert_hash_random(0.0)
+ assert_hash_random(+1.0)
+ assert_hash_random(-1.0)
+ assert_hash_random(1.72723e-77)
+ assert_hash_random(Float::INFINITY, "Float::INFINITY")
+ end
+
+ def test_label_syntax
+ return unless @cls == Hash
+
+ feature4935 = '[ruby-core:37553] [Feature #4935]'
+ x = 'world'
+ hash = assert_nothing_raised(SyntaxError, feature4935) do
+ break eval(%q({foo: 1, "foo-bar": 2, "hello-#{x}": 3, 'hello-#{x}': 4, 'bar': {}}))
+ end
+ assert_equal({:foo => 1, :'foo-bar' => 2, :'hello-world' => 3, :'hello-#{x}' => 4, :bar => {}}, hash, feature4935)
+ x = x
+ end
+
def test_dig
h = @cls[a: @cls[b: [1, 2, 3]], c: 4]
assert_equal(1, h.dig(:a, :b, 0))
@@ -1617,12 +1840,12 @@ class TestHash < Test::Unit::TestCase
def o.respond_to?(*args)
super
end
- assert_raise(TypeError, bug12030) {@cls[foo: o].dig(:foo, :foo)}
+ assert_raise(TypeError, bug12030) {{foo: o}.dig(:foo, :foo)}
end
def test_cmp
- h1 = @cls[a:1, b:2]
- h2 = @cls[a:1, b:2, c:3]
+ h1 = {a:1, b:2}
+ h2 = {a:1, b:2, c:3}
assert_operator(h1, :<=, h1)
assert_operator(h1, :<=, h2)
@@ -1646,8 +1869,8 @@ class TestHash < Test::Unit::TestCase
end
def test_cmp_samekeys
- h1 = @cls[a:1]
- h2 = @cls[a:2]
+ h1 = {a:1}
+ h2 = {a:2}
assert_operator(h1, :<=, h1)
assert_not_operator(h1, :<=, h2)
@@ -1671,15 +1894,15 @@ class TestHash < Test::Unit::TestCase
end
def test_to_proc
- h = @cls[
+ h = {
1 => 10,
2 => 20,
3 => 30,
- ]
+ }
assert_equal([10, 20, 30], [1, 2, 3].map(&h))
- assert_predicate(h.to_proc, :lambda?)
+ assert_equal(true, h.to_proc.lambda?)
end
def test_transform_keys
@@ -1809,6 +2032,22 @@ class TestHash < Test::Unit::TestCase
assert_equal(@cls[a: 2, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10], x)
end
+ def test_broken_hash_value
+ bug14218 = '[ruby-core:84395] [Bug #14218]'
+
+ assert_equal(0, 1_000_000.times.count{a=Object.new.hash; b=Object.new.hash; a < 0 && b < 0 && a + b > 0}, bug14218)
+ 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)}
@@ -1838,27 +2077,6 @@ class TestHash < Test::Unit::TestCase
# ignore
end
- # Previously this test would fail because rb_hash inside opt_aref would look
- # at the current method name
- def test_hash_recursion_independent_of_mid
- o = Class.new do
- def hash(h, k)
- h[k]
- end
-
- def any_other_name(h, k)
- h[k]
- end
- end.new
-
- rec = []; rec << rec
-
- h = @cls[]
- h[rec] = 1
- assert o.hash(h, rec)
- assert o.any_other_name(h, rec)
- end
-
class TestSubHash < TestHash
class SubHash < Hash
end
@@ -1868,341 +2086,6 @@ class TestHash < Test::Unit::TestCase
super
end
end
-end
-
-class TestHashOnly < Test::Unit::TestCase
- def test_bad_initialize_copy
- h = Class.new(Hash) {
- def initialize_copy(h)
- super(Object.new)
- end
- }.new
- assert_raise(TypeError) { h.dup }
- end
-
- def test_dup_will_not_rehash
- assert_hash_does_not_rehash(&:dup)
- end
-
- def assert_hash_does_not_rehash
- obj = Object.new
- class << obj
- attr_accessor :hash_calls
- def hash
- @hash_calls += 1
- super
- end
- end
- obj.hash_calls = 0
- hash = {obj => 42}
- assert_equal(1, obj.hash_calls)
- yield hash
- assert_equal(1, obj.hash_calls)
- end
-
- def test_select_reject_will_not_rehash
- assert_hash_does_not_rehash do |hash|
- hash.select { true }
- end
- assert_hash_does_not_rehash do |hash|
- hash.reject { false }
- end
- end
-
- def test_st_literal_memory_leak
- assert_no_memory_leak([], "", "#{<<~"begin;"}\n#{<<~'end;'}", rss: true)
- begin;
- 1_000_000.times do
- # >8 element hashes are ST allocated rather than AR allocated
- {a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9}
- end
- end;
- end
-
- def test_compare_by_id_memory_leak
- assert_no_memory_leak([], "", <<~RUBY, rss: true)
- 1_000_000.times do
- {a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8}.compare_by_identity
- end
- RUBY
- end
-
- def test_try_convert
- assert_equal({1=>2}, Hash.try_convert({1=>2}))
- assert_equal(nil, Hash.try_convert("1=>2"))
- o = Object.new
- def o.to_hash; {3=>4} end
- assert_equal({3=>4}, Hash.try_convert(o))
- end
-
- def test_AREF_fstring_key
- # warmup ObjectSpace.count_objects
- ObjectSpace.count_objects
-
- h = {"abc" => 1}
- before = ObjectSpace.count_objects[:T_STRING]
- 5.times{ h["abc"] }
- assert_equal before, ObjectSpace.count_objects[:T_STRING]
- end
-
- def test_AREF_fstring_key_default_proc
- assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- h = Hash.new do |h, k|
- k.frozen?
- end
-
- str = "foo"
- refute str.frozen? # assumes this file is frozen_string_literal: false
- refute h[str]
- refute h["foo"]
- end;
- end
-
- def test_ASET_fstring_key
- a, b = {}, {}
- assert_equal 1, a["abc"] = 1
- assert_equal 1, b["abc"] = 1
- 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
- h['abc'] = 2
- assert_equal 2, h.size, '[ruby-core:78783] [Bug #12855]'
- end
-
- def test_hash_aref_fstring_identity
- h = {}.compare_by_identity
- h['abc'] = 1
- assert_nil h['abc'], '[ruby-core:78783] [Bug #12855]'
- end
-
- def test_NEWHASH_fstring_key
- a = {"ABC" => :t}
- 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_rehash_memory_leak
- assert_no_memory_leak([], <<~PREP, <<~CODE, rss: true)
- ar_hash = 1.times.map { |i| [i, i] }.to_h
- st_hash = 10.times.map { |i| [i, i] }.to_h
-
- code = proc do
- ar_hash.rehash
- st_hash.rehash
- end
- 1_000.times(&code)
- PREP
- 1_000_000.times(&code)
- CODE
- 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_replace_st_with_ar
- # ST hash
- h1 = { a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9 }
- # AR hash
- h2 = { a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7 }
- # Replace ST hash with AR hash
- h1.replace(h2)
- assert_equal(h2, h1)
- end
-
- def test_nil_to_h
- h = nil.to_h
- assert_equal({}, h)
- assert_nil(h.default)
- assert_nil(h.default_proc)
- end
-
- def test_initialize_wrong_arguments
- assert_raise(ArgumentError) do
- Hash.new(0) { }
- end
- end
-
- def test_replace_memory_leak
- assert_no_memory_leak([], "#{<<-"begin;"}", "#{<<-'end;'}", rss: true)
- h = ("aa".."zz").each_with_index.to_h
- 10_000.times {h.dup}
- begin;
- 500_000.times {h.dup.replace(h)}
- end;
- end
-
- def hash_iter_recursion(h, level)
- return if level == 0
- h.each_key {}
- h.each_value { hash_iter_recursion(h, level - 1) }
- end
-
- def test_iterlevel_in_ivar_bug19589
- h = { a: nil }
- hash_iter_recursion(h, 200)
- assert true
- end
-
- def test_exception_in_rehash_memory_leak
- bug9187 = '[ruby-core:58728] [Bug #9187]'
-
- prepare = <<-EOS
- class Foo
- def initialize
- @raise = false
- end
-
- def hash
- raise if @raise
- @raise = true
- return 0
- end
- end
- h = {Foo.new => true}
- EOS
-
- code = <<-EOS
- 10_0000.times do
- h.rehash rescue nil
- end
- GC.start
- EOS
-
- assert_no_memory_leak([], prepare, code, bug9187)
- end
-
- def test_memory_size_after_delete
- require 'objspace'
- h = {}
- 1000.times {|i| h[i] = true}
- big = ObjectSpace.memsize_of(h)
- 1000.times {|i| h.delete(i)}
- assert_operator ObjectSpace.memsize_of(h), :<, big/10
- end
-
- def test_wrapper
- bug9381 = '[ruby-core:59638] [Bug #9381]'
-
- wrapper = Class.new do
- def initialize(obj)
- @obj = obj
- end
-
- def hash
- @obj.hash
- end
-
- def eql?(other)
- @obj.eql?(other)
- end
- end
-
- bad = [
- 5, true, false, nil,
- 0.0, 1.72723e-77,
- :foo, "dsym_#{self.object_id.to_s(16)}_#{Time.now.to_i.to_s(16)}".to_sym,
- "str",
- ].select do |x|
- hash = {x => bug9381}
- hash[wrapper.new(x)] != bug9381
- end
- assert_empty(bad, bug9381)
- end
-
- def assert_hash_random(obj, dump = obj.inspect)
- a = [obj.hash.to_s]
- 3.times {
- assert_in_out_err(["-e", "print (#{dump}).hash"], "") do |r, e|
- a += r
- assert_equal([], e)
- end
- }
- assert_not_equal([obj.hash.to_s], a.uniq)
- assert_operator(a.uniq.size, :>, 2, proc {a.inspect})
- end
-
- def test_string_hash_random
- assert_hash_random('abc')
- end
-
- def test_symbol_hash_random
- assert_hash_random(:-)
- assert_hash_random(:foo)
- assert_hash_random("dsym_#{self.object_id.to_s(16)}_#{Time.now.to_i.to_s(16)}".to_sym)
- end
-
- def test_integer_hash_random
- assert_hash_random(0)
- assert_hash_random(+1)
- assert_hash_random(-1)
- assert_hash_random(+(1<<100))
- assert_hash_random(-(1<<100))
- end
-
- def test_float_hash_random
- assert_hash_random(0.0)
- assert_hash_random(+1.0)
- assert_hash_random(-1.0)
- assert_hash_random(1.72723e-77)
- assert_hash_random(Float::INFINITY, "Float::INFINITY")
- end
-
- def test_label_syntax
- feature4935 = '[ruby-core:37553] [Feature #4935]'
- x = 'world'
- hash = assert_nothing_raised(SyntaxError, feature4935) do
- break eval(%q({foo: 1, "foo-bar": 2, "hello-#{x}": 3, 'hello-#{x}': 4, 'bar': {}}))
- end
- assert_equal({:foo => 1, :'foo-bar' => 2, :'hello-world' => 3, :'hello-#{x}' => 4, :bar => {}}, hash, feature4935)
- x = x
- end
-
- def test_broken_hash_value
- bug14218 = '[ruby-core:84395] [Bug #14218]'
-
- assert_equal(0, 1_000_000.times.count{a=Object.new.hash; b=Object.new.hash; a < 0 && b < 0 && a + b > 0}, bug14218)
- 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
ruby2_keywords def get_flagged_hash(*args)
args.last
@@ -2228,11 +2111,23 @@ class TestHashOnly < Test::Unit::TestCase
assert_raise(TypeError) { Hash.ruby2_keywords_hash(1) }
end
- def ar2st_object
- class << (obj = Object.new)
- attr_reader :h
+ def test_ar2st
+ # insert
+ obj = Object.new
+ obj.instance_variable_set(:@h, h = {})
+ def obj.hash
+ 10.times{|i| @h[i] = i}
+ 0
end
- obj.instance_variable_set(:@h, {})
+ 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
@@ -2243,21 +2138,6 @@ class TestHashOnly < Test::Unit::TestCase
def obj.eql? other
other.class == Object
end
- obj
- end
-
- def test_ar2st_insert
- obj = ar2st_object
- h = obj.h
-
- 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
- end
-
- def test_ar2st_delete
- obj = ar2st_object
- h = obj.h
-
obj2 = Object.new
def obj2.hash
0
@@ -2266,12 +2146,20 @@ class TestHashOnly < Test::Unit::TestCase
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
- end
-
- def test_ar2st_lookup
- obj = ar2st_object
- h = obj.h
+ # 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
@@ -2312,35 +2200,4 @@ class TestHashOnly < Test::Unit::TestCase
end;
end
end
-
- def test_compare_by_identity_during_iteration
- h = { 1 => 1 }
- h.each do
- assert_raise(RuntimeError, "compare_by_identity during iteration") do
- h.compare_by_identity
- end
- end
- end
-
- def test_ar_hash_to_st_hash
- assert_normal_exit("#{<<~"begin;"}\n#{<<~'end;'}", 'https://bugs.ruby-lang.org/issues/20050#note-5')
- begin;
- srand(0)
- class Foo
- def to_a
- []
- end
-
- def hash
- $h.delete($h.keys.sample) if rand < 0.1
- to_a.hash
- end
- end
-
- 1000.times do
- $h = {}
- (0..10).each {|i| $h[Foo.new] ||= {} }
- end
- end;
- end
end
diff --git a/test/ruby/test_integer.rb b/test/ruby/test_integer.rb
index 3349a1c493..2f3f00ecda 100644
--- a/test/ruby/test_integer.rb
+++ b/test/ruby/test_integer.rb
@@ -138,6 +138,20 @@ class TestInteger < Test::Unit::TestCase
assert_equal(1234, Integer(1234))
assert_equal(1, Integer(1.234))
+ # base argument
+ assert_equal(1234, Integer("1234", 10))
+ assert_equal(668, Integer("1234", 8))
+ assert_equal(4660, Integer("1234", 16))
+ assert_equal(49360, Integer("1234", 36))
+ # decimal, not octal
+ assert_equal(1234, Integer("01234", 10))
+ assert_raise(ArgumentError) { Integer("0x123", 10) }
+ assert_raise(ArgumentError) { Integer(1234, 10) }
+ assert_raise(ArgumentError) { Integer(12.34, 10) }
+ assert_raise(ArgumentError) { Integer(Object.new, 1) }
+
+ assert_raise(ArgumentError) { Integer(1, 1, 1) }
+
assert_equal(2 ** 50, Integer(2.0 ** 50))
assert_raise(TypeError) { Integer(nil) }
@@ -231,39 +245,6 @@ class TestInteger < Test::Unit::TestCase
end;
end
- def test_Integer_when_to_str
- def (obj = Object.new).to_str
- "0x10"
- end
- assert_equal(16, Integer(obj))
- end
-
- def test_Integer_with_base
- assert_equal(1234, Integer("1234", 10))
- assert_equal(668, Integer("1234", 8))
- assert_equal(4660, Integer("1234", 16))
- assert_equal(49360, Integer("1234", 36))
- # decimal, not octal
- assert_equal(1234, Integer("01234", 10))
- assert_raise(ArgumentError) { Integer("0x123", 10) }
- assert_raise(ArgumentError) { Integer(1234, 10) }
- assert_raise(ArgumentError) { Integer(12.34, 10) }
- assert_raise(ArgumentError) { Integer(Object.new, 1) }
-
- assert_raise(ArgumentError) { Integer(1, 1, 1) }
-
- def (base = Object.new).to_int
- 8
- end
- assert_equal(8, Integer("10", base))
-
- assert_raise(TypeError) { Integer("10", "8") }
- def (base = Object.new).to_int
- "8"
- end
- assert_raise(TypeError) { Integer("10", base) }
- end
-
def test_int_p
assert_not_predicate(1.0, :integer?)
assert_predicate(1, :integer?)
@@ -321,34 +302,23 @@ class TestInteger < Test::Unit::TestCase
begin;
called = false
Integer.class_eval do
- alias old_succ succ
- undef succ
- define_method(:succ){|x| called = true; x+1}
+ alias old_plus +
+ undef +
+ define_method(:+){|x| called = true; 1}
alias old_lt <
undef <
define_method(:<){|x| called = true}
end
-
- fix = 1
- fix.times{break 0}
- fix_called = called
-
- called = false
-
big = 2**65
big.times{break 0}
- big_called = called
-
Integer.class_eval do
- undef succ
- alias succ old_succ
+ undef +
+ alias + old_plus
undef <
alias < old_lt
end
-
- # Asssert that Fixnum and Bignum behave consistently
bug18377 = "[ruby-core:106361]"
- assert_equal(fix_called, big_called, bug18377)
+ assert_equal(false, called, bug18377)
end;
end
@@ -704,14 +674,6 @@ class TestInteger < Test::Unit::TestCase
def test_fdiv
assert_equal(1.0, 1.fdiv(1))
assert_equal(0.5, 1.fdiv(2))
-
- m = 50 << Float::MANT_DIG
- prev = 1.0
- (1..100).each do |i|
- val = (m + i).fdiv(m)
- assert_operator val, :>=, prev, "1+epsilon*(#{i}/100)"
- prev = val
- end
end
def test_obj_fdiv
@@ -740,25 +702,4 @@ class TestInteger < Test::Unit::TestCase
def o.to_int; Object.new; end
assert_raise_with_message(TypeError, /can't convert Object to Integer/) {Integer.try_convert(o)}
end
-
- def test_ceildiv
- assert_equal(0, 0.ceildiv(3))
- assert_equal(1, 1.ceildiv(3))
- assert_equal(1, 3.ceildiv(3))
- assert_equal(2, 4.ceildiv(3))
-
- assert_equal(-1, 4.ceildiv(-3))
- assert_equal(-1, -4.ceildiv(3))
- assert_equal(2, -4.ceildiv(-3))
-
- assert_equal(3, 3.ceildiv(1.2))
- assert_equal(3, 3.ceildiv(6/5r))
-
- assert_equal(10, (10**100-11).ceildiv(10**99-1))
- assert_equal(11, (10**100-9).ceildiv(10**99-1))
-
- o = Object.new
- def o.coerce(other); [other, 10]; end
- assert_equal(124, 1234.ceildiv(o))
- end
end
diff --git a/test/ruby/test_integer_comb.rb b/test/ruby/test_integer_comb.rb
index 150f45cfd7..1ad13dd31b 100644
--- a/test/ruby/test_integer_comb.rb
+++ b/test/ruby/test_integer_comb.rb
@@ -408,32 +408,19 @@ class TestIntegerComb < Test::Unit::TestCase
end
def test_remainder
- coerce = EnvUtil.labeled_class("CoerceNum") do
- def initialize(num)
- @num = num
- end
- def coerce(other)
- [other, @num]
- end
- def inspect
- "#{self.class.name}(#@num)"
- end
- alias to_s inspect
- end
-
VS.each {|a|
- (VS + VS.map {|b| [coerce.new(b), b]}).each {|b, i = b|
- if i == 0
+ VS.each {|b|
+ if b == 0
assert_raise(ZeroDivisionError) { a.divmod(b) }
else
- r = assert_nothing_raised(ArgumentError, "#{a}.remainder(#{b})") {a.remainder(b)}
+ r = a.remainder(b)
assert_kind_of(Integer, r)
if a < 0
- assert_operator(-i.abs, :<, r, "#{a}.remainder(#{b})")
+ assert_operator(-b.abs, :<, r, "#{a}.remainder(#{b})")
assert_operator(0, :>=, r, "#{a}.remainder(#{b})")
elsif 0 < a
assert_operator(0, :<=, r, "#{a}.remainder(#{b})")
- assert_operator(i.abs, :>, r, "#{a}.remainder(#{b})")
+ assert_operator(b.abs, :>, r, "#{a}.remainder(#{b})")
else
assert_equal(0, r, "#{a}.remainder(#{b})")
end
diff --git a/test/ruby/test_io.rb b/test/ruby/test_io.rb
index 476d9f882f..4f54052d3b 100644
--- a/test/ruby/test_io.rb
+++ b/test/ruby/test_io.rb
@@ -312,7 +312,7 @@ class TestIO < Test::Unit::TestCase
w.print "a\n\nb\n\n"
w.close
end, proc do |r|
- assert_equal("a\n\nb\n\n", r.gets(nil, chomp: true), "[Bug #18770]")
+ assert_equal "a\n\nb\n", r.gets(nil, chomp: true)
assert_nil r.gets("")
r.close
end)
@@ -655,8 +655,8 @@ class TestIO < Test::Unit::TestCase
if have_nonblock?
def test_copy_stream_no_busy_wait
- omit "RJIT has busy wait on GC. This sometimes fails with --jit." if defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled?
- omit "multiple threads already active" if Thread.list.size > 1
+ skip "MJIT has busy wait on GC. This sometimes fails with --jit." if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?
+ skip "multiple threads already active" if Thread.list.size > 1
msg = 'r58534 [ruby-core:80969] [Backport #13533]'
IO.pipe do |r,w|
@@ -675,7 +675,7 @@ class TestIO < Test::Unit::TestCase
begin
w2.nonblock = true
rescue Errno::EBADF
- omit "nonblocking IO for pipe is not implemented"
+ skip "nonblocking IO for pipe is not implemented"
end
s = w2.syswrite("a" * 100000)
t = Thread.new { sleep 0.1; r2.read }
@@ -779,7 +779,7 @@ class TestIO < Test::Unit::TestCase
r1.nonblock = true
w2.nonblock = true
rescue Errno::EBADF
- omit "nonblocking IO for pipe is not implemented"
+ skip "nonblocking IO for pipe is not implemented"
end
t1 = Thread.new { w1 << megacontent; w1.close }
t2 = Thread.new { r2.read }
@@ -843,7 +843,7 @@ class TestIO < Test::Unit::TestCase
assert_equal("bcd", r.read)
end)
rescue NotImplementedError
- omit "pread(2) is not implemtented."
+ skip "pread(2) is not implemtented."
end
}
end
@@ -900,10 +900,6 @@ class TestIO < Test::Unit::TestCase
end if defined? UNIXSocket
def test_copy_stream_socket4
- if RUBY_PLATFORM =~ /mingw|mswin/
- omit "pread(2) is not implemented."
- end
-
with_bigsrc {|bigsrc, bigcontent|
File.open(bigsrc) {|f|
assert_equal(0, f.pos)
@@ -920,13 +916,9 @@ class TestIO < Test::Unit::TestCase
}
}
}
- end
+ end if defined? UNIXSocket
def test_copy_stream_socket5
- if RUBY_PLATFORM =~ /mingw|mswin/
- omit "pread(2) is not implemented."
- end
-
with_bigsrc {|bigsrc, bigcontent|
File.open(bigsrc) {|f|
assert_equal(bigcontent[0,100], f.read(100))
@@ -944,13 +936,9 @@ class TestIO < Test::Unit::TestCase
}
}
}
- end
+ end if defined? UNIXSocket
def test_copy_stream_socket6
- if RUBY_PLATFORM =~ /mingw|mswin/
- omit "pread(2) is not implemented."
- end
-
mkcdtmpdir {
megacontent = "abc" * 1234567
File.open("megasrc", "w") {|f| f << megacontent }
@@ -959,7 +947,7 @@ class TestIO < Test::Unit::TestCase
begin
s1.nonblock = true
rescue Errno::EBADF
- omit "nonblocking IO for pipe is not implemented"
+ skip "nonblocking IO for pipe is not implemented"
end
t1 = Thread.new { s2.read }
t2 = Thread.new {
@@ -971,13 +959,9 @@ class TestIO < Test::Unit::TestCase
assert_equal(megacontent, result)
}
}
- end
+ end if defined? UNIXSocket
def test_copy_stream_socket7
- if RUBY_PLATFORM =~ /mingw|mswin/
- omit "pread(2) is not implemented."
- end
-
GC.start
mkcdtmpdir {
megacontent = "abc" * 1234567
@@ -987,7 +971,7 @@ class TestIO < Test::Unit::TestCase
begin
s1.nonblock = true
rescue Errno::EBADF
- omit "nonblocking IO for pipe is not implemented"
+ skip "nonblocking IO for pipe is not implemented"
end
trapping_usr2 do |rd|
nr = 30
@@ -1012,7 +996,7 @@ class TestIO < Test::Unit::TestCase
end
}
}
- end
+ end if defined? UNIXSocket and IO.method_defined?("nonblock=")
def test_copy_stream_strio
src = StringIO.new("abcd")
@@ -1457,16 +1441,6 @@ class TestIO < Test::Unit::TestCase
End
end
- def test_dup_timeout
- with_pipe do |r, w|
- r.timeout = 0.1
- r2 = r.dup
- assert_equal(0.1, r2.timeout)
- ensure
- r2&.close
- end
- end
-
def test_inspect
with_pipe do |r, w|
assert_match(/^#<IO:fd \d+>$/, r.inspect)
@@ -1623,28 +1597,6 @@ class TestIO < Test::Unit::TestCase
end
end
- def test_read_nonblock_file
- make_tempfile do |path|
- File.open(path, 'r') do |file|
- file.read_nonblock(4)
- end
- end
- end
-
- def test_write_nonblock_file
- make_tempfile do |path|
- File.open(path, 'w') do |file|
- file.write_nonblock("Ruby")
- end
- end
- end
-
- def test_explicit_path
- io = IO.for_fd(0, path: "Fake Path", autoclose: false)
- assert_match %r"Fake Path", io.inspect
- assert_equal "Fake Path", io.path
- end
-
def test_write_nonblock_simple_no_exceptions
pipe(proc do |w|
w.write_nonblock('1', exception: false)
@@ -1679,7 +1631,7 @@ class TestIO < Test::Unit::TestCase
end if have_nonblock?
def test_read_nonblock_no_exceptions
- omit '[ruby-core:90895] RJIT worker may leave fd open in a forked child' if defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled? # TODO: consider acquiring GVL from RJIT worker.
+ skip '[ruby-core:90895] MJIT worker may leave fd open in a forked child' if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # TODO: consider acquiring GVL from MJIT worker.
with_pipe {|r, w|
assert_equal :wait_readable, r.read_nonblock(4096, exception: false)
w.puts "HI!"
@@ -1898,110 +1850,6 @@ class TestIO < Test::Unit::TestCase
end)
end
- def test_readline_bad_param_raises
- File.open(__FILE__) do |f|
- assert_raise(TypeError) do
- f.readline Object.new
- end
- end
-
- File.open(__FILE__) do |f|
- assert_raise(TypeError) do
- f.readline 1, 2
- end
- end
- end
-
- def test_readline_raises
- File.open(__FILE__) do |f|
- assert_equal File.read(__FILE__), f.readline(nil)
- assert_raise(EOFError) do
- f.readline
- end
- end
- end
-
- def test_readline_separators
- File.open(__FILE__) do |f|
- line = f.readline("def")
- assert_equal File.read(__FILE__)[/\A.*?def/m], line
- end
-
- File.open(__FILE__) do |f|
- line = f.readline("def", chomp: true)
- assert_equal File.read(__FILE__)[/\A.*?(?=def)/m], line
- end
- end
-
- def test_readline_separators_limits
- t = Tempfile.open("readline_limit")
- str = "#" * 50
- sep = "def"
-
- t.write str
- t.write sep
- t.write str
- t.flush
-
- # over limit
- File.open(t.path) do |f|
- line = f.readline sep, str.bytesize
- assert_equal(str, line)
- end
-
- # under limit
- File.open(t.path) do |f|
- line = f.readline(sep, str.bytesize + 5)
- assert_equal(str + sep, line)
- end
-
- # under limit + chomp
- File.open(t.path) do |f|
- line = f.readline(sep, str.bytesize + 5, chomp: true)
- assert_equal(str, line)
- end
- ensure
- t&.close!
- end
-
- def test_readline_limit_without_separator
- t = Tempfile.open("readline_limit")
- str = "#" * 50
- sep = "\n"
-
- t.write str
- t.write sep
- t.write str
- t.flush
-
- # over limit
- File.open(t.path) do |f|
- line = f.readline str.bytesize
- assert_equal(str, line)
- end
-
- # under limit
- File.open(t.path) do |f|
- line = f.readline(str.bytesize + 5)
- assert_equal(str + sep, line)
- end
-
- # under limit + chomp
- File.open(t.path) do |f|
- line = f.readline(str.bytesize + 5, chomp: true)
- assert_equal(str, line)
- end
- ensure
- t&.close!
- end
-
- def test_readline_chomp_true
- File.open(__FILE__) do |f|
- line = f.readline(chomp: true)
- assert_equal File.readlines(__FILE__).first.chomp, line
- end
- end
-
def test_set_lineno_readline
pipe(proc do |w|
w.puts "foo"
@@ -2046,20 +1894,6 @@ class TestIO < Test::Unit::TestCase
assert_equal("baz\n", e.next)
assert_raise(StopIteration) { e.next }
end)
-
- pipe(proc do |w|
- w.write "foo\n"
- w.close
- end, proc do |r|
- assert_equal(["foo\n"], r.each_line(nil, chomp: true).to_a, "[Bug #18770]")
- end)
-
- pipe(proc do |w|
- w.write "foo\n"
- w.close
- end, proc do |r|
- assert_equal(["fo", "o\n"], r.each_line(nil, 2, chomp: true).to_a, "[Bug #18770]")
- end)
end
def test_each_byte2
@@ -2365,14 +2199,6 @@ class TestIO < Test::Unit::TestCase
end)
end
- def test_sysread_with_negative_length
- make_tempfile {|t|
- open(t.path) do |f|
- assert_raise(ArgumentError) { f.sysread(-1) }
- end
- }
- end
-
def test_flag
make_tempfile {|t|
assert_raise(ArgumentError) do
@@ -2451,9 +2277,9 @@ class TestIO < Test::Unit::TestCase
end
def test_autoclose_true_closed_by_finalizer
- # http://ci.rvm.jp/results/trunk-rjit@silicon-docker/1465760
- # http://ci.rvm.jp/results/trunk-rjit@silicon-docker/1469765
- omit 'this randomly fails with RJIT' if defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled?
+ # http://ci.rvm.jp/results/trunk-mjit@silicon-docker/1465760
+ # http://ci.rvm.jp/results/trunk-mjit@silicon-docker/1469765
+ skip 'this randomly fails with MJIT' if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?
feature2250 = '[ruby-core:26222]'
pre = 'ft2250'
@@ -2465,7 +2291,7 @@ class TestIO < Test::Unit::TestCase
t.close
rescue Errno::EBADF
end
- omit "expect IO object was GC'ed but not recycled yet"
+ skip "expect IO object was GC'ed but not recycled yet"
rescue WeakRef::RefError
assert_raise(Errno::EBADF, feature2250) {t.close}
end
@@ -2481,7 +2307,7 @@ class TestIO < Test::Unit::TestCase
begin
w.close
t.close
- omit "expect IO object was GC'ed but not recycled yet"
+ skip "expect IO object was GC'ed but not recycled yet"
rescue WeakRef::RefError
assert_nothing_raised(Errno::EBADF, feature2250) {t.close}
end
@@ -2516,19 +2342,15 @@ class TestIO < Test::Unit::TestCase
end
def test_open_pipe
- assert_deprecated_warning(/Kernel#open with a leading '\|'/) do # https://bugs.ruby-lang.org/issues/19630
- open("|" + EnvUtil.rubybin, "r+") do |f|
- f.puts "puts 'foo'"
- f.close_write
- assert_equal("foo\n", f.read)
- end
+ open("|" + EnvUtil.rubybin, "r+") do |f|
+ f.puts "puts 'foo'"
+ f.close_write
+ assert_equal("foo\n", f.read)
end
end
def test_read_command
- assert_deprecated_warning(/IO process creation with a leading '\|'/) do # https://bugs.ruby-lang.org/issues/19630
- assert_equal("foo\n", IO.read("|echo foo"))
- end
+ assert_equal("foo\n", IO.read("|echo foo"))
assert_raise(Errno::ENOENT, Errno::EINVAL) do
File.read("|#{EnvUtil.rubybin} -e puts")
end
@@ -2542,9 +2364,7 @@ class TestIO < Test::Unit::TestCase
Class.new(IO).binread("|#{EnvUtil.rubybin} -e puts")
end
assert_raise(Errno::ESPIPE) do
- assert_deprecated_warning(/IO process creation with a leading '\|'/) do # https://bugs.ruby-lang.org/issues/19630
- IO.read("|echo foo", 1, 1)
- end
+ IO.read("|echo foo", 1, 1)
end
end
@@ -2729,16 +2549,11 @@ class TestIO < Test::Unit::TestCase
def test_foreach
a = []
-
- assert_deprecated_warning(/IO process creation with a leading '\|'/) do # https://bugs.ruby-lang.org/issues/19630
- IO.foreach("|" + EnvUtil.rubybin + " -e 'puts :foo; puts :bar; puts :baz'") {|x| a << x }
- end
+ IO.foreach("|" + EnvUtil.rubybin + " -e 'puts :foo; puts :bar; puts :baz'") {|x| a << x }
assert_equal(["foo\n", "bar\n", "baz\n"], a)
a = []
- assert_deprecated_warning(/IO process creation with a leading '\|'/) do # https://bugs.ruby-lang.org/issues/19630
- IO.foreach("|" + EnvUtil.rubybin + " -e 'puts :zot'", :open_args => ["r"]) {|x| a << x }
- end
+ IO.foreach("|" + EnvUtil.rubybin + " -e 'puts :zot'", :open_args => ["r"]) {|x| a << x }
assert_equal(["zot\n"], a)
make_tempfile {|t|
@@ -2773,8 +2588,6 @@ class TestIO < Test::Unit::TestCase
bug = '[ruby-dev:31525]'
assert_raise(ArgumentError, bug) {IO.foreach}
- assert_raise(ArgumentError, "[Bug #18767] [ruby-core:108499]") {IO.foreach(__FILE__, 0){}}
-
a = nil
assert_nothing_raised(ArgumentError, bug) {a = IO.foreach(t.path).to_a}
assert_equal(["foo\n", "bar\n", "baz\n"], a, bug)
@@ -2783,8 +2596,6 @@ class TestIO < Test::Unit::TestCase
assert_raise_with_message(IOError, /not opened for reading/, bug6054) do
IO.foreach(t.path, mode:"w").next
end
-
- assert_raise(ArgumentError, "[Bug #18771] [ruby-core:108503]") {IO.foreach(t, "\n", 10, true){}}
}
end
@@ -2794,7 +2605,6 @@ class TestIO < Test::Unit::TestCase
assert_equal(["foo\nb", "ar\nb", "az\n"], IO.readlines(t.path, "b"))
assert_equal(["fo", "o\n", "ba", "r\n", "ba", "z\n"], IO.readlines(t.path, 2))
assert_equal(["fo", "o\n", "b", "ar", "\nb", "az", "\n"], IO.readlines(t.path, "b", 2))
- assert_raise(ArgumentError, "[Bug #18771] [ruby-core:108503]") {IO.readlines(t, "\n", 10, true){}}
}
end
@@ -2860,7 +2670,7 @@ class TestIO < Test::Unit::TestCase
end
def test_puts_parallel
- omit "not portable"
+ skip "not portable"
pipe(proc do |w|
threads = []
100.times do
@@ -2981,9 +2791,6 @@ class TestIO < Test::Unit::TestCase
assert_equal("foo\nbar\nbaz\n", File.read(t.path))
assert_equal("foo\nba", File.read(t.path, 6))
assert_equal("bar\n", File.read(t.path, 4, 4))
-
- assert_raise(ArgumentError) { File.read(t.path, -1) }
- assert_raise(ArgumentError) { File.read(t.path, 1, -1) }
}
end
@@ -3290,8 +3097,6 @@ __END__
end
def test_cross_thread_close_stdio
- omit "[Bug #18613]" if /freebsd/ =~ RUBY_PLATFORM
-
assert_separately([], <<-'end;')
IO.pipe do |r,w|
$stdin.reopen(r)
@@ -3499,7 +3304,7 @@ __END__
begin
f = File.open('/dev/tty')
rescue Errno::ENOENT, Errno::ENXIO => e
- omit e.message
+ skip e.message
else
tiocgwinsz=0x5413
winsize=""
@@ -3625,10 +3430,10 @@ __END__
with_pipe do |r,w|
# Linux 2.6.15 and earlier returned EINVAL instead of ESPIPE
assert_raise(Errno::ESPIPE, Errno::EINVAL) {
- r.advise(:willneed) or omit "fadvise(2) is not implemented"
+ r.advise(:willneed) or skip "fadvise(2) is not implemented"
}
assert_raise(Errno::ESPIPE, Errno::EINVAL) {
- w.advise(:willneed) or omit "fadvise(2) is not implemented"
+ w.advise(:willneed) or skip "fadvise(2) is not implemented"
}
end
end if /linux/ =~ RUBY_PLATFORM
@@ -3768,14 +3573,14 @@ __END__
f.write('1')
pos = f.tell
rescue Errno::ENOSPC
- omit "non-sparse file system"
+ skip "non-sparse file system"
rescue SystemCallError
else
assert_equal(0x1_0000_0000, pos, msg)
end
end;
rescue Timeout::Error
- omit "Timeout because of slow file writing"
+ skip "Timeout because of slow file writing"
end
}
end if /mswin|mingw/ =~ RUBY_PLATFORM
@@ -3929,7 +3734,7 @@ __END__
end
def test_race_gets_and_close
- opt = { signal: :ABRT, timeout: 10 }
+ opt = { signal: :ABRT, timeout: 200 }
assert_separately([], "#{<<-"begin;"}\n#{<<-"end;"}", **opt)
bug13076 = '[ruby-core:78845] [Bug #13076]'
begin;
@@ -3960,8 +3765,6 @@ __END__
end
def test_race_closed_stream
- omit "[Bug #18613]" if /freebsd/ =~ RUBY_PLATFORM
-
assert_separately([], "#{<<-"begin;"}\n#{<<-"end;"}")
begin;
bug13158 = '[ruby-core:79262] [Bug #13158]'
@@ -4056,8 +3859,6 @@ __END__
end
def test_closed_stream_in_rescue
- omit "[Bug #18613]" if /freebsd/ =~ RUBY_PLATFORM
-
assert_separately([], "#{<<-"begin;"}\n#{<<~"end;"}")
begin;
10.times do
@@ -4091,7 +3892,7 @@ __END__
assert_raise(EOFError) { f.pread(1, f.size) }
end
}
- end
+ end if IO.method_defined?(:pread)
def test_pwrite
make_tempfile { |t|
@@ -4100,7 +3901,7 @@ __END__
assert_equal("ooo", f.pread(3, 4))
end
}
- end
+ end if IO.method_defined?(:pread) and IO.method_defined?(:pwrite)
def test_select_exceptfds
if Etc.uname[:sysname] == 'SunOS'
@@ -4126,9 +3927,6 @@ __END__
noex = Thread.new do # everything right and never see exceptions :)
until sig_rd.wait_readable(0)
IO.pipe do |r, w|
- assert_nil r.timeout
- assert_nil w.timeout
-
th = Thread.new { r.read(1) }
w.write(dot)
diff --git a/test/ruby/test_io_buffer.rb b/test/ruby/test_io_buffer.rb
index 7a58ec0c5a..c1034efe34 100644
--- a/test/ruby/test_io_buffer.rb
+++ b/test/ruby/test_io_buffer.rb
@@ -80,7 +80,7 @@ class TestIOBuffer < Test::Unit::TestCase
end
def test_file_mapped_invalid
- assert_raise TypeError do
+ assert_raise NoMethodError do
IO::Buffer.map("foobar")
end
end
@@ -102,6 +102,11 @@ class TestIOBuffer < Test::Unit::TestCase
IO::Buffer.for(string) do |buffer|
refute buffer.readonly?
+ # Cannot modify string as it's locked by the buffer:
+ assert_raise RuntimeError do
+ string[0] = "h"
+ end
+
buffer.set_value(:U8, 0, "h".ord)
# Buffer releases it's ownership of the string:
@@ -111,16 +116,6 @@ class TestIOBuffer < Test::Unit::TestCase
end
end
- def test_string_mapped_buffer_locked
- string = "Hello World"
- IO::Buffer.for(string) do |buffer|
- # Cannot modify string as it's locked by the buffer:
- assert_raise RuntimeError do
- string[0] = "h"
- end
- end
- end
-
def test_non_string
not_string = Object.new
@@ -129,20 +124,6 @@ class TestIOBuffer < Test::Unit::TestCase
end
end
- def test_string
- result = IO::Buffer.string(12) do |buffer|
- buffer.set_string("Hello World!")
- end
-
- assert_equal "Hello World!", result
- end
-
- def test_string_negative
- assert_raise ArgumentError do
- IO::Buffer.string(-1)
- end
- end
-
def test_resize_mapped
buffer = IO::Buffer.new
@@ -199,14 +180,6 @@ class TestIOBuffer < Test::Unit::TestCase
assert_positive buffer2 <=> buffer1
end
- def test_compare_zero_length
- buffer1 = IO::Buffer.new(0)
- buffer2 = IO::Buffer.new(1)
-
- assert_negative buffer1 <=> buffer2
- assert_positive buffer2 <=> buffer1
- end
-
def test_slice
buffer = IO::Buffer.new(128)
slice = buffer.slice(8, 32)
@@ -214,26 +187,16 @@ class TestIOBuffer < Test::Unit::TestCase
assert_equal("Hello World", buffer.get_string(8, 11))
end
- def test_slice_arguments
- buffer = IO::Buffer.for("Hello World")
-
- slice = buffer.slice
- assert_equal "Hello World", slice.get_string
-
- slice = buffer.slice(2)
- assert_equal("llo World", slice.get_string)
- end
-
- def test_slice_bounds_error
+ def test_slice_bounds
buffer = IO::Buffer.new(128)
assert_raise ArgumentError do
buffer.slice(128, 10)
end
- assert_raise ArgumentError do
- buffer.slice(-10, 10)
- end
+ # assert_raise RuntimeError do
+ # pp buffer.slice(-10, 10)
+ # end
end
def test_locked
@@ -265,25 +228,13 @@ class TestIOBuffer < Test::Unit::TestCase
chunk = buffer.get_string(0, message.bytesize, Encoding::BINARY)
assert_equal Encoding::BINARY, chunk.encoding
- assert_raise_with_message(ArgumentError, /bigger than the buffer size/) do
+ assert_raise_with_message(ArgumentError, /exceeds buffer size/) do
buffer.get_string(0, 129)
end
- assert_raise_with_message(ArgumentError, /bigger than the buffer size/) do
+ assert_raise_with_message(ArgumentError, /exceeds buffer size/) do
buffer.get_string(129)
end
-
- assert_raise_with_message(ArgumentError, /Offset can't be negative/) do
- buffer.get_string(-1)
- end
- end
-
- def test_zero_length_get_string
- buffer = IO::Buffer.new.slice(0, 0)
- assert_equal "", buffer.get_string
-
- buffer = IO::Buffer.new(0)
- assert_equal "", buffer.get_string
end
# We check that values are correctly round tripped.
@@ -310,78 +261,17 @@ class TestIOBuffer < Test::Unit::TestCase
:F64 => [-1.0, 0.0, 0.5, 1.0, 128.0],
}
- def test_get_set_value
+ def test_get_set_primitives
buffer = IO::Buffer.new(128)
- RANGES.each do |data_type, values|
+ RANGES.each do |type, values|
values.each do |value|
- buffer.set_value(data_type, 0, value)
- assert_equal value, buffer.get_value(data_type, 0), "Converting #{value} as #{data_type}."
+ buffer.set_value(type, 0, value)
+ assert_equal value, buffer.get_value(type, 0), "Converting #{value} as #{type}."
end
end
end
- def test_get_set_values
- buffer = IO::Buffer.new(128)
-
- RANGES.each do |data_type, values|
- format = [data_type] * values.size
-
- buffer.set_values(format, 0, values)
- assert_equal values, buffer.get_values(format, 0), "Converting #{values} as #{format}."
- end
- end
-
- def test_zero_length_get_set_values
- buffer = IO::Buffer.new(0)
-
- assert_equal [], buffer.get_values([], 0)
- assert_equal 0, buffer.set_values([], 0, [])
- end
-
- def test_values
- buffer = IO::Buffer.new(128)
-
- RANGES.each do |data_type, values|
- format = [data_type] * values.size
-
- buffer.set_values(format, 0, values)
- assert_equal values, buffer.values(data_type, 0, values.size), "Reading #{values} as #{format}."
- end
- end
-
- def test_each
- buffer = IO::Buffer.new(128)
-
- RANGES.each do |data_type, values|
- format = [data_type] * values.size
- data_type_size = IO::Buffer.size_of(data_type)
- values_with_offsets = values.map.with_index{|value, index| [index * data_type_size, value]}
-
- buffer.set_values(format, 0, values)
- assert_equal values_with_offsets, buffer.each(data_type, 0, values.size).to_a, "Reading #{values} as #{data_type}."
- end
- end
-
- def test_zero_length_each
- buffer = IO::Buffer.new(0)
-
- assert_equal [], buffer.each(:U8).to_a
- end
-
- def test_each_byte
- string = "The quick brown fox jumped over the lazy dog."
- buffer = IO::Buffer.for(string)
-
- assert_equal string.bytes, buffer.each_byte.to_a
- end
-
- def test_zero_length_each_byte
- buffer = IO::Buffer.new(0)
-
- assert_equal [], buffer.each_byte.to_a
- end
-
def test_clear
buffer = IO::Buffer.new(16)
buffer.set_string("Hello World!")
@@ -413,38 +303,17 @@ class TestIOBuffer < Test::Unit::TestCase
input.close
end
- def hello_world_tempfile
+ def test_read
io = Tempfile.new
io.write("Hello World")
io.seek(0)
- yield io
- ensure
- io&.close!
- end
-
- def test_read
- hello_world_tempfile do |io|
- buffer = IO::Buffer.new(128)
- buffer.read(io)
- assert_equal "Hello", buffer.get_string(0, 5)
- end
- end
-
- def test_read_with_with_length
- hello_world_tempfile do |io|
- buffer = IO::Buffer.new(128)
- buffer.read(io, 5)
- assert_equal "Hello", buffer.get_string(0, 5)
- end
- end
+ buffer = IO::Buffer.new(128)
+ buffer.read(io, 5)
- def test_read_with_with_offset
- hello_world_tempfile do |io|
- buffer = IO::Buffer.new(128)
- buffer.read(io, nil, 6)
- assert_equal "Hello", buffer.get_string(6, 5)
- end
+ assert_equal "Hello", buffer.get_string(0, 5)
+ ensure
+ io.close!
end
def test_write
@@ -452,7 +321,7 @@ class TestIOBuffer < Test::Unit::TestCase
buffer = IO::Buffer.new(128)
buffer.set_string("Hello")
- buffer.write(io)
+ buffer.write(io, 5)
io.seek(0)
assert_equal "Hello", io.read(5)
@@ -466,7 +335,7 @@ class TestIOBuffer < Test::Unit::TestCase
io.seek(0)
buffer = IO::Buffer.new(128)
- buffer.pread(io, 6, 5)
+ buffer.pread(io, 5, 6)
assert_equal "World", buffer.get_string(0, 5)
assert_equal 0, io.tell
@@ -474,26 +343,12 @@ class TestIOBuffer < Test::Unit::TestCase
io.close!
end
- def test_pread_offset
- io = Tempfile.new
- io.write("Hello World")
- io.seek(0)
-
- buffer = IO::Buffer.new(128)
- buffer.pread(io, 6, 5, 6)
-
- assert_equal "World", buffer.get_string(6, 5)
- assert_equal 0, io.tell
- ensure
- io.close!
- end
-
def test_pwrite
io = Tempfile.new
buffer = IO::Buffer.new(128)
buffer.set_string("World")
- buffer.pwrite(io, 6, 5)
+ buffer.pwrite(io, 5, 6)
assert_equal 0, io.tell
@@ -502,74 +357,4 @@ class TestIOBuffer < Test::Unit::TestCase
ensure
io.close!
end
-
- def test_pwrite_offset
- io = Tempfile.new
-
- buffer = IO::Buffer.new(128)
- buffer.set_string("Hello World")
- buffer.pwrite(io, 6, 5, 6)
-
- assert_equal 0, io.tell
-
- io.seek(6)
- assert_equal "World", io.read(5)
- ensure
- io.close!
- end
-
- def test_operators
- source = IO::Buffer.for("1234123412")
- mask = IO::Buffer.for("133\x00")
-
- assert_equal IO::Buffer.for("123\x00123\x0012"), (source & mask)
- assert_equal IO::Buffer.for("1334133413"), (source | mask)
- assert_equal IO::Buffer.for("\x00\x01\x004\x00\x01\x004\x00\x01"), (source ^ mask)
- assert_equal IO::Buffer.for("\xce\xcd\xcc\xcb\xce\xcd\xcc\xcb\xce\xcd"), ~source
- end
-
- def test_inplace_operators
- source = IO::Buffer.for("1234123412")
- mask = IO::Buffer.for("133\x00")
-
- assert_equal IO::Buffer.for("123\x00123\x0012"), source.dup.and!(mask)
- assert_equal IO::Buffer.for("1334133413"), source.dup.or!(mask)
- assert_equal IO::Buffer.for("\x00\x01\x004\x00\x01\x004\x00\x01"), source.dup.xor!(mask)
- assert_equal IO::Buffer.for("\xce\xcd\xcc\xcb\xce\xcd\xcc\xcb\xce\xcd"), source.dup.not!
- end
-
- def test_shared
- message = "Hello World"
- buffer = IO::Buffer.new(64, IO::Buffer::MAPPED | IO::Buffer::SHARED)
-
- pid = fork do
- buffer.set_string(message)
- end
-
- Process.wait(pid)
- string = buffer.get_string(0, message.bytesize)
- assert_equal message, string
- rescue NotImplementedError
- omit "Fork/shared memory is not supported."
- end
-
- def test_private
- Tempfile.create(%w"buffer .txt") do |file|
- file.write("Hello World")
-
- buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::PRIVATE)
- begin
- assert buffer.private?
- refute buffer.readonly?
-
- buffer.set_string("J")
-
- # It was not changed because the mapping was private:
- file.seek(0)
- assert_equal "Hello World", file.read
- ensure
- buffer&.free
- end
- end
- end
end
diff --git a/test/ruby/test_io_m17n.rb b/test/ruby/test_io_m17n.rb
index b01d627d92..27b16a2a36 100644
--- a/test/ruby/test_io_m17n.rb
+++ b/test/ruby/test_io_m17n.rb
@@ -1142,94 +1142,12 @@ EOT
IO.pipe do |r, w|
assert_nothing_raised(bug5567) do
assert_warning(/Unsupported/, bug5567) {r.set_encoding("fffffffffffxx")}
- w.puts("foo")
- assert_equal("foo\n", r.gets)
assert_warning(/Unsupported/, bug5567) {r.set_encoding("fffffffffffxx", "us-ascii")}
- w.puts("bar")
- assert_equal("bar\n", r.gets)
assert_warning(/Unsupported/, bug5567) {r.set_encoding("us-ascii", "fffffffffffxx")}
- w.puts("zot")
- begin
- assert_equal("zot\n", r.gets)
- rescue Encoding::ConverterNotFoundError => e
- assert_match(/\((\S+) to \1\)/, e.message)
- end
end
end
end
- def test_set_encoding_argument_parsing
- File.open(File::NULL) do |f|
- f.set_encoding('binary')
- assert_equal(Encoding::ASCII_8BIT, f.external_encoding)
- end
-
- File.open(File::NULL) do |f|
- f.set_encoding(Encoding.find('binary'))
- assert_equal(Encoding::ASCII_8BIT, f.external_encoding)
- end
-
- File.open(File::NULL) do |f|
- f.set_encoding('binary:utf-8')
- assert_equal(nil, f.internal_encoding)
- assert_equal(Encoding::ASCII_8BIT, f.external_encoding)
- end
-
- File.open(File::NULL) do |f|
- f.set_encoding('binary', 'utf-8')
- assert_equal(nil, f.internal_encoding)
- assert_equal(Encoding::ASCII_8BIT, f.external_encoding)
- end
-
- File.open(File::NULL) do |f|
- f.set_encoding(Encoding.find('binary'), Encoding.find('utf-8'))
- assert_equal(nil, f.internal_encoding)
- assert_equal(Encoding::ASCII_8BIT, f.external_encoding)
- end
-
- File.open(File::NULL) do |f|
- f.set_encoding('binary', Encoding.find('utf-8'))
- assert_equal(nil, f.internal_encoding)
- assert_equal(Encoding::ASCII_8BIT, f.external_encoding)
- end
-
- File.open(File::NULL) do |f|
- f.set_encoding(Encoding.find('binary'), 'utf-8')
- assert_equal(nil, f.internal_encoding)
- assert_equal(Encoding::ASCII_8BIT, f.external_encoding)
- end
-
- File.open(File::NULL) do |f|
- f.set_encoding('iso-8859-1:utf-8')
- assert_equal(Encoding::UTF_8, f.internal_encoding)
- assert_equal(Encoding::ISO_8859_1, f.external_encoding)
- end
-
- File.open(File::NULL) do |f|
- f.set_encoding('iso-8859-1', 'utf-8')
- assert_equal(Encoding::UTF_8, f.internal_encoding)
- assert_equal(Encoding::ISO_8859_1, f.external_encoding)
- end
-
- File.open(File::NULL) do |f|
- f.set_encoding(Encoding.find('iso-8859-1'), Encoding.find('utf-8'))
- assert_equal(Encoding::UTF_8, f.internal_encoding)
- assert_equal(Encoding::ISO_8859_1, f.external_encoding)
- end
-
- File.open(File::NULL) do |f|
- f.set_encoding('iso-8859-1', Encoding.find('utf-8'))
- assert_equal(Encoding::UTF_8, f.internal_encoding)
- assert_equal(Encoding::ISO_8859_1, f.external_encoding)
- end
-
- File.open(File::NULL) do |f|
- f.set_encoding(Encoding.find('iso-8859-1'), 'utf-8')
- assert_equal(Encoding::UTF_8, f.internal_encoding)
- assert_equal(Encoding::ISO_8859_1, f.external_encoding)
- end
- end
-
def test_textmode_twice
assert_raise(ArgumentError) {
open(__FILE__, "rt", textmode: true) {|f|
@@ -1396,27 +1314,23 @@ EOT
end
def test_open_pipe_r_enc
- EnvUtil.suppress_warning do # https://bugs.ruby-lang.org/issues/19630
- open("|#{EnvUtil.rubybin} -e 'putc 255'", "r:ascii-8bit") {|f|
- assert_equal(Encoding::ASCII_8BIT, f.external_encoding)
- assert_equal(nil, f.internal_encoding)
- s = f.read
- assert_equal(Encoding::ASCII_8BIT, s.encoding)
- assert_equal("\xff".force_encoding("ascii-8bit"), s)
- }
- end
+ open("|#{EnvUtil.rubybin} -e 'putc 255'", "r:ascii-8bit") {|f|
+ assert_equal(Encoding::ASCII_8BIT, f.external_encoding)
+ assert_equal(nil, f.internal_encoding)
+ s = f.read
+ assert_equal(Encoding::ASCII_8BIT, s.encoding)
+ assert_equal("\xff".force_encoding("ascii-8bit"), s)
+ }
end
def test_open_pipe_r_enc2
- EnvUtil.suppress_warning do # https://bugs.ruby-lang.org/issues/19630
- open("|#{EnvUtil.rubybin} -e 'putc \"\\u3042\"'", "r:UTF-8") {|f|
- assert_equal(Encoding::UTF_8, f.external_encoding)
- assert_equal(nil, f.internal_encoding)
- s = f.read
- assert_equal(Encoding::UTF_8, s.encoding)
- assert_equal("\u3042", s)
- }
- end
+ open("|#{EnvUtil.rubybin} -e 'putc \"\\u3042\"'", "r:UTF-8") {|f|
+ assert_equal(Encoding::UTF_8, f.external_encoding)
+ assert_equal(nil, f.internal_encoding)
+ s = f.read
+ assert_equal(Encoding::UTF_8, s.encoding)
+ assert_equal("\u3042", s)
+ }
end
def test_s_foreach_enc
diff --git a/test/ruby/test_io_timeout.rb b/test/ruby/test_io_timeout.rb
deleted file mode 100644
index e017395980..0000000000
--- a/test/ruby/test_io_timeout.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-# frozen_string_literal: false
-
-require 'io/nonblock'
-
-class TestIOTimeout < Test::Unit::TestCase
- def with_pipe
- omit "UNIXSocket is not defined!" unless defined?(UNIXSocket)
-
- begin
- i, o = UNIXSocket.pair
-
- yield i, o
- ensure
- i.close
- o.close
- end
- end
-
- def test_timeout_attribute
- with_pipe do |i, o|
- assert_nil i.timeout
-
- i.timeout = 10
- assert_equal 10, i.timeout
- assert_nil o.timeout
-
- o.timeout = 20
- assert_equal 20, o.timeout
- assert_equal 10, i.timeout
- end
- end
-
- def test_timeout_read_exception
- with_pipe do |i, o|
- i.timeout = 0.0001
-
- assert_raise(IO::TimeoutError) {i.read}
- end
- end
-
- def test_timeout_gets_exception
- with_pipe do |i, o|
- i.timeout = 0.0001
-
- assert_raise(IO::TimeoutError) {i.gets}
- end
- end
-
- def test_timeout_puts
- with_pipe do |i, o|
- i.timeout = 0.0001
- o.puts("Hello World")
- o.close
-
- assert_equal "Hello World", i.gets.chomp
- end
- end
-end
diff --git a/test/ruby/test_iseq.rb b/test/ruby/test_iseq.rb
index b0896511d8..f01d36cc5a 100644
--- a/test/ruby/test_iseq.rb
+++ b/test/ruby/test_iseq.rb
@@ -162,7 +162,7 @@ class TestISeq < Test::Unit::TestCase
end
obj = Object.new
def obj.foo(*) nil.instance_eval{ ->{super} } end
- assert_raise_with_message(Ractor::IsolationError, /refer unshareable object \[\] from variable `\*'/) do
+ assert_raise_with_message(Ractor::IsolationError, /hidden variable/) do
Ractor.make_shareable(obj.foo)
end
end
@@ -355,13 +355,6 @@ class TestISeq < Test::Unit::TestCase
end
end
- # [Bug #19173]
- def test_compile_error
- assert_raise SyntaxError do
- RubyVM::InstructionSequence.compile 'using Module.new; yield'
- end
- end
-
def test_compile_file_error
Tempfile.create(%w"test_iseq .rb") do |f|
f.puts "end"
@@ -399,18 +392,10 @@ class TestISeq < Test::Unit::TestCase
def anon_star(*); end
- def test_anon_rest_param_in_disasm
+ def test_anon_param_in_disasm
iseq = RubyVM::InstructionSequence.of(method(:anon_star))
param_names = iseq.to_a[iseq.to_a.index(:method) + 1]
- assert_equal [:*], param_names
- end
-
- def anon_keyrest(**); end
-
- def test_anon_keyrest_param_in_disasm
- iseq = RubyVM::InstructionSequence.of(method(:anon_keyrest))
- param_names = iseq.to_a[iseq.to_a.index(:method) + 1]
- assert_equal [:**], param_names
+ assert_equal [2], param_names
end
def anon_block(&); end
@@ -497,8 +482,7 @@ class TestISeq < Test::Unit::TestCase
[7, :line],
[9, :return]]],
[["ensure in foo@2", [[7, :line]]]],
- [["rescue in foo@4", [[5, :line],
- [5, :rescue]]]]]],
+ [["rescue in foo@4", [[5, :line]]]]]],
[["<class:D>@17", [[17, :class],
[18, :end]]]]], collect_iseq.call(sample_iseq)
end
@@ -547,7 +531,7 @@ class TestISeq < Test::Unit::TestCase
bin = assert_nothing_raised(mesg) do
iseq.to_binary
rescue RuntimeError => e
- omit e.message if /compile with coverage/ =~ e.message
+ skip e.message if /compile with coverage/ =~ e.message
raise
end
10.times do
@@ -638,8 +622,6 @@ class TestISeq < Test::Unit::TestCase
}
lines
- ensure
- Object.send(:remove_const, :A) rescue nil
end
def test_to_binary_line_tracepoint
@@ -760,53 +742,4 @@ class TestISeq < Test::Unit::TestCase
assert_equal :new, r.take
RUBY
end
-
- def test_ever_condition_loop
- assert_ruby_status([], "BEGIN {exit}; while true && true; end")
- end
-
- def test_unreachable_syntax_error
- mesg = /Invalid break/
- assert_syntax_error("false and break", mesg)
- assert_syntax_error("if false and break; end", mesg)
- end
-
- def test_unreachable_pattern_matching
- assert_in_out_err([], "#{<<~"begin;"}\n#{<<~'end;'}", %w[1])
- begin;
- if true or {a: 0} in {a:}
- p 1
- else
- p a
- end
- end;
- end
-
- def test_loading_kwargs_memory_leak
- assert_no_memory_leak([], "#{<<~"begin;"}", "#{<<~'end;'}", rss: true)
- a = RubyVM::InstructionSequence.compile("foo(bar: :baz)").to_binary
- begin;
- 1_000_000.times do
- RubyVM::InstructionSequence.load_from_binary(a)
- end
- end;
- end
-
- def test_ibf_bignum
- iseq = RubyVM::InstructionSequence.compile("0x0"+"_0123_4567_89ab_cdef"*5)
- expected = iseq.eval
- result = RubyVM::InstructionSequence.load_from_binary(iseq.to_binary).eval
- assert_equal expected, result, proc {sprintf("expected: %x, result: %x", expected, result)}
- end
-
- def test_compile_prism_with_file
- Tempfile.create(%w"test_iseq .rb") do |f|
- f.puts "name = 'Prism'; puts 'hello"
- f.close
-
- assert_nothing_raised(SyntaxError) {
- RubyVM::InstructionSequence.compile_prism(f.path)
- }
- end
- end
end
diff --git a/test/ruby/test_jit.rb b/test/ruby/test_jit.rb
new file mode 100644
index 0000000000..07ac76210d
--- /dev/null
+++ b/test/ruby/test_jit.rb
@@ -0,0 +1,1273 @@
+# 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/,
+ /\AJIT cancel: .+\n\z/,
+ /\ASuccessful MJIT finish\n\z/,
+ ]
+ MAX_CACHE_PATTERNS = [
+ /\AJIT compaction \([^)]+\): .+\n\z/,
+ /\AToo many JIT code, but skipped unloading units for JIT compaction\n\z/,
+ /\ANo units can be unloaded -- .+\n\z/,
+ ]
+
+ # trace_* insns are not compiled for now...
+ TEST_PENDING_INSNS = RubyVM::INSTRUCTION_NAMES.select { |n| n.start_with?('trace_') }.map(&:to_sym) + [
+ # not supported yet
+ :defineclass,
+
+ # to be tested
+ :invokebuiltin,
+
+ # never used
+ :opt_invokebuiltin_delegate,
+ ].each do |insn|
+ if !RubyVM::INSTRUCTION_NAMES.include?(insn.to_s)
+ warn "instruction #{insn.inspect} is not defined but included in TestJIT::TEST_PENDING_INSNS"
+ end
+ end
+
+ def self.untested_insns
+ @untested_insns ||= (RubyVM::INSTRUCTION_NAMES.map(&:to_sym) - TEST_PENDING_INSNS)
+ end
+
+ def self.setup
+ return if defined?(@setup_hooked)
+ @setup_hooked = true
+
+ # ci.rvm.jp caches its build environment. Clean up temporary files left by SEGV.
+ if ENV['RUBY_DEBUG']&.include?('ci')
+ Dir.glob("#{ENV.fetch('TMPDIR', '/tmp')}/_ruby_mjit_p*u*.*").each do |file|
+ puts "test/ruby/test_jit.rb: removing #{file}"
+ File.unlink(file)
+ end
+ end
+
+ # ruby -w -Itest/lib test/ruby/test_jit.rb
+ if $VERBOSE
+ pid = $$
+ at_exit do
+ if pid == $$ && !TestJIT.untested_insns.empty?
+ warn "you may want to add tests for following insns, when you have a chance: #{TestJIT.untested_insns.join(' ')}"
+ end
+ end
+ end
+ end
+
+ def setup
+ unless JITSupport.supported?
+ skip 'JIT seems not supported on this platform'
+ end
+ self.class.setup
+ end
+
+ def test_compile_insn_nop
+ assert_compile_once('nil rescue true', result_inspect: 'nil', insns: %i[nop])
+ end
+
+ def test_compile_insn_local
+ assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1', insns: %i[setlocal_WC_0 getlocal_WC_0])
+ begin;
+ foo = 1
+ foo
+ end;
+
+ insns = %i[setlocal getlocal setlocal_WC_0 getlocal_WC_0 setlocal_WC_1 getlocal_WC_1]
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", success_count: 3, stdout: '168', insns: insns)
+ begin;
+ def foo
+ a = 0
+ [1, 2].each do |i|
+ a += i
+ [3, 4].each do |j|
+ a *= j
+ end
+ end
+ a
+ end
+
+ print foo
+ end;
+ end
+
+ def test_compile_insn_blockparam
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '3', success_count: 2, insns: %i[getblockparam setblockparam])
+ begin;
+ def foo(&b)
+ a = b
+ b = 2
+ a.call + 2
+ end
+
+ print foo { 1 }
+ end;
+ end
+
+ def test_compile_insn_getblockparamproxy
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '4', success_count: 3, insns: %i[getblockparamproxy])
+ begin;
+ def bar(&b)
+ b.call
+ end
+
+ def foo(&b)
+ bar(&b) * bar(&b)
+ end
+
+ print foo { 2 }
+ end;
+ end
+
+ def test_compile_insn_getspecial
+ assert_compile_once('$1', result_inspect: 'nil', insns: %i[getspecial])
+ end
+
+ def test_compile_insn_setspecial
+ assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: 'true', insns: %i[setspecial])
+ begin;
+ true if nil.nil?..nil.nil?
+ end;
+ end
+
+ def test_compile_insn_instancevariable
+ assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1', insns: %i[getinstancevariable setinstancevariable])
+ begin;
+ @foo = 1
+ @foo
+ end;
+
+ # optimized getinstancevariable call
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '33', success_count: 1, min_calls: 2)
+ begin;
+ class A
+ def initialize
+ @a = 1
+ @b = 2
+ end
+
+ def three
+ @a + @b
+ end
+ end
+
+ a = A.new
+ print(a.three) # set ic
+ print(a.three) # inlined ic
+ end;
+ end
+
+ def test_compile_insn_classvariable
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '1', success_count: 1, insns: %i[getclassvariable setclassvariable])
+ begin;
+ class Foo
+ def self.foo
+ @@foo = 1
+ @@foo
+ end
+ end
+
+ print Foo.foo
+ end;
+ end
+
+ def test_compile_insn_constant
+ assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1', insns: %i[getconstant setconstant])
+ begin;
+ FOO = 1
+ FOO
+ end;
+ end
+
+ def test_compile_insn_global
+ assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1', insns: %i[getglobal setglobal])
+ begin;
+ $foo = 1
+ $foo
+ end;
+ end
+
+ def test_compile_insn_putnil
+ assert_compile_once('nil', result_inspect: 'nil', insns: %i[putnil])
+ end
+
+ def test_compile_insn_putself
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'hello', success_count: 1, insns: %i[putself])
+ begin;
+ proc { print "hello" }.call
+ end;
+ end
+
+ def test_compile_insn_putobject
+ assert_compile_once('0', result_inspect: '0', insns: %i[putobject_INT2FIX_0_])
+ assert_compile_once('1', result_inspect: '1', insns: %i[putobject_INT2FIX_1_])
+ assert_compile_once('2', result_inspect: '2', insns: %i[putobject])
+ end
+
+ def test_compile_insn_definemethod_definesmethod
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'helloworld', success_count: 3, insns: %i[definemethod definesmethod])
+ begin;
+ print 1.times.map {
+ def method_definition
+ 'hello'
+ end
+
+ def self.smethod_definition
+ 'world'
+ end
+
+ method_definition + smethod_definition
+ }.join
+ end;
+ end
+
+ def test_compile_insn_putspecialobject
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'a', success_count: 2, insns: %i[putspecialobject])
+ begin;
+ print 1.times.map {
+ def a
+ 'a'
+ end
+
+ alias :b :a
+
+ b
+ }.join
+ end;
+ end
+
+ def test_compile_insn_putstring_concatstrings_objtostring
+ assert_compile_once('"a#{}b" + "c"', result_inspect: '"abc"', insns: %i[putstring concatstrings objtostring])
+ 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_reput
+ skip "write test"
+ end
+
+ def test_compile_insn_setn
+ assert_compile_once('[nil][0] = 1', result_inspect: '1', insns: %i[setn])
+ end
+
+ def test_compile_insn_adjuststack
+ assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: 'true', insns: %i[adjuststack])
+ begin;
+ x = [true]
+ x[0] ||= nil
+ x[0]
+ end;
+ end
+
+ def test_compile_insn_defined
+ assert_compile_once('defined?(a)', result_inspect: 'nil', insns: %i[defined])
+ end
+
+ def test_compile_insn_checkkeyword
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'true', success_count: 1, insns: %i[checkkeyword])
+ begin;
+ def test(x: rand)
+ x
+ end
+ print test(x: true)
+ end;
+ end
+
+ def test_compile_insn_tracecoverage
+ skip "write test"
+ end
+
+ def test_compile_insn_defineclass
+ skip "support this in mjit_compile (low priority)"
+ end
+
+ def test_compile_insn_send
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '1', success_count: 3, insns: %i[send])
+ begin;
+ print proc { yield_self { 1 } }.call
+ end;
+ end
+
+ def test_compile_insn_opt_str_freeze
+ assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '"foo"', insns: %i[opt_str_freeze])
+ begin;
+ 'foo'.freeze
+ end;
+ end
+
+ def test_compile_insn_opt_nil_p
+ assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: 'false', insns: %i[opt_nil_p])
+ begin;
+ nil.nil?.nil?
+ end;
+ end
+
+ def test_compile_insn_opt_str_uminus
+ assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '"bar"', insns: %i[opt_str_uminus])
+ begin;
+ -'bar'
+ end;
+ end
+
+ def test_compile_insn_opt_newarray_max
+ assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '2', insns: %i[opt_newarray_max])
+ begin;
+ a = 1
+ b = 2
+ [a, b].max
+ end;
+ end
+
+ def test_compile_insn_opt_newarray_min
+ assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1', insns: %i[opt_newarray_min])
+ begin;
+ a = 1
+ b = 2
+ [a, b].min
+ end;
+ end
+
+ def test_compile_insn_opt_send_without_block
+ assert_compile_once('print', result_inspect: 'nil', insns: %i[opt_send_without_block])
+ end
+
+ def test_compile_insn_invokesuper
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '3', success_count: 4, insns: %i[invokesuper])
+ begin;
+ mod = Module.new {
+ def test
+ super + 2
+ end
+ }
+ klass = Class.new {
+ prepend mod
+ def test
+ 1
+ end
+ }
+ print klass.new.test
+ end;
+ end
+
+ def test_compile_insn_invokeblock_leave
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '2', success_count: 2, insns: %i[invokeblock leave])
+ begin;
+ def foo
+ yield
+ end
+ print foo { 2 }
+ end;
+ end
+
+ def test_compile_insn_throw
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '4', success_count: 2, insns: %i[throw])
+ begin;
+ def test
+ proc do
+ if 1+1 == 1
+ return 3
+ else
+ return 4
+ end
+ 5
+ end.call
+ end
+ print test
+ end;
+ end
+
+ def test_compile_insn_jump_branchif
+ assert_compile_once("#{<<~"begin;"}\n#{<<~'end;'}", result_inspect: 'nil', insns: %i[jump branchif])
+ begin;
+ a = false
+ 1 + 1 while a
+ end;
+ end
+
+ def test_compile_insn_branchunless
+ assert_compile_once("#{<<~"begin;"}\n#{<<~'end;'}", result_inspect: '1', insns: %i[branchunless])
+ begin;
+ a = true
+ if a
+ 1
+ else
+ 2
+ end
+ end;
+ end
+
+ def test_compile_insn_branchnil
+ assert_compile_once("#{<<~"begin;"}\n#{<<~'end;'}", result_inspect: '3', insns: %i[branchnil])
+ begin;
+ a = 2
+ a&.+(1)
+ end;
+ end
+
+ def test_compile_insn_objtostring
+ assert_compile_once("#{<<~"begin;"}\n#{<<~'end;'}", result_inspect: '"42"', insns: %i[objtostring])
+ 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[opt_case_dispatch])
+ begin;
+ case 'hello'
+ when 'hello'
+ 'world'
+ end
+ end;
+ end
+
+ def test_compile_insn_opt_calc
+ assert_compile_once('4 + 2 - ((2 * 3 / 2) % 2)', result_inspect: '5', insns: %i[opt_plus opt_minus opt_mult opt_div opt_mod])
+ assert_compile_once('4.0 + 2.0 - ((2.0 * 3.0 / 2.0) % 2.0)', result_inspect: '5.0', insns: %i[opt_plus opt_minus opt_mult opt_div opt_mod])
+ assert_compile_once('4 + 2', result_inspect: '6')
+ end
+
+ def test_compile_insn_opt_cmp
+ assert_compile_once('(1 == 1) && (1 != 2)', result_inspect: 'true', insns: %i[opt_eq opt_neq])
+ end
+
+ def test_compile_insn_opt_rel
+ assert_compile_once('1 < 2 && 1 <= 1 && 2 > 1 && 1 >= 1', result_inspect: 'true', insns: %i[opt_lt opt_le opt_gt opt_ge])
+ end
+
+ def test_compile_insn_opt_ltlt
+ assert_compile_once('[1] << 2', result_inspect: '[1, 2]', insns: %i[opt_ltlt])
+ end
+
+ def test_compile_insn_opt_and
+ assert_compile_once('1 & 3', result_inspect: '1', insns: %i[opt_and])
+ end
+
+ def test_compile_insn_opt_or
+ assert_compile_once('1 | 3', result_inspect: '3', insns: %i[opt_or])
+ end
+
+ def test_compile_insn_opt_aref
+ # optimized call (optimized JIT) -> send call
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '21', success_count: 2, min_calls: 1, insns: %i[opt_aref])
+ begin;
+ obj = Object.new
+ def obj.[](h)
+ h
+ end
+
+ block = proc { |h| h[1] }
+ print block.call({ 1 => 2 })
+ print block.call(obj)
+ end;
+
+ # send call -> optimized call (send JIT) -> optimized call
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '122', success_count: 2, min_calls: 2)
+ begin;
+ obj = Object.new
+ def obj.[](h)
+ h
+ end
+
+ block = proc { |h| h[1] }
+ print block.call(obj)
+ print block.call({ 1 => 2 })
+ print block.call({ 1 => 2 })
+ end;
+ end
+
+ def test_compile_insn_opt_aref_with
+ assert_compile_once("{ '1' => 2 }['1']", result_inspect: '2', insns: %i[opt_aref_with])
+ end
+
+ def test_compile_insn_opt_aset
+ assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '5', insns: %i[opt_aset opt_aset_with])
+ begin;
+ hash = { '1' => 2 }
+ (hash['2'] = 2) + (hash[1.to_s] = 3)
+ end;
+ end
+
+ def test_compile_insn_opt_length_size
+ assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '4', insns: %i[opt_length opt_size])
+ begin;
+ array = [1, 2]
+ array.length + array.size
+ end;
+ end
+
+ def test_compile_insn_opt_empty_p
+ assert_compile_once('[].empty?', result_inspect: 'true', insns: %i[opt_empty_p])
+ end
+
+ def test_compile_insn_opt_succ
+ assert_compile_once('1.succ', result_inspect: '2', insns: %i[opt_succ])
+ end
+
+ def test_compile_insn_opt_not
+ assert_compile_once('!!true', result_inspect: 'true', insns: %i[opt_not])
+ end
+
+ def test_compile_insn_opt_regexpmatch2
+ assert_compile_once("/true/ =~ 'true'", result_inspect: '0', insns: %i[opt_regexpmatch2])
+ assert_compile_once("'true' =~ /true/", result_inspect: '0', insns: %i[opt_regexpmatch2])
+ end
+
+ def test_compile_insn_opt_invokebuiltin_delegate_leave
+ iseq = eval(EnvUtil.invoke_ruby(['-e', <<~'EOS'], '', true).first)
+ p RubyVM::InstructionSequence.of("\x00".method(:unpack)).to_a
+ EOS
+ insns = collect_insns(iseq)
+ mark_tested_insn(:opt_invokebuiltin_delegate_leave, used_insns: insns)
+ assert_eval_with_jit('print "\x00".unpack("c")', stdout: '[0]', success_count: 1)
+ end
+
+ def test_compile_insn_checkmatch
+ assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '"world"', insns: %i[checkmatch])
+ begin;
+ ary = %w(hello good-bye)
+ case 'hello'
+ when *ary
+ 'world'
+ end
+ end;
+ end
+
+ def test_jit_output
+ out, err = eval_with_jit('5.times { puts "MJIT" }', verbose: 1, min_calls: 5)
+ assert_equal("MJIT\n" * 5, out)
+ assert_match(/^#{JIT_SUCCESS_PREFIX}: block in <main>@-e:1 -> .+_ruby_mjit_p\d+u\d+\.c$/, err)
+ assert_match(/^Successful MJIT finish$/, err)
+ end
+
+ def test_nothing_to_unload_with_jit_wait
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'hello', success_count: 11, max_cache: 10, ignorable_patterns: MAX_CACHE_PATTERNS)
+ begin;
+ def a1() a2() end
+ def a2() a3() end
+ def a3() a4() end
+ def a4() a5() end
+ def a5() a6() end
+ def a6() a7() end
+ def a7() a8() end
+ def a8() a9() end
+ def a9() a10() end
+ def a10() a11() end
+ def a11() print('hello') end
+ a1
+ end;
+ end
+
+ def test_unload_units_on_fiber
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'hello', success_count: 12, max_cache: 10, ignorable_patterns: MAX_CACHE_PATTERNS)
+ begin;
+ def a1() a2(false); a2(true) end
+ def a2(a) a3(a) end
+ def a3(a) a4(a) end
+ def a4(a) a5(a) end
+ def a5(a) a6(a) end
+ def a6(a) a7(a) end
+ def a7(a) a8(a) end
+ def a8(a) a9(a) end
+ def a9(a) a10(a) end
+ def a10(a)
+ if a
+ Fiber.new { a11 }.resume
+ end
+ end
+ def a11() print('hello') end
+ a1
+ end;
+ end
+
+ def test_unload_units_and_compaction
+ Dir.mktmpdir("jit_test_unload_units_") do |dir|
+ # MIN_CACHE_SIZE is 10
+ out, err = eval_with_jit({"TMPDIR"=>dir}, "#{<<~"begin;"}\n#{<<~'end;'}", verbose: 1, min_calls: 1, max_cache: 10)
+ begin;
+ i = 0
+ while i < 11
+ eval(<<-EOS)
+ def mjit#{i}
+ print #{i}
+ end
+ mjit#{i}
+ EOS
+ i += 1
+ end
+
+ if defined?(fork)
+ # test the child does not try to delete files which are deleted by parent,
+ # and test possible deadlock on fork during MJIT unload and JIT compaction on child
+ Process.waitpid(Process.fork {})
+ end
+ end;
+
+ debug_info = %Q[stdout:\n"""\n#{out}\n"""\n\nstderr:\n"""\n#{err}"""\n]
+ assert_equal('012345678910', out, debug_info)
+ compactions, errs = err.lines.partition do |l|
+ l.match?(/\AJIT compaction \(\d+\.\dms\): Compacted \d+ methods /)
+ end
+ 10.times do |i|
+ assert_match(/\A#{JIT_SUCCESS_PREFIX}: mjit#{i}@\(eval\):/, errs[i], debug_info)
+ end
+
+ assert_equal("No units can be unloaded -- incremented max-cache-size to 11 for --jit-wait\n", errs[10], debug_info)
+ assert_match(/\A#{JIT_SUCCESS_PREFIX}: mjit10@\(eval\):/, errs[11], debug_info)
+ # On --jit-wait, when the number of JIT-ed code reaches --jit-max-cache,
+ # it should trigger compaction.
+ unless RUBY_PLATFORM.match?(/mswin|mingw/) # compaction is not supported on Windows yet
+ assert_equal(1, compactions.size, debug_info)
+ end
+
+ if RUBY_PLATFORM.match?(/mswin/)
+ # "Permission Denied" error is preventing to remove so file on AppVeyor/RubyCI.
+ skip 'Removing so file is randomly failing on AppVeyor/RubyCI mswin due to Permission Denied.'
+ else
+ # verify .c files are deleted on unload_units
+ assert_send([Dir, :empty?, dir], debug_info)
+ end
+ end
+ end
+
+ def test_newarraykwsplat_on_stack
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "[nil, [{:type=>:development}]]\n", success_count: 1, insns: %i[newarraykwsplat])
+ begin;
+ def arr
+ [nil, [:type => :development]]
+ end
+ p arr
+ end;
+ end
+
+ def test_local_stack_on_exception
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '3', success_count: 2)
+ begin;
+ def b
+ raise
+ rescue
+ 2
+ end
+
+ def a
+ # Calling #b should be vm_exec, not direct mjit_exec.
+ # Otherwise `1` on local variable would be purged.
+ 1 + b
+ end
+
+ print a
+ end;
+ end
+
+ def test_local_stack_with_sp_motion_by_blockargs
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '1', success_count: 2)
+ begin;
+ def b(base)
+ 1
+ end
+
+ # This method is simple enough to have false in catch_except_p.
+ # So local_stack_p would be true in JIT compiler.
+ def a
+ m = method(:b)
+
+ # ci->flag has VM_CALL_ARGS_BLOCKARG and cfp->sp is moved in vm_caller_setup_arg_block.
+ # So, for this send insn, JIT-ed code should use cfp->sp instead of local variables for stack.
+ Module.module_eval(&m)
+ end
+
+ print a
+ end;
+ end
+
+ def test_catching_deep_exception
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '1', success_count: 4)
+ begin;
+ def catch_true(paths, prefixes) # catch_except_p: TRUE
+ prefixes.each do |prefix| # catch_except_p: TRUE
+ paths.each do |path| # catch_except_p: FALSE
+ return path
+ end
+ end
+ end
+
+ def wrapper(paths, prefixes)
+ catch_true(paths, prefixes)
+ end
+
+ print wrapper(['1'], ['2'])
+ end;
+ end
+
+ def test_inlined_builtin_methods
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '', success_count: 1, min_calls: 2)
+ begin;
+ def test
+ float = 0.0
+ float.abs
+ float.-@
+ float.zero?
+ end
+ test
+ test
+ end;
+ end
+
+ def test_inlined_c_method
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "aaa", success_count: 2, recompile_count: 1, min_calls: 2)
+ begin;
+ def test(obj, recursive: nil)
+ if recursive
+ test(recursive)
+ end
+ obj.to_s
+ end
+
+ print(test('a')) # set #to_s cc to String#to_s (expecting C method)
+ print(test('a')) # JIT with #to_s cc: String#to_s
+ # update #to_s cd->cc to Symbol#to_s, then go through the Symbol#to_s cd->cc
+ # after checking receiver class using inlined #to_s cc with String#to_s.
+ print(test('a', recursive: :foo))
+ end;
+ end
+
+ def test_inlined_exivar
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "aaa", success_count: 3, recompile_count: 1, min_calls: 2)
+ begin;
+ class Foo < Hash
+ def initialize
+ @a = :a
+ end
+
+ def bar
+ @a
+ end
+ end
+
+ print(Foo.new.bar)
+ print(Foo.new.bar) # compile #initialize, #bar -> recompile #bar
+ print(Foo.new.bar) # compile #bar with exivar
+ end;
+ end
+
+ def test_inlined_undefined_ivar
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "bbb", success_count: 3, min_calls: 3)
+ begin;
+ class Foo
+ def initialize
+ @a = :a
+ end
+
+ def bar
+ if @b.nil?
+ @b = :b
+ end
+ end
+ end
+
+ print(Foo.new.bar)
+ print(Foo.new.bar)
+ print(Foo.new.bar)
+ end;
+ end
+
+ def test_inlined_setivar_frozen
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "FrozenError\n", success_count: 2, min_calls: 3)
+ begin;
+ class A
+ def a
+ @a = 1
+ end
+ end
+
+ a = A.new
+ a.a
+ a.a
+ a.a
+ a.freeze
+ begin
+ a.a
+ rescue FrozenError => e
+ p e.class
+ end
+ end;
+ end
+
+ def test_inlined_getconstant
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '11', success_count: 1, min_calls: 2)
+ begin;
+ FOO = 1
+ def const
+ FOO
+ end
+ print const
+ print const
+ end;
+ end
+
+ def test_attr_reader
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "4nil\nnil\n6", success_count: 2, min_calls: 2)
+ begin;
+ class A
+ attr_reader :a, :b
+
+ def initialize
+ @a = 2
+ end
+
+ def test
+ a
+ end
+
+ def undefined
+ b
+ end
+ end
+
+ a = A.new
+ print(a.test * a.test)
+ p(a.undefined)
+ p(a.undefined)
+
+ # redefinition
+ def a.test
+ 3
+ end
+
+ print(2 * a.test)
+ end;
+
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "true", success_count: 1, min_calls: 2)
+ begin;
+ class Hoge
+ attr_reader :foo
+
+ def initialize
+ @foo = []
+ @bar = nil
+ end
+ end
+
+ class Fuga < Hoge
+ def initialize
+ @bar = nil
+ @foo = []
+ end
+ end
+
+ def test(recv)
+ recv.foo.empty?
+ end
+
+ hoge = Hoge.new
+ fuga = Fuga.new
+
+ test(hoge) # VM: cc set index=1
+ test(hoge) # JIT: compile with index=1
+ test(fuga) # JIT -> VM: cc set index=2
+ print test(hoge) # JIT: should use index=1, not index=2 in cc
+ end;
+ end
+
+ def test_heap_promotion_of_ivar_in_the_middle_of_jit
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "true\ntrue\n", success_count: 2, min_calls: 2)
+ begin;
+ class A
+ def initialize
+ @iv0 = nil
+ @iv1 = []
+ @iv2 = nil
+ end
+
+ def test(add)
+ @iv0.nil?
+ @iv2.nil?
+ add_ivar if add
+ @iv1.empty?
+ end
+
+ def add_ivar
+ @iv3 = nil
+ end
+ end
+
+ a = A.new
+ p a.test(false)
+ p a.test(true)
+ end;
+ end
+
+ def test_jump_to_precompiled_branch
+ assert_eval_with_jit("#{<<~'begin;'}\n#{<<~'end;'}", stdout: ".0", success_count: 1, min_calls: 1)
+ begin;
+ def test(foo)
+ ".#{foo unless foo == 1}" if true
+ end
+ print test(0)
+ end;
+ end
+
+ def test_clean_so
+ if RUBY_PLATFORM.match?(/mswin/)
+ skip 'Removing so file is randomly failing on AppVeyor/RubyCI mswin due to Permission Denied.'
+ end
+ Dir.mktmpdir("jit_test_clean_so_") do |dir|
+ code = "x = 0; 10.times {|i|x+=i}"
+ eval_with_jit({"TMPDIR"=>dir}, code)
+ assert_send([Dir, :empty?, dir])
+ eval_with_jit({"TMPDIR"=>dir}, code, save_temps: true)
+ assert_not_send([Dir, :empty?, dir])
+ end
+ end
+
+ def test_clean_objects_on_exec
+ if /mswin|mingw/ =~ RUBY_PLATFORM
+ # TODO: check call stack and close handle of code which is not on stack, and remove objects on best-effort basis
+ skip 'Removing so file being used does not work on Windows'
+ end
+ Dir.mktmpdir("jit_test_clean_objects_on_exec_") do |dir|
+ eval_with_jit({"TMPDIR"=>dir}, "#{<<~"begin;"}\n#{<<~"end;"}", min_calls: 1)
+ begin;
+ def a; end; a
+ exec "true"
+ end;
+ error_message = "Undeleted files:\n #{Dir.glob("#{dir}/*").join("\n ")}\n"
+ assert_send([Dir, :empty?, dir], error_message)
+ end
+ end
+
+ def test_lambda_longjmp
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '5', success_count: 1)
+ begin;
+ fib = lambda do |x|
+ return x if x == 0 || x == 1
+ fib.call(x-1) + fib.call(x-2)
+ end
+ print fib.call(5)
+ end;
+ end
+
+ def test_stack_pointer_with_assignment
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "nil\nnil\n", success_count: 1)
+ begin;
+ 2.times do
+ a, _ = nil
+ p a
+ end
+ end;
+ end
+
+ def test_frame_omitted_inlining
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "true\ntrue\ntrue\n", success_count: 1, min_calls: 2)
+ begin;
+ class Integer
+ remove_method :zero?
+ def zero?
+ self == 0
+ end
+ end
+
+ 3.times do
+ p 0.zero?
+ end
+ end;
+ end
+
+ def test_block_handler_with_possible_frame_omitted_inlining
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "70.0\n70.0\n70.0\n", success_count: 2, min_calls: 2)
+ begin;
+ def multiply(a, b)
+ a *= b
+ end
+
+ 3.times do
+ p multiply(7.0, 10.0)
+ end
+ end;
+ end
+
+ def test_builtin_frame_omitted_inlining
+ assert_eval_with_jit('0.zero?; 0.zero?; 3.times { p 0.zero? }', stdout: "true\ntrue\ntrue\n", success_count: 1, min_calls: 2)
+ end
+
+ def test_program_counter_with_regexpmatch
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "aa", success_count: 1)
+ begin;
+ 2.times do
+ break if /a/ =~ "ab" && !$~[0]
+ print $~[0]
+ end
+ end;
+ end
+
+ def test_pushed_values_with_opt_aset_with
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "{}{}", success_count: 1)
+ begin;
+ 2.times do
+ print(Thread.current["a"] = {})
+ end
+ end;
+ end
+
+ def test_pushed_values_with_opt_aref_with
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "nil\nnil\n", success_count: 1)
+ begin;
+ 2.times do
+ p(Thread.current["a"])
+ end
+ end;
+ end
+
+ def test_mjit_pause_wait
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '', success_count: 0, min_calls: 1)
+ begin;
+ RubyVM::MJIT.pause
+ proc {}.call
+ end;
+ end
+
+ def test_not_cancel_by_tracepoint_class
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", success_count: 1, min_calls: 2)
+ begin;
+ TracePoint.new(:class) {}.enable
+ 2.times {}
+ end;
+ end
+
+ def test_cancel_by_tracepoint
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", success_count: 0, min_calls: 2)
+ begin;
+ TracePoint.new(:line) {}.enable
+ 2.times {}
+ end;
+ end
+
+ def test_caller_locations_without_catch_table
+ out, _ = eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", min_calls: 1)
+ begin;
+ def b # 2
+ caller_locations.first # 3
+ end # 4
+ # 5
+ def a # 6
+ print # <-- don't leave PC here # 7
+ b # 8
+ end
+ puts a
+ puts a
+ end;
+ lines = out.lines
+ assert_equal("-e:8:in `a'\n", lines[0])
+ assert_equal("-e:8:in `a'\n", lines[1])
+ end
+
+ def test_fork_with_mjit_worker_thread
+ Dir.mktmpdir("jit_test_fork_with_mjit_worker_thread_") do |dir|
+ # min_calls: 2 to skip fork block
+ out, err = eval_with_jit({ "TMPDIR" => dir }, "#{<<~"begin;"}\n#{<<~"end;"}", min_calls: 2, verbose: 1)
+ begin;
+ def before_fork; end
+ def after_fork; end
+
+ before_fork; before_fork # the child should not delete this .o file
+ pid = Process.fork do # this child should not delete shared .pch file
+ sleep 2.0 # to prevent mixing outputs on Solaris
+ after_fork; after_fork # this child does not share JIT-ed after_fork with parent
+ end
+ after_fork; after_fork # this parent does not share JIT-ed after_fork with child
+
+ Process.waitpid(pid)
+ end;
+ success_count = err.scan(/^#{JIT_SUCCESS_PREFIX}:/).size
+ debug_info = "stdout:\n```\n#{out}\n```\n\nstderr:\n```\n#{err}```\n"
+ assert_equal(3, success_count, debug_info)
+
+ # assert no remove error
+ assert_equal("Successful MJIT finish\n" * 2, err.gsub(/^#{JIT_SUCCESS_PREFIX}:[^\n]+\n/, ''), debug_info)
+
+ # ensure objects are deleted
+ assert_send([Dir, :empty?, dir], debug_info)
+ end
+ end if defined?(fork)
+
+ private
+
+ # The shortest way to test one proc
+ def assert_compile_once(script, result_inspect:, insns: [], uplevel: 1)
+ if script.match?(/\A\n.+\n\z/m)
+ script = script.gsub(/^/, ' ')
+ else
+ script = " #{script} "
+ end
+ assert_eval_with_jit("p proc {#{script}}.call", stdout: "#{result_inspect}\n", success_count: 1, insns: insns, uplevel: uplevel + 1)
+ end
+
+ # Shorthand for normal test cases
+ def assert_eval_with_jit(script, stdout: nil, success_count:, recompile_count: nil, min_calls: 1, max_cache: 1000, insns: [], uplevel: 1, ignorable_patterns: [])
+ out, err = eval_with_jit(script, verbose: 1, min_calls: min_calls, max_cache: max_cache)
+ success_actual = err.scan(/^#{JIT_SUCCESS_PREFIX}:/).size
+ recompile_actual = err.scan(/^#{JIT_RECOMPILE_PREFIX}:/).size
+ # Add --mjit-verbose=2 logs for cl.exe because compiler's error message is suppressed
+ # for cl.exe with --mjit-verbose=1. See `start_process` in mjit_worker.c.
+ if RUBY_PLATFORM.match?(/mswin/) && success_count != success_actual
+ out2, err2 = eval_with_jit(script, verbose: 2, min_calls: min_calls, max_cache: max_cache)
+ end
+
+ # Make sure that the script has insns expected to be tested
+ used_insns = method_insns(script)
+ insns.each do |insn|
+ mark_tested_insn(insn, used_insns: used_insns, uplevel: uplevel + 3)
+ end
+
+ suffix = "script:\n#{code_block(script)}\nstderr:\n#{code_block(err)}#{(
+ "\nstdout(verbose=2 retry):\n#{code_block(out2)}\nstderr(verbose=2 retry):\n#{code_block(err2)}" if out2 || err2
+ )}"
+ assert_equal(
+ success_count, success_actual,
+ "Expected #{success_count} times of JIT success, but succeeded #{success_actual} times.\n\n#{suffix}",
+ )
+ if recompile_count
+ assert_equal(
+ recompile_count, recompile_actual,
+ "Expected #{success_count} times of JIT recompile, but recompiled #{success_actual} times.\n\n#{suffix}",
+ )
+ end
+ if stdout
+ assert_equal(stdout, out, "Expected stdout #{out.inspect} to match #{stdout.inspect} with script:\n#{code_block(script)}")
+ end
+ err_lines = err.lines.reject! do |l|
+ l.chomp.empty? || l.match?(/\A#{JIT_SUCCESS_PREFIX}/) || (IGNORABLE_PATTERNS + ignorable_patterns).any? { |pat| pat.match?(l) }
+ end
+ unless err_lines.empty?
+ warn err_lines.join(''), uplevel: uplevel
+ end
+ end
+
+ def mark_tested_insn(insn, used_insns:, uplevel: 1)
+ # Currently, this check emits a false-positive warning against opt_regexpmatch2,
+ # so the insn is excluded explicitly. See https://bugs.ruby-lang.org/issues/18269
+ if !used_insns.include?(insn) && insn != :opt_regexpmatch2
+ $stderr.puts
+ warn "'#{insn}' insn is not included in the script. Actual insns are: #{used_insns.join(' ')}\n", uplevel: uplevel
+ end
+ TestJIT.untested_insns.delete(insn)
+ end
+
+ # Collect block's insns or defined method's insns, which are expected to be JIT-ed.
+ # Note that this intentionally excludes insns in script's toplevel because they are not JIT-ed.
+ def method_insns(script)
+ insns = []
+ RubyVM::InstructionSequence.compile(script).to_a.last.each do |(insn, *args)|
+ case insn
+ when :send
+ insns += collect_insns(args.last)
+ when :definemethod, :definesmethod
+ insns += collect_insns(args[1])
+ when :defineclass
+ insns += collect_insns(args[1])
+ end
+ end
+ insns.uniq
+ end
+
+ # Recursively collect insns in iseq_array
+ def collect_insns(iseq_array)
+ return [] if iseq_array.nil?
+
+ insns = iseq_array.last.select { |x| x.is_a?(Array) }.map(&:first)
+ iseq_array.last.each do |(insn, *args)|
+ case insn
+ when :definemethod, :definesmethod, :send
+ insns += collect_insns(args.last)
+ end
+ end
+ insns
+ end
+end
diff --git a/test/ruby/test_jit_debug.rb b/test/ruby/test_jit_debug.rb
new file mode 100644
index 0000000000..b8dc9416ef
--- /dev/null
+++ b/test/ruby/test_jit_debug.rb
@@ -0,0 +1,17 @@
+require_relative 'test_jit'
+
+return unless defined?(TestJIT)
+return if ENV.key?('APPVEYOR')
+return if ENV.key?('RUBYCI_NICKNAME')
+return if ENV['RUBY_DEBUG']&.include?('ci') # ci.rvm.jp
+return if /mswin/ =~ RUBY_PLATFORM
+
+class TestJITDebug < TestJIT
+ @@test_suites.delete TestJIT if self.respond_to? :on_parallel_worker?
+
+ def setup
+ super
+ # let `#eval_with_jit` use --mjit-debug
+ @mjit_debug = true
+ end
+end
diff --git a/test/ruby/test_keyword.rb b/test/ruby/test_keyword.rb
index 9aca787dff..9094259bc2 100644
--- a/test/ruby/test_keyword.rb
+++ b/test/ruby/test_keyword.rb
@@ -190,74 +190,27 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal(["bar", 111111], f[str: "bar", num: 111111])
end
- def test_unset_hash_flag
- bug18625 = "[ruby-core: 107847]"
- singleton_class.class_eval do
- ruby2_keywords def foo(*args)
- args
- end
-
- def single(arg)
- arg
- end
-
- def splat(*args)
- args.last
- end
-
- def kwargs(**kw)
- kw
- end
- end
-
- h = { a: 1 }
- args = foo(**h)
- marked = args.last
- assert_equal(true, Hash.ruby2_keywords_hash?(marked))
-
- after_usage = single(*args)
- assert_equal(h, after_usage)
- assert_same(marked, args.last)
- assert_not_same(marked, after_usage)
- assert_equal(false, Hash.ruby2_keywords_hash?(after_usage))
-
- after_usage = splat(*args)
- assert_equal(h, after_usage)
- assert_same(marked, args.last)
- assert_not_same(marked, after_usage, bug18625)
- assert_equal(false, Hash.ruby2_keywords_hash?(after_usage), bug18625)
-
- after_usage = kwargs(*args)
- assert_equal(h, after_usage)
- assert_same(marked, args.last)
- assert_not_same(marked, after_usage, bug18625)
- assert_not_same(marked, after_usage)
- assert_equal(false, Hash.ruby2_keywords_hash?(after_usage))
-
- assert_equal(true, Hash.ruby2_keywords_hash?(marked))
- end
-
- def assert_equal_not_same(kw, res)
- assert_instance_of(Hash, res)
- assert_equal(kw, res)
- assert_not_same(kw, res)
- end
-
def test_keyword_splat_new
kw = {}
h = {a: 1}
- def self.yo(**kw) kw end
- m = method(:yo)
- assert_equal(false, yo(**{}).frozen?)
- assert_equal_not_same(kw, yo(**kw))
- assert_equal_not_same(h, yo(**h))
- assert_equal(false, send(:yo, **{}).frozen?)
- assert_equal_not_same(kw, send(:yo, **kw))
- assert_equal_not_same(h, send(:yo, **h))
- assert_equal(false, public_send(:yo, **{}).frozen?)
- assert_equal_not_same(kw, public_send(:yo, **kw))
- assert_equal_not_same(h, public_send(:yo, **h))
+ def self.assert_equal_not_same(kw, res)
+ assert_instance_of(Hash, res)
+ assert_equal(kw, res)
+ assert_not_same(kw, res)
+ end
+
+ def self.y(**kw) kw end
+ m = method(:y)
+ assert_equal(false, y(**{}).frozen?)
+ assert_equal_not_same(kw, y(**kw))
+ assert_equal_not_same(h, y(**h))
+ assert_equal(false, send(:y, **{}).frozen?)
+ assert_equal_not_same(kw, send(:y, **kw))
+ assert_equal_not_same(h, send(:y, **h))
+ assert_equal(false, public_send(:y, **{}).frozen?)
+ assert_equal_not_same(kw, public_send(:y, **kw))
+ assert_equal_not_same(h, public_send(:y, **h))
assert_equal(false, m.(**{}).frozen?)
assert_equal_not_same(kw, m.(**kw))
assert_equal_not_same(h, m.(**h))
@@ -266,25 +219,25 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal_not_same(h, m.send(:call, **h))
m = method(:send)
- assert_equal(false, m.(:yo, **{}).frozen?)
- assert_equal_not_same(kw, m.(:yo, **kw))
- assert_equal_not_same(h, m.(:yo, **h))
- assert_equal(false, m.send(:call, :yo, **{}).frozen?)
- assert_equal_not_same(kw, m.send(:call, :yo, **kw))
- assert_equal_not_same(h, m.send(:call, :yo, **h))
-
- singleton_class.send(:remove_method, :yo)
- define_singleton_method(:yo) { |**kw| kw }
- m = method(:yo)
- assert_equal(false, yo(**{}).frozen?)
- assert_equal_not_same(kw, yo(**kw))
- assert_equal_not_same(h, yo(**h))
- assert_equal(false, send(:yo, **{}).frozen?)
- assert_equal_not_same(kw, send(:yo, **kw))
- assert_equal_not_same(h, send(:yo, **h))
- assert_equal(false, public_send(:yo, **{}).frozen?)
- assert_equal_not_same(kw, public_send(:yo, **kw))
- assert_equal_not_same(h, public_send(:yo, **h))
+ assert_equal(false, m.(:y, **{}).frozen?)
+ assert_equal_not_same(kw, m.(:y, **kw))
+ assert_equal_not_same(h, m.(:y, **h))
+ assert_equal(false, m.send(:call, :y, **{}).frozen?)
+ assert_equal_not_same(kw, m.send(:call, :y, **kw))
+ assert_equal_not_same(h, m.send(:call, :y, **h))
+
+ singleton_class.send(:remove_method, :y)
+ define_singleton_method(:y) { |**kw| kw }
+ m = method(:y)
+ assert_equal(false, y(**{}).frozen?)
+ assert_equal_not_same(kw, y(**kw))
+ assert_equal_not_same(h, y(**h))
+ assert_equal(false, send(:y, **{}).frozen?)
+ assert_equal_not_same(kw, send(:y, **kw))
+ assert_equal_not_same(h, send(:y, **h))
+ assert_equal(false, public_send(:y, **{}).frozen?)
+ assert_equal_not_same(kw, public_send(:y, **kw))
+ assert_equal_not_same(h, public_send(:y, **h))
assert_equal(false, m.(**{}).frozen?)
assert_equal_not_same(kw, m.(**kw))
assert_equal_not_same(h, m.(**h))
@@ -292,17 +245,17 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal_not_same(kw, m.send(:call, **kw))
assert_equal_not_same(h, m.send(:call, **h))
- yo = lambda { |**kw| kw }
- m = yo.method(:call)
- assert_equal(false, yo.(**{}).frozen?)
- assert_equal_not_same(kw, yo.(**kw))
- assert_equal_not_same(h, yo.(**h))
- assert_equal(false, yo.send(:call, **{}).frozen?)
- assert_equal_not_same(kw, yo.send(:call, **kw))
- assert_equal_not_same(h, yo.send(:call, **h))
- assert_equal(false, yo.public_send(:call, **{}).frozen?)
- assert_equal_not_same(kw, yo.public_send(:call, **kw))
- assert_equal_not_same(h, yo.public_send(:call, **h))
+ y = lambda { |**kw| kw }
+ m = y.method(:call)
+ assert_equal(false, y.(**{}).frozen?)
+ assert_equal_not_same(kw, y.(**kw))
+ assert_equal_not_same(h, y.(**h))
+ assert_equal(false, y.send(:call, **{}).frozen?)
+ assert_equal_not_same(kw, y.send(:call, **kw))
+ assert_equal_not_same(h, y.send(:call, **h))
+ assert_equal(false, y.public_send(:call, **{}).frozen?)
+ assert_equal_not_same(kw, y.public_send(:call, **kw))
+ assert_equal_not_same(h, y.public_send(:call, **h))
assert_equal(false, m.(**{}).frozen?)
assert_equal_not_same(kw, m.(**kw))
assert_equal_not_same(h, m.(**h))
@@ -310,17 +263,17 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal_not_same(kw, m.send(:call, **kw))
assert_equal_not_same(h, m.send(:call, **h))
- yo = :yo.to_proc
- m = yo.method(:call)
- assert_equal(false, yo.(self, **{}).frozen?)
- assert_equal_not_same(kw, yo.(self, **kw))
- assert_equal_not_same(h, yo.(self, **h))
- assert_equal(false, yo.send(:call, self, **{}).frozen?)
- assert_equal_not_same(kw, yo.send(:call, self, **kw))
- assert_equal_not_same(h, yo.send(:call, self, **h))
- assert_equal(false, yo.public_send(:call, self, **{}).frozen?)
- assert_equal_not_same(kw, yo.public_send(:call, self, **kw))
- assert_equal_not_same(h, yo.public_send(:call, self, **h))
+ y = :y.to_proc
+ m = y.method(:call)
+ assert_equal(false, y.(self, **{}).frozen?)
+ assert_equal_not_same(kw, y.(self, **kw))
+ assert_equal_not_same(h, y.(self, **h))
+ assert_equal(false, y.send(:call, self, **{}).frozen?)
+ assert_equal_not_same(kw, y.send(:call, self, **kw))
+ assert_equal_not_same(h, y.send(:call, self, **h))
+ assert_equal(false, y.public_send(:call, self, **{}).frozen?)
+ assert_equal_not_same(kw, y.public_send(:call, self, **kw))
+ assert_equal_not_same(h, y.public_send(:call, self, **h))
assert_equal(false, m.(self, **{}).frozen?)
assert_equal_not_same(kw, m.(self, **kw))
assert_equal_not_same(h, m.(self, **h))
@@ -329,20 +282,20 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal_not_same(h, m.send(:call, self, **h))
c = Class.new do
- def yo(**kw) kw end
+ def y(**kw) kw end
end
o = c.new
- def o.yo(**kw) super end
- m = o.method(:yo)
- assert_equal(false, o.yo(**{}).frozen?)
- assert_equal_not_same(kw, o.yo(**kw))
- assert_equal_not_same(h, o.yo(**h))
- assert_equal(false, o.send(:yo, **{}).frozen?)
- assert_equal_not_same(kw, o.send(:yo, **kw))
- assert_equal_not_same(h, o.send(:yo, **h))
- assert_equal(false, o.public_send(:yo, **{}).frozen?)
- assert_equal_not_same(kw, o.public_send(:yo, **kw))
- assert_equal_not_same(h, o.public_send(:yo, **h))
+ def o.y(**kw) super end
+ m = o.method(:y)
+ assert_equal(false, o.y(**{}).frozen?)
+ assert_equal_not_same(kw, o.y(**kw))
+ assert_equal_not_same(h, o.y(**h))
+ assert_equal(false, o.send(:y, **{}).frozen?)
+ assert_equal_not_same(kw, o.send(:y, **kw))
+ assert_equal_not_same(h, o.send(:y, **h))
+ assert_equal(false, o.public_send(:y, **{}).frozen?)
+ assert_equal_not_same(kw, o.public_send(:y, **kw))
+ assert_equal_not_same(h, o.public_send(:y, **h))
assert_equal(false, m.(**{}).frozen?)
assert_equal_not_same(kw, m.(**kw))
assert_equal_not_same(h, m.(**h))
@@ -350,17 +303,17 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal_not_same(kw, m.send(:call, **kw))
assert_equal_not_same(h, m.send(:call, **h))
- o.singleton_class.send(:remove_method, :yo)
- def o.yo(**kw) super(**kw) end
- assert_equal(false, o.yo(**{}).frozen?)
- assert_equal_not_same(kw, o.yo(**kw))
- assert_equal_not_same(h, o.yo(**h))
- assert_equal(false, o.send(:yo, **{}).frozen?)
- assert_equal_not_same(kw, o.send(:yo, **kw))
- assert_equal_not_same(h, o.send(:yo, **h))
- assert_equal(false, o.public_send(:yo, **{}).frozen?)
- assert_equal_not_same(kw, o.public_send(:yo, **kw))
- assert_equal_not_same(h, o.public_send(:yo, **h))
+ o.singleton_class.send(:remove_method, :y)
+ def o.y(**kw) super(**kw) end
+ assert_equal(false, o.y(**{}).frozen?)
+ assert_equal_not_same(kw, o.y(**kw))
+ assert_equal_not_same(h, o.y(**h))
+ assert_equal(false, o.send(:y, **{}).frozen?)
+ assert_equal_not_same(kw, o.send(:y, **kw))
+ assert_equal_not_same(h, o.send(:y, **h))
+ assert_equal(false, o.public_send(:y, **{}).frozen?)
+ assert_equal_not_same(kw, o.public_send(:y, **kw))
+ assert_equal_not_same(h, o.public_send(:y, **h))
assert_equal(false, m.(**{}).frozen?)
assert_equal_not_same(kw, m.(**kw))
assert_equal_not_same(h, m.(**h))
@@ -372,17 +325,17 @@ class TestKeywordArguments < Test::Unit::TestCase
def method_missing(_, **kw) kw end
end
o = c.new
- def o.yo(**kw) super end
- m = o.method(:yo)
- assert_equal(false, o.yo(**{}).frozen?)
- assert_equal_not_same(kw, o.yo(**kw))
- assert_equal_not_same(h, o.yo(**h))
- assert_equal(false, o.send(:yo, **{}).frozen?)
- assert_equal_not_same(kw, o.send(:yo, **kw))
- assert_equal_not_same(h, o.send(:yo, **h))
- assert_equal(false, o.public_send(:yo, **{}).frozen?)
- assert_equal_not_same(kw, o.public_send(:yo, **kw))
- assert_equal_not_same(h, o.public_send(:yo, **h))
+ def o.y(**kw) super end
+ m = o.method(:y)
+ assert_equal(false, o.y(**{}).frozen?)
+ assert_equal_not_same(kw, o.y(**kw))
+ assert_equal_not_same(h, o.y(**h))
+ assert_equal(false, o.send(:y, **{}).frozen?)
+ assert_equal_not_same(kw, o.send(:y, **kw))
+ assert_equal_not_same(h, o.send(:y, **h))
+ assert_equal(false, o.public_send(:y, **{}).frozen?)
+ assert_equal_not_same(kw, o.public_send(:y, **kw))
+ assert_equal_not_same(h, o.public_send(:y, **h))
assert_equal(false, m.(**{}).frozen?)
assert_equal_not_same(kw, m.(**kw))
assert_equal_not_same(h, m.(**h))
@@ -390,17 +343,17 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal_not_same(kw, m.send(:call, **kw))
assert_equal_not_same(h, m.send(:call, **h))
- o.singleton_class.send(:remove_method, :yo)
- def o.yo(**kw) super(**kw) end
- assert_equal(false, o.yo(**{}).frozen?)
- assert_equal_not_same(kw, o.yo(**kw))
- assert_equal_not_same(h, o.yo(**h))
- assert_equal(false, o.send(:yo, **{}).frozen?)
- assert_equal_not_same(kw, o.send(:yo, **kw))
- assert_equal_not_same(h, o.send(:yo, **h))
- assert_equal(false, o.public_send(:yo, **{}).frozen?)
- assert_equal_not_same(kw, o.public_send(:yo, **kw))
- assert_equal_not_same(h, o.public_send(:yo, **h))
+ o.singleton_class.send(:remove_method, :y)
+ def o.y(**kw) super(**kw) end
+ assert_equal(false, o.y(**{}).frozen?)
+ assert_equal_not_same(kw, o.y(**kw))
+ assert_equal_not_same(h, o.y(**h))
+ assert_equal(false, o.send(:y, **{}).frozen?)
+ assert_equal_not_same(kw, o.send(:y, **kw))
+ assert_equal_not_same(h, o.send(:y, **h))
+ assert_equal(false, o.public_send(:y, **{}).frozen?)
+ assert_equal_not_same(kw, o.public_send(:y, **kw))
+ assert_equal_not_same(h, o.public_send(:y, **h))
assert_equal(false, m.(**{}).frozen?)
assert_equal_not_same(kw, m.(**kw))
assert_equal_not_same(h, m.(**h))
@@ -436,41 +389,17 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal_not_same(h, m.(**h))
assert_equal_not_same(h, m.send(:call, **h))
- singleton_class.send(:remove_method, :yo)
+ singleton_class.send(:remove_method, :y)
def self.method_missing(_, **kw) kw end
- assert_equal(false, yo(**{}).frozen?)
- assert_equal_not_same(kw, yo(**kw))
- assert_equal_not_same(h, yo(**h))
- assert_equal(false, send(:yo, **{}).frozen?)
- assert_equal_not_same(kw, send(:yo, **kw))
- assert_equal_not_same(h, send(:yo, **h))
- assert_equal(false, public_send(:yo, **{}).frozen?)
- assert_equal_not_same(kw, public_send(:yo, **kw))
- assert_equal_not_same(h, public_send(:yo, **h))
-
- def self.yo(*a, **kw) = kw
- assert_equal_not_same kw, yo(**kw)
- assert_equal_not_same kw, yo(**kw, **kw)
-
- singleton_class.send(:remove_method, :yo)
- def self.yo(opts) = opts
- assert_equal_not_same h, yo(*[], **h)
- a = []
- assert_equal_not_same h, yo(*a, **h)
- end
-
- def test_keyword_splat_to_non_keyword_method
- h = {a: 1}.freeze
-
- def self.yo(kw) kw end
- assert_equal_not_same(h, yo(**h))
- assert_equal_not_same(h, method(:yo).(**h))
- assert_equal_not_same(h, :yo.to_proc.(self, **h))
-
- def self.yoa(*kw) kw[0] end
- assert_equal_not_same(h, yoa(**h))
- assert_equal_not_same(h, method(:yoa).(**h))
- assert_equal_not_same(h, :yoa.to_proc.(self, **h))
+ assert_equal(false, y(**{}).frozen?)
+ assert_equal_not_same(kw, y(**kw))
+ assert_equal_not_same(h, y(**h))
+ assert_equal(false, send(:y, **{}).frozen?)
+ assert_equal_not_same(kw, send(:y, **kw))
+ assert_equal_not_same(h, send(:y, **h))
+ assert_equal(false, public_send(:y, **{}).frozen?)
+ assert_equal_not_same(kw, public_send(:y, **kw))
+ assert_equal_not_same(h, public_send(:y, **h))
end
def test_regular_kwsplat
@@ -3609,7 +3538,7 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal(splat_expect, pr.call(a), bug8463)
pr = proc {|a, **opt| next a, opt}
- assert_equal([splat_expect, {}], pr.call(splat_expect), bug8463)
+ assert_equal(splat_expect.values_at(0, -1), pr.call(splat_expect), bug8463)
end
def req_plus_keyword(x, **h)
diff --git a/test/ruby/test_lambda.rb b/test/ruby/test_lambda.rb
index 7738034240..9949fab8c7 100644
--- a/test/ruby/test_lambda.rb
+++ b/test/ruby/test_lambda.rb
@@ -177,6 +177,32 @@ class TestLambdaParameters < Test::Unit::TestCase
RUBY
end
+ def pass_along(&block)
+ lambda(&block)
+ end
+
+ def pass_along2(&block)
+ pass_along(&block)
+ end
+
+ def test_create_non_lambda_for_proc_one_level
+ prev_warning, Warning[:deprecated] = Warning[:deprecated], false
+ f = pass_along {}
+ refute_predicate(f, :lambda?, '[Bug #15620]')
+ assert_nothing_raised(ArgumentError) { f.call(:extra_arg) }
+ ensure
+ Warning[:deprecated] = prev_warning
+ end
+
+ def test_create_non_lambda_for_proc_two_levels
+ prev_warning, Warning[:deprecated] = Warning[:deprecated], false
+ f = pass_along2 {}
+ refute_predicate(f, :lambda?, '[Bug #15620]')
+ assert_nothing_raised(ArgumentError) { f.call(:extra_arg) }
+ ensure
+ Warning[:deprecated] = prev_warning
+ end
+
def test_instance_exec
bug12568 = '[ruby-core:76300] [Bug #12568]'
assert_nothing_raised(ArgumentError, bug12568) do
diff --git a/test/ruby/test_lazy_enumerator.rb b/test/ruby/test_lazy_enumerator.rb
index 22127e903a..2116d0ee31 100644
--- a/test/ruby/test_lazy_enumerator.rb
+++ b/test/ruby/test_lazy_enumerator.rb
@@ -282,11 +282,6 @@ class TestLazyEnumerator < Test::Unit::TestCase
assert_equal(3, a.current)
end
- def test_zip_map_lambda_bug_19569
- ary = [1, 2, 3].to_enum.lazy.zip([:a, :b, :c]).map(&:last).to_a
- assert_equal([:a, :b, :c], ary)
- end
-
def test_take
a = Step.new(1..10)
assert_equal(1, a.take(5).first)
@@ -300,26 +295,6 @@ class TestLazyEnumerator < Test::Unit::TestCase
assert_equal(nil, a.current)
end
- def test_take_0_bug_18971
- def (bomb = Object.new.extend(Enumerable)).each
- raise
- end
- [2..10, bomb].each do |e|
- assert_equal([], e.lazy.take(0).map(&:itself).to_a)
- assert_equal([], e.lazy.take(0).select(&:even?).to_a)
- assert_equal([], e.lazy.take(0).select(&:odd?).to_a)
- assert_equal([], e.lazy.take(0).reject(&:even?).to_a)
- assert_equal([], e.lazy.take(0).reject(&:odd?).to_a)
- assert_equal([], e.lazy.take(0).take(1).to_a)
- assert_equal([], e.lazy.take(0).take(0).take(1).to_a)
- assert_equal([], e.lazy.take(0).drop(0).to_a)
- assert_equal([], e.lazy.take(0).find_all {|_| true}.to_a)
- assert_equal([], e.lazy.take(0).zip((12..20)).to_a)
- assert_equal([], e.lazy.take(0).uniq.to_a)
- assert_equal([], e.lazy.take(0).sort.to_a)
- end
- end
-
def test_take_bad_arg
a = Step.new(1..10)
assert_raise(ArgumentError) { a.lazy.take(-1) }
diff --git a/test/ruby/test_m17n.rb b/test/ruby/test_m17n.rb
index 907360b3a6..c793520ac4 100644
--- a/test/ruby/test_m17n.rb
+++ b/test/ruby/test_m17n.rb
@@ -226,16 +226,38 @@ class TestM17N < Test::Unit::TestCase
end
end
- def test_utf_dummy_are_like_regular_dummy_encodings
- [Encoding::UTF_16, Encoding::UTF_32].each do |enc|
- s = "\u3042".encode("UTF-32BE")
- assert_equal(s.dup.force_encoding("ISO-2022-JP").inspect, s.dup.force_encoding(enc).inspect)
- s = "\x00\x00\xFE\xFF"
- assert_equal(s.dup.force_encoding("ISO-2022-JP").inspect, s.dup.force_encoding(enc).inspect)
-
- assert_equal [0, 0, 254, 255], "\x00\x00\xFE\xFF".force_encoding(enc).codepoints
- assert_equal 0, "\x00\x00\xFE\xFF".force_encoding(enc).ord
- assert_equal 255, "\xFF\xFE\x00\x00".force_encoding(enc).ord
+ STR_WITHOUT_BOM = "\u3042".freeze
+ STR_WITH_BOM = "\uFEFF\u3042".freeze
+ bug8940 = '[ruby-core:59757] [Bug #8940]'
+ bug9415 = '[ruby-dev:47895] [Bug #9415]'
+ %w/UTF-16 UTF-32/.each do |enc|
+ %w/BE LE/.each do |endian|
+ bom = "\uFEFF".encode("#{enc}#{endian}").force_encoding(enc)
+
+ define_method("test_utf_16_32_inspect(#{enc}#{endian})") do
+ s = STR_WITHOUT_BOM.encode(enc + endian)
+ # When a UTF-16/32 string doesn't have a BOM,
+ # inspect as a dummy encoding string.
+ assert_equal(s.dup.force_encoding("ISO-2022-JP").inspect,
+ s.dup.force_encoding(enc).inspect)
+ assert_normal_exit("#{bom.b.dump}.force_encoding('#{enc}').inspect", bug8940)
+ end
+
+ define_method("test_utf_16_32_codepoints(#{enc}#{endian})") do
+ assert_equal([0xFEFF], bom.codepoints, bug9415)
+ end
+
+ define_method("test_utf_16_32_ord(#{enc}#{endian})") do
+ assert_equal(0xFEFF, bom.ord, bug9415)
+ end
+
+ define_method("test_utf_16_32_inspect(#{enc}#{endian}-BOM)") do
+ s = STR_WITH_BOM.encode(enc + endian)
+ # When a UTF-16/32 string has a BOM,
+ # inspect as a particular encoding string.
+ assert_equal(s.inspect,
+ s.dup.force_encoding(enc).inspect)
+ end
end
end
@@ -278,7 +300,7 @@ class TestM17N < Test::Unit::TestCase
orig_int, Encoding.default_internal = Encoding.default_internal, nil
orig_ext = Encoding.default_external
- omit "https://bugs.ruby-lang.org/issues/18338"
+ skip "https://bugs.ruby-lang.org/issues/18338"
o = Object.new
@@ -870,22 +892,10 @@ class TestM17N < Test::Unit::TestCase
assert_raise(Encoding::CompatibilityError) {
"%s%s" % [s("\xc2\xa1"), e("\xc2\xa1")]
}
-
- assert_equal("\u3042".encode('Windows-31J'), "%c" % "\u3042\u3044".encode('Windows-31J'))
end
def test_sprintf_p
Encoding.list.each do |e|
- unless e.ascii_compatible?
- format = e.dummy? ? "%p".force_encoding(e) : "%p".encode(e)
- assert_raise(Encoding::CompatibilityError) do
- sprintf(format, nil)
- end
- assert_raise(Encoding::CompatibilityError) do
- format % nil
- end
- next
- end
format = "%p".force_encoding(e)
['', 'a', "\xC2\xA1", "\x00"].each do |s|
s.force_encoding(e)
@@ -1090,23 +1100,7 @@ class TestM17N < Test::Unit::TestCase
assert_nil(e("\xa1\xa2\xa3\xa4").index(e("\xa3")))
assert_nil(e("\xa1\xa2\xa3\xa4").rindex(e("\xa3")))
s = e("\xa3\xb0\xa3\xb1\xa3\xb2\xa3\xb3\xa3\xb4")
-
- a_with_e = /EUC-JP and ASCII-8BIT/
- assert_raise_with_message(Encoding::CompatibilityError, a_with_e) do
- s.index(a("\xb1\xa3"))
- end
- assert_raise_with_message(Encoding::CompatibilityError, a_with_e) do
- s.rindex(a("\xb1\xa3"))
- end
-
- a_with_e = /ASCII-8BIT regexp with EUC-JP string/
- assert_raise_with_message(Encoding::CompatibilityError, a_with_e) do
- s.index(Regexp.new(a("\xb1\xa3")))
- end
- assert_raise_with_message(Encoding::CompatibilityError, a_with_e) do
- s.rindex(Regexp.new(a("\xb1\xa3")))
- end
-
+ assert_raise(Encoding::CompatibilityError){s.rindex(a("\xb1\xa3"))}
bug11488 = '[ruby-core:70592] [Bug #11488]'
each_encoding("abcdef", "def") do |str, substr|
assert_equal(3, str.index(substr), bug11488)
diff --git a/test/ruby/test_marshal.rb b/test/ruby/test_marshal.rb
index 13645e3aa8..361d18dd4b 100644
--- a/test/ruby/test_marshal.rb
+++ b/test/ruby/test_marshal.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: false
require 'test/unit'
+require 'tempfile'
require_relative 'marshaltestlib'
class TestMarshal < Test::Unit::TestCase
@@ -32,7 +33,7 @@ class TestMarshal < Test::Unit::TestCase
end
def test_marshal
- a = [1, 2, 3, 2**32, 2**64, [4,5,"foo"], {1=>"bar"}, 2.5, fact(30)]
+ a = [1, 2, 3, [4,5,"foo"], {1=>"bar"}, 2.5, fact(30)]
assert_equal a, Marshal.load(Marshal.dump(a))
[[1,2,3,4], [81, 2, 118, 3146]].each { |w,x,y,z|
@@ -46,26 +47,6 @@ class TestMarshal < Test::Unit::TestCase
}
end
- def test_marshal_integers
- a = []
- [-2, -1, 0, 1, 2].each do |i|
- 0.upto(65).map do |exp|
- a << 2**exp + i
- end
- end
- assert_equal a, Marshal.load(Marshal.dump(a))
-
- a = [2**32, []]*2
- assert_equal a, Marshal.load(Marshal.dump(a))
-
- a = [2**32, 2**32, []]*2
- assert_equal a, Marshal.load(Marshal.dump(a))
- end
-
- def test_marshal_small_bignum_backref
- assert_equal [2**32, 2**32], Marshal.load("\x04\b[\al+\b\x00\x00\x00\x00\x01\x00@\x06")
- end
-
StrClone = String.clone
def test_marshal_cloned_class
assert_instance_of(StrClone, Marshal.load(Marshal.dump(StrClone.new("abc"))))
@@ -91,14 +72,6 @@ class TestMarshal < Test::Unit::TestCase
TestMarshal.instance_eval { remove_const :StructInvalidMembers }
end
- def test_load_range_as_struct
- assert_raise(TypeError, 'GH-6832') do
- # Can be obtained with:
- # $ ruby -e 'Range = Struct.new(:a, :b, :c); p Marshal.dump(Range.new(nil, nil, nil))'
- Marshal.load("\x04\bS:\nRange\b:\x06a0:\x06b0:\x06c0")
- end
- end
-
class C
def initialize(str)
@str = str
@@ -313,10 +286,11 @@ class TestMarshal < Test::Unit::TestCase
assert_equal(c, Marshal.load(Marshal.dump(c)), bug2109)
assert_nothing_raised(ArgumentError, '[ruby-dev:40386]') do
- re = IO.pipe do |r, w|
- w.write("\x04\bI/\x00\x00\x06:\rencoding\"\rUS-ASCII")
- # Marshal.load would not overread and block
- Marshal.load(r)
+ re = Tempfile.create("marshal_regexp") do |f|
+ f.binmode.write("\x04\bI/\x00\x00\x06:\rencoding\"\rUS-ASCII")
+ f.rewind
+ re2 = Marshal.load(f)
+ re2
end
assert_equal(//, re)
end
diff --git a/test/ruby/test_math.rb b/test/ruby/test_math.rb
index 6e67099c6b..73f44c6ae3 100644
--- a/test/ruby/test_math.rb
+++ b/test/ruby/test_math.rb
@@ -5,7 +5,6 @@ class TestMath < Test::Unit::TestCase
def assert_infinity(a, *rest)
rest = ["not infinity: #{a.inspect}"] if rest.empty?
assert_predicate(a, :infinite?, *rest)
- assert_predicate(a, :positive?, *rest)
end
def assert_nan(a, *rest)
@@ -166,9 +165,6 @@ class TestMath < Test::Unit::TestCase
assert_nothing_raised { assert_nan(Math.log(0.0, 0.0)) }
assert_nothing_raised { assert_nan(Math.log(Float::NAN)) }
assert_nothing_raised { assert_nan(Math.log(1.0, Float::NAN)) }
- assert_nothing_raised { assert_infinity(-Math.log(0)) }
- assert_nothing_raised { assert_infinity(-Math.log(0, 2)) }
- check(307.95368556425274, Math.log(2**1023, 10))
end
def test_log2
@@ -183,7 +179,6 @@ class TestMath < Test::Unit::TestCase
assert_raise_with_message(Math::DomainError, /\blog2\b/) { Math.log2(-1.0) }
assert_raise_with_message(Math::DomainError, /\blog2\b/) { Math.log2(-Float::EPSILON) }
assert_nothing_raised { assert_nan(Math.log2(Float::NAN)) }
- assert_nothing_raised { assert_infinity(-Math.log2(0)) }
end
def test_log10
@@ -198,7 +193,6 @@ class TestMath < Test::Unit::TestCase
assert_raise_with_message(Math::DomainError, /\blog10\b/) { Math.log10(-1.0) }
assert_raise_with_message(Math::DomainError, /\blog10\b/) { Math.log10(-Float::EPSILON) }
assert_nothing_raised { assert_nan(Math.log10(Float::NAN)) }
- assert_nothing_raised { assert_infinity(-Math.log10(0)) }
end
def test_sqrt
@@ -283,7 +277,8 @@ class TestMath < Test::Unit::TestCase
assert_raise_with_message(Math::DomainError, /\bgamma\b/) { Math.gamma(-1.0) }
x = Math.gamma(-0.0)
mesg = "Math.gamma(-0.0) should be -INF"
- assert_infinity(-x, mesg)
+ assert_infinity(x, mesg)
+ assert_predicate(x, :negative?, mesg)
assert_nan(Math.gamma(Float::NAN))
end
@@ -304,6 +299,7 @@ class TestMath < Test::Unit::TestCase
x, sign = Math.lgamma(-0.0)
mesg = "Math.lgamma(-0.0) should be [INF, -1]"
assert_infinity(x, mesg)
+ assert_predicate(x, :positive?, mesg)
assert_equal(-1, sign, mesg)
x, sign = Math.lgamma(Float::NAN)
assert_nan(x)
diff --git a/test/ruby/test_method.rb b/test/ruby/test_method.rb
index 90635bc5e5..ac50a9d0b0 100644
--- a/test/ruby/test_method.rb
+++ b/test/ruby/test_method.rb
@@ -318,17 +318,6 @@ class TestMethod < Test::Unit::TestCase
assert_equal(:foo, o.foo)
end
- PUBLIC_SINGLETON_TEST = Object.new
- class << PUBLIC_SINGLETON_TEST
- private
- PUBLIC_SINGLETON_TEST.define_singleton_method(:dsm){}
- def PUBLIC_SINGLETON_TEST.def; end
- end
- def test_define_singleton_method_public
- assert_nil(PUBLIC_SINGLETON_TEST.dsm)
- assert_nil(PUBLIC_SINGLETON_TEST.def)
- end
-
def test_define_singleton_method_no_proc
o = Object.new
assert_raise(ArgumentError) {
@@ -450,17 +439,6 @@ class TestMethod < Test::Unit::TestCase
assert_equal(:bar, m.clone.bar)
end
- def test_clone_under_gc_compact_stress
- EnvUtil.under_gc_compact_stress do
- o = Object.new
- def o.foo; :foo; end
- m = o.method(:foo)
- def m.bar; :bar; end
- assert_equal(:foo, m.clone.call)
- assert_equal(:bar, m.clone.bar)
- end
- end
-
def test_inspect
o = Object.new
def o.foo; end; line_no = __LINE__
@@ -588,9 +566,9 @@ 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, :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]], method(:mk1).parameters)
assert_equal([[:keyrest, :o]], method(:mk2).parameters)
assert_equal([[:req, :a], [:keyrest, :o]], method(:mk3).parameters)
assert_equal([[:opt, :a], [:keyrest, :o]], method(:mk4).parameters)
@@ -614,9 +592,9 @@ 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, :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]], self.class.instance_method(:mk1).parameters)
assert_equal([[:keyrest, :o]], self.class.instance_method(:mk2).parameters)
assert_equal([[:req, :a], [:keyrest, :o]], self.class.instance_method(:mk3).parameters)
assert_equal([[:opt, :a], [:keyrest, :o]], self.class.instance_method(:mk4).parameters)
@@ -641,7 +619,7 @@ class TestMethod < Test::Unit::TestCase
assert_equal([[:req, :a], [:rest, :b], [:req, :c], [:block, :d]], method(:pmo6).parameters)
assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:block, :e]], method(:pmo7).parameters)
assert_equal([[:req], [:block, :b]], method(:pma1).parameters)
- assert_equal([[:keyrest, :**]], method(:pmk1).parameters)
+ assert_equal([[:keyrest]], method(:pmk1).parameters)
assert_equal([[:keyrest, :o]], method(:pmk2).parameters)
assert_equal([[:req, :a], [:keyrest, :o]], method(:pmk3).parameters)
assert_equal([[:opt, :a], [:keyrest, :o]], method(:pmk4).parameters)
@@ -665,7 +643,7 @@ class TestMethod < Test::Unit::TestCase
assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:block, :e]], self.class.instance_method(:pmo7).parameters)
assert_equal([[:req], [:block, :b]], self.class.instance_method(:pma1).parameters)
assert_equal([[:req], [:block, :b]], self.class.instance_method(:pma1).parameters)
- assert_equal([[:keyrest, :**]], self.class.instance_method(:pmk1).parameters)
+ assert_equal([[:keyrest]], self.class.instance_method(:pmk1).parameters)
assert_equal([[:keyrest, :o]], self.class.instance_method(:pmk2).parameters)
assert_equal([[:req, :a], [:keyrest, :o]], self.class.instance_method(:pmk3).parameters)
assert_equal([[:opt, :a], [:keyrest, :o]], self.class.instance_method(:pmk4).parameters)
@@ -782,14 +760,6 @@ class TestMethod < Test::Unit::TestCase
assert_raise(NoMethodError) { (self).mv2 }
assert_nothing_raised { self.mv3 }
- class << (obj = Object.new)
- private def [](x) x end
- def mv1(x) self[x] end
- def mv2(x) (self)[x] end
- end
- assert_nothing_raised { obj.mv1(0) }
- assert_raise(NoMethodError) { obj.mv2(0) }
-
v = Visibility.new
assert_equal('method', defined?(v.mv1))
@@ -1226,6 +1196,25 @@ class TestMethod < Test::Unit::TestCase
assert_nil(super_method)
end
+ def test_method_visibility_predicates
+ v = Visibility.new
+ assert_equal(true, v.method(:mv1).public?)
+ assert_equal(true, v.method(:mv2).private?)
+ assert_equal(true, v.method(:mv3).protected?)
+ assert_equal(false, v.method(:mv2).public?)
+ assert_equal(false, v.method(:mv3).private?)
+ assert_equal(false, v.method(:mv1).protected?)
+ end
+
+ def test_unbound_method_visibility_predicates
+ assert_equal(true, Visibility.instance_method(:mv1).public?)
+ assert_equal(true, Visibility.instance_method(:mv2).private?)
+ assert_equal(true, Visibility.instance_method(:mv3).protected?)
+ assert_equal(false, Visibility.instance_method(:mv2).public?)
+ assert_equal(false, Visibility.instance_method(:mv3).private?)
+ assert_equal(false, Visibility.instance_method(:mv1).protected?)
+ end
+
# Bug 18435
def test_instance_methods_owner_consistency
a = Module.new { def method1; end }
@@ -1255,12 +1244,12 @@ class TestMethod < Test::Unit::TestCase
unbound = b.instance_method(:foo)
assert_equal unbound, b.public_instance_method(:foo)
- assert_equal "#<UnboundMethod: A#foo(arg=...) #{__FILE__}:#{line}>", unbound.inspect
+ assert_equal "#<UnboundMethod: B(A)#foo(arg=...) #{__FILE__}:#{line}>", unbound.inspect
assert_equal [[:opt, :arg]], unbound.parameters
a.remove_method(:foo)
- assert_equal "#<UnboundMethod: A#foo(arg=...) #{__FILE__}:#{line}>", unbound.inspect
+ assert_equal "#<UnboundMethod: B(A)#foo(arg=...) #{__FILE__}:#{line}>", unbound.inspect
assert_equal [[:opt, :arg]], unbound.parameters
obj = b.new
@@ -1300,7 +1289,7 @@ class TestMethod < Test::Unit::TestCase
a.remove_method(:foo)
- assert_equal "#<UnboundMethod: A#foo(arg=...) #{__FILE__}:#{line}>", unbound.inspect
+ assert_equal "#<UnboundMethod: B(A)#foo(arg=...) #{__FILE__}:#{line}>", unbound.inspect
assert_equal [[:opt, :arg]], unbound.parameters
assert_equal a0_foo, unbound.super_method
@@ -1308,7 +1297,7 @@ class TestMethod < Test::Unit::TestCase
assert_equal 1, unbound.bind_call(obj)
assert_include b.instance_methods(false), :foo
- assert_equal "#<UnboundMethod: A0#foo(arg1=..., arg2=...) #{__FILE__}:#{line0}>", b.instance_method(:foo).inspect
+ assert_equal "#<UnboundMethod: B(A0)#foo(arg1=..., arg2=...) #{__FILE__}:#{line0}>", b.instance_method(:foo).inspect
end
def test_zsuper_method_redefined_bind_call
@@ -1333,7 +1322,6 @@ class TestMethod < Test::Unit::TestCase
m2 = c2.instance_method(:foo)
c1.class_exec do
- remove_method :foo
def foo
[:bar2]
end
@@ -1374,7 +1362,7 @@ class TestMethod < Test::Unit::TestCase
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.
- omit 'do not exhaust memory on RubyCI openSUSE Leap machine'
+ 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]'
@@ -1442,25 +1430,25 @@ class TestMethod < Test::Unit::TestCase
end
def test_argument_error_location
- body = <<~'END_OF_BODY'
- eval <<~'EOS', nil, "main.rb"
- $line_lambda = __LINE__; $f = lambda do
- _x = 1
- end
- $line_method = __LINE__; def foo
- _x = 1
- end
- begin
- $f.call(1)
- rescue ArgumentError => e
- assert_equal "main.rb:#{$line_lambda}:in `block in <main>'", e.backtrace.first
- end
- begin
- foo(1)
- rescue ArgumentError => e
- assert_equal "main.rb:#{$line_method}:in `foo'", e.backtrace.first
- end
- EOS
+ body = <<-'END_OF_BODY'
+ eval <<-'EOS'
+ $line_lambda = __LINE__; $f = lambda do
+ _x = 1
+ end
+ $line_method = __LINE__; def foo
+ _x = 1
+ end
+ begin
+ $f.call(1)
+ rescue ArgumentError => e
+ assert_equal "(eval):#{$line_lambda.to_s}:in `block in <main>'", e.backtrace.first
+ end
+ begin
+ foo(1)
+ rescue ArgumentError => e
+ assert_equal "(eval):#{$line_method}:in `foo'", e.backtrace.first
+ end
+ EOS
END_OF_BODY
assert_separately [], body
@@ -1469,7 +1457,7 @@ class TestMethod < Test::Unit::TestCase
end
def test_zsuper_private_override_instance_method
- assert_separately([], <<-'end;', timeout: 30)
+ assert_separately(%w(--disable-gems), <<-'end;', timeout: 30)
# Bug #16942 [ruby-core:98691]
module M
def x
@@ -1490,7 +1478,7 @@ class TestMethod < Test::Unit::TestCase
end
def test_override_optimized_method_on_class_using_prepend
- assert_separately([], <<-'end;', timeout: 30)
+ assert_separately(%w(--disable-gems), <<-'end;', timeout: 30)
# Bug #17725 [ruby-core:102884]
$VERBOSE = nil
String.prepend(Module.new)
@@ -1576,7 +1564,7 @@ class TestMethod < Test::Unit::TestCase
# use_symbol = Object.instance_methods[0].is_a?(Symbol)
nummodule = nummethod = 0
mods = []
- ObjectSpace.each_object(Module) {|m| mods << m if String === m.name }
+ ObjectSpace.each_object(Module) {|m| mods << m if m.name }
mods = mods.sort_by {|m| m.name }
mods.each {|mod|
nummodule += 1
@@ -1614,12 +1602,4 @@ class TestMethod < Test::Unit::TestCase
def test_invalidating_CC_ASAN
assert_ruby_status(['-e', 'using Module.new'])
end
-
- def test_kwarg_eval_memory_leak
- assert_no_memory_leak([], "", <<~RUBY, rss: true, limit: 1.2)
- 100_000.times do
- eval("Hash.new(foo: 123)")
- end
- RUBY
- end
end
diff --git a/test/ruby/test_module.rb b/test/ruby/test_module.rb
index 4722fa22e0..b5414d139e 100644
--- a/test/ruby/test_module.rb
+++ b/test/ruby/test_module.rb
@@ -253,14 +253,6 @@ class TestModule < Test::Unit::TestCase
assert_operator(Math, :const_defined?, "PI")
assert_not_operator(Math, :const_defined?, :IP)
assert_not_operator(Math, :const_defined?, "IP")
-
- # Test invalid symbol name
- # [Bug #20245]
- EnvUtil.under_gc_stress do
- assert_raise(EncodingError) do
- Math.const_defined?("\xC3")
- end
- end
end
def each_bad_constants(m, &b)
@@ -543,7 +535,7 @@ class TestModule < Test::Unit::TestCase
super
end
end.new
- assert_operator(m, :<, Enumerable)
+ assert_equal(true, m < Enumerable)
end
def test_prepend_self
@@ -580,26 +572,6 @@ class TestModule < Test::Unit::TestCase
assert_equal(2, a2.b)
end
- def test_ancestry_of_duped_classes
- m = Module.new
- sc = Class.new
- a = Class.new(sc) do
- def b; 2 end
- prepend m
- end
-
- a2 = a.dup.new
-
- assert_kind_of Object, a2
- assert_kind_of sc, a2
- refute_kind_of a, a2
- assert_kind_of m, a2
-
- assert_kind_of Class, a2.class
- assert_kind_of sc.singleton_class, a2.class
- assert_same sc, a2.class.superclass
- end
-
def test_gc_prepend_chain
assert_separately([], <<-EOS)
10000.times { |i|
@@ -784,25 +756,6 @@ class TestModule < Test::Unit::TestCase
assert_equal([:m1, :m0, :m, :sc, :m1, :m0, :c], sc.new.m)
end
- def test_protected_include_into_included_module
- m1 = Module.new do
- def other_foo(other)
- other.foo
- end
-
- protected
- def foo
- :ok
- end
- end
- m2 = Module.new
- c1 = Class.new { include m2 }
- c2 = Class.new { include m2 }
- m2.include(m1)
-
- assert_equal :ok, c1.new.other_foo(c2.new)
- end
-
def test_instance_methods
assert_equal([:user, :user2], User.instance_methods(false).sort)
assert_equal([:user, :user2, :mixin].sort, User.instance_methods(true).sort)
@@ -1002,15 +955,6 @@ class TestModule < Test::Unit::TestCase
assert_equal([:bClass1], BClass.public_instance_methods(false))
end
- def test_undefined_instance_methods
- assert_equal([], AClass.undefined_instance_methods)
- assert_equal([], BClass.undefined_instance_methods)
- c = Class.new(AClass) {undef aClass}
- assert_equal([:aClass], c.undefined_instance_methods)
- c = Class.new(c)
- assert_equal([], c.undefined_instance_methods)
- end
-
def test_s_public
o = (c = Class.new(AClass)).new
assert_raise(NoMethodError, /private method/) {o.aClass1}
@@ -1336,6 +1280,8 @@ class TestModule < Test::Unit::TestCase
end
end
include LangModuleSpecInObject
+ module LangModuleTop
+ end
puts "ok" if LangModuleSpecInObject::LangModuleTop == LangModuleTop
INPUT
@@ -1736,47 +1682,6 @@ class TestModule < Test::Unit::TestCase
assert_equal("TestModule::C\u{df}", c.name, '[ruby-core:24600]')
c = Module.new.module_eval("class X\u{df} < Module; self; end")
assert_match(/::X\u{df}:/, c.new.to_s)
- ensure
- Object.send(:remove_const, "C\u{df}")
- end
-
-
- def test_const_added
- eval(<<~RUBY)
- module TestConstAdded
- @memo = []
- class << self
- attr_accessor :memo
-
- def const_added(sym)
- memo << sym
- end
- end
- CONST = 1
- module SubModule
- end
-
- class SubClass
- end
- end
- TestConstAdded::OUTSIDE_CONST = 2
- module TestConstAdded::OutsideSubModule; end
- class TestConstAdded::OutsideSubClass; end
- RUBY
- TestConstAdded.const_set(:CONST_SET, 3)
- assert_equal [
- :CONST,
- :SubModule,
- :SubClass,
- :OUTSIDE_CONST,
- :OutsideSubModule,
- :OutsideSubClass,
- :CONST_SET,
- ], TestConstAdded.memo
- ensure
- if self.class.const_defined? :TestConstAdded
- self.class.send(:remove_const, :TestConstAdded)
- end
end
def test_method_added
@@ -2360,18 +2265,6 @@ class TestModule < Test::Unit::TestCase
assert_equal(:foo, removed)
end
- def test_frozen_prepend_remove_method
- [Module, Class].each do |klass|
- mod = klass.new do
- prepend(Module.new)
- def foo; end
- end
- mod.freeze
- assert_raise(FrozenError, '[Bug #19166]') { mod.send(:remove_method, :foo) }
- assert_equal([:foo], mod.instance_methods(false))
- end
- end
-
def test_prepend_class_ancestors
bug6658 = '[ruby-core:45919]'
m = labeled_module("m")
@@ -2878,7 +2771,6 @@ class TestModule < Test::Unit::TestCase
def test_invalid_attr
%W[
- foo=
foo?
@foo
@@foo
@@ -3183,7 +3075,6 @@ class TestModule < Test::Unit::TestCase
end
def test_redefinition_mismatch
- omit "Investigating trunk-rjit failure on ci.rvm.jp" if defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled?
m = Module.new
m.module_eval "A = 1", __FILE__, line = __LINE__
e = assert_raise_with_message(TypeError, /is not a module/) {
@@ -3301,7 +3192,7 @@ class TestModule < Test::Unit::TestCase
end
def test_complemented_method_entry_memory_leak
- # [Bug #19894] [Bug #19896]
+ # [Bug #19894]
assert_no_memory_leak([], <<~PREP, <<~CODE, rss: true)
code = proc do
$c = Class.new do
@@ -3325,19 +3216,7 @@ class TestModule < Test::Unit::TestCase
end
1_000.times(&code)
PREP
- 300_000.times(&code)
- CODE
- end
-
- def test_module_clone_memory_leak
- # [Bug #19901]
- assert_no_memory_leak([], <<~PREP, <<~CODE, rss: true)
- code = proc do
- Module.new.clone
- end
- 1_000.times(&code)
- PREP
- 1_000_000.times(&code)
+ 100_000.times(&code)
CODE
end
@@ -3348,7 +3227,7 @@ class TestModule < Test::Unit::TestCase
methods = singleton_class.private_instance_methods(false)
assert_include(methods, :#{method}, ":#{method} should be private")
- assert_raise_with_message(NoMethodError, /^private method `#{method}' called for /) {
+ assert_raise_with_message(NoMethodError, "private method `#{method}' called for main:Object") {
recv = self
recv.#{method}
}
diff --git a/test/ruby/test_nomethod_error.rb b/test/ruby/test_nomethod_error.rb
index 0306535943..321b7ccab2 100644
--- a/test/ruby/test_nomethod_error.rb
+++ b/test/ruby/test_nomethod_error.rb
@@ -85,7 +85,7 @@ class TestNoMethodError < Test::Unit::TestCase
bug3237 = '[ruby-core:29948]'
str = "\u2600"
id = :"\u2604"
- msg = "undefined method `#{id}' for an instance of String"
+ msg = "undefined method `#{id}' for \"#{str}\":String"
assert_raise_with_message(NoMethodError, Regexp.compile(Regexp.quote(msg)), bug3237) do
str.__send__(id)
end
diff --git a/test/ruby/test_object.rb b/test/ruby/test_object.rb
index 0bb9e633a1..83208bbcdb 100644
--- a/test/ruby/test_object.rb
+++ b/test/ruby/test_object.rb
@@ -355,41 +355,6 @@ class TestObject < Test::Unit::TestCase
end
end
- def test_remove_instance_variable_re_embed
- require "objspace"
-
- c = Class.new do
- def a = @a
-
- def b = @b
-
- def c = @c
- end
-
- o1 = c.new
- o2 = c.new
-
- o1.instance_variable_set(:@foo, 5)
- o1.instance_variable_set(:@a, 0)
- o1.instance_variable_set(:@b, 1)
- o1.instance_variable_set(:@c, 2)
- refute_includes ObjectSpace.dump(o1), '"embedded":true'
- o1.remove_instance_variable(:@foo)
- assert_includes ObjectSpace.dump(o1), '"embedded":true'
-
- o2.instance_variable_set(:@a, 0)
- o2.instance_variable_set(:@b, 1)
- o2.instance_variable_set(:@c, 2)
- assert_includes ObjectSpace.dump(o2), '"embedded":true'
-
- assert_equal(0, o1.a)
- assert_equal(1, o1.b)
- assert_equal(2, o1.c)
- assert_equal(0, o2.a)
- assert_equal(1, o2.b)
- assert_equal(2, o2.c)
- end
-
def test_convert_string
o = Object.new
def o.to_s; 1; end
@@ -457,18 +422,6 @@ class TestObject < Test::Unit::TestCase
assert_equal(1+3+5+7+9, n)
end
- def test_max_shape_variation_with_performance_warnings
- assert_in_out_err([], <<-INPUT, %w(), /The class Foo reached 8 shape variations, instance variables accesses will be slower and memory usage increased/)
- $VERBOSE = false
- Warning[:performance] = true
-
- class Foo; end
- 10.times do |i|
- Foo.new.instance_variable_set(:"@a\#{i}", nil)
- end
- INPUT
- end
-
def test_redefine_method_under_verbose
assert_in_out_err([], <<-INPUT, %w(2), /warning: method redefined; discarding old foo$/)
$VERBOSE = true
@@ -900,15 +853,6 @@ class TestObject < Test::Unit::TestCase
x.instance_variable_set(:@bar, 42)
assert_match(/\A#<Object:0x\h+ (?:@foo="value", @bar=42|@bar=42, @foo="value")>\z/, x.inspect)
- # Bug: [ruby-core:19167]
- x = Object.new
- x.instance_variable_set(:@foo, NilClass)
- assert_match(/\A#<Object:0x\h+ @foo=NilClass>\z/, x.inspect)
- x.instance_variable_set(:@foo, TrueClass)
- assert_match(/\A#<Object:0x\h+ @foo=TrueClass>\z/, x.inspect)
- x.instance_variable_set(:@foo, FalseClass)
- assert_match(/\A#<Object:0x\h+ @foo=FalseClass>\z/, x.inspect)
-
# #inspect does not call #to_s anymore
feature6130 = '[ruby-core:43238]'
x = Object.new
@@ -981,19 +925,6 @@ class TestObject < Test::Unit::TestCase
end
end
- def test_singleton_class_freeze
- x = Object.new
- xs = x.singleton_class
- x.freeze
- assert_predicate(xs, :frozen?)
-
- y = Object.new
- ys = y.singleton_class
- ys.prepend(Module.new)
- y.freeze
- assert_predicate(ys, :frozen?, '[Bug #19169]')
- end
-
def test_redef_method_missing
bug5473 = '[ruby-core:40287]'
['ArgumentError.new("bug5473")', 'ArgumentError, "bug5473"', '"bug5473"'].each do |code|
@@ -1062,13 +993,4 @@ class TestObject < Test::Unit::TestCase
end
EOS
end
-
- def test_frozen_inspect
- obj = Object.new
- obj.instance_variable_set(:@a, "a")
- ins = obj.inspect
- obj.freeze
-
- assert_equal(ins, obj.inspect)
- end
end
diff --git a/test/ruby/test_objectspace.rb b/test/ruby/test_objectspace.rb
index a7cfb064a8..e0f9eecd11 100644
--- a/test/ruby/test_objectspace.rb
+++ b/test/ruby/test_objectspace.rb
@@ -65,11 +65,6 @@ End
assert_raise_with_message(TypeError, msg) {ObjectSpace._id2ref(Object.new)}
end
- def test_id2ref_invalid_symbol_id
- msg = /is not symbol id value/
- assert_raise_with_message(RangeError, msg) { ObjectSpace._id2ref(:a.object_id + GC::INTERNAL_CONSTANTS[:RVALUE_SIZE]) }
- 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 70b6bde6ed..43795d150c 100644
--- a/test/ruby/test_optimization.rb
+++ b/test/ruby/test_optimization.rb
@@ -437,31 +437,6 @@ class TestRubyOptimization < Test::Unit::TestCase
message(bug12565) {disasm(:add_one_and_two)})
end
- def test_c_func_with_sp_offset_under_tailcall
- tailcall("#{<<-"begin;"}\n#{<<~"end;"}")
- begin;
- def calc_one_plus_two
- 1 + 2.abs
- end
-
- def one_plus_two
- calc_one_plus_two
- end
- end;
- assert_equal(3, one_plus_two)
- end
-
- def test_tailcall_and_post_arg
- tailcall(<<~RUBY)
- def ret_const = :ok
-
- def post_arg(_a = 1, _b) = ret_const
- RUBY
-
- # YJIT probably uses a fallback on the call to post_arg
- assert_equal(:ok, post_arg(0))
- end
-
def test_tailcall_interrupted_by_sigint
bug12576 = 'ruby-core:76327'
script = "#{<<-"begin;"}\n#{<<~'end;'}"
@@ -535,7 +510,7 @@ class TestRubyOptimization < Test::Unit::TestCase
end
def test_tailcall_not_to_grow_stack
- omit 'currently JIT-ed code always creates a new stack frame' if defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled?
+ skip 'currently JIT-ed code always creates a new stack frame' if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?
bug16161 = '[ruby-core:94881]'
tailcall("#{<<-"begin;"}\n#{<<~"end;"}")
diff --git a/test/ruby/test_pack.rb b/test/ruby/test_pack.rb
index 1ce46e8916..9738f82b7e 100644
--- a/test/ruby/test_pack.rb
+++ b/test/ruby/test_pack.rb
@@ -1,44 +1,25 @@
# coding: US-ASCII
# frozen_string_literal: false
require 'test/unit'
-require 'rbconfig'
-require 'rbconfig/sizeof'
class TestPack < Test::Unit::TestCase
- # Note: the size of intptr_t and uintptr_t should be equal.
- J_SIZE = RbConfig::SIZEOF['uintptr_t']
-
def test_pack
- format = "c2x5CCxsdils_l_a6";
+ $format = "c2x5CCxsdils_l_a6";
# Need the expression in here to force ary[5] to be numeric. This avoids
# test2 failing because ary2 goes str->numeric->str and ary does not.
ary = [1,-100,127,128,32767,987.654321098 / 100.0,12345,123456,-32767,-123456,"abcdef"]
- x = ary.pack(format)
- ary2 = x.unpack(format)
+ $x = ary.pack($format)
+ ary2 = $x.unpack($format)
assert_equal(ary.length, ary2.length)
assert_equal(ary.join(':'), ary2.join(':'))
- assert_match(/def/, x)
-
- x = [-1073741825]
- assert_equal(x, x.pack("q").unpack("q"))
-
- x = [-1]
- assert_equal(x, x.pack("l").unpack("l"))
- end
-
- def test_ascii_incompatible
- assert_raise(Encoding::CompatibilityError) do
- ["foo"].pack("u".encode("UTF-32BE"))
- end
+ assert_match(/def/, $x)
- assert_raise(Encoding::CompatibilityError) do
- "foo".unpack("C".encode("UTF-32BE"))
- end
+ $x = [-1073741825]
+ assert_equal($x, $x.pack("q").unpack("q"))
- assert_raise(Encoding::CompatibilityError) do
- "foo".unpack1("C".encode("UTF-32BE"))
- end
+ $x = [-1]
+ assert_equal($x, $x.pack("l").unpack("l"))
end
def test_pack_n
@@ -98,11 +79,11 @@ class TestPack < Test::Unit::TestCase
assert_equal("\x01\x02\x03\x04", [0x01020304].pack("L"+mod))
assert_equal("\x01\x02\x03\x04\x05\x06\x07\x08", [0x0102030405060708].pack("q"+mod))
assert_equal("\x01\x02\x03\x04\x05\x06\x07\x08", [0x0102030405060708].pack("Q"+mod))
- case J_SIZE
- when 4
+ psize = [nil].pack('p').bytesize
+ if psize == 4
assert_equal("\x01\x02\x03\x04", [0x01020304].pack("j"+mod))
assert_equal("\x01\x02\x03\x04", [0x01020304].pack("J"+mod))
- when 8
+ elsif psize == 8
assert_equal("\x01\x02\x03\x04\x05\x06\x07\x08", [0x0102030405060708].pack("j"+mod))
assert_equal("\x01\x02\x03\x04\x05\x06\x07\x08", [0x0102030405060708].pack("J"+mod))
end
@@ -114,11 +95,10 @@ class TestPack < Test::Unit::TestCase
assert_match(/\A\x00*\x01\x02\x03\x04\z/, [0x01020304].pack("I!"+mod))
assert_match(/\A\x00*\x01\x02\x03\x04\z/, [0x01020304].pack("l!"+mod))
assert_match(/\A\x00*\x01\x02\x03\x04\z/, [0x01020304].pack("L!"+mod))
- case J_SIZE
- when 4
+ if psize == 4
assert_match(/\A\x00*\x01\x02\x03\x04\z/, [0x01020304].pack("j!"+mod))
assert_match(/\A\x00*\x01\x02\x03\x04\z/, [0x01020304].pack("J!"+mod))
- when 8
+ elsif psize == 8
assert_match(/\A\x00*\x01\x02\x03\x04\x05\x06\x07\x08\z/, [0x0102030405060708].pack("j!"+mod))
assert_match(/\A\x00*\x01\x02\x03\x04\x05\x06\x07\x08\z/, [0x0102030405060708].pack("J!"+mod))
end
@@ -147,11 +127,11 @@ class TestPack < Test::Unit::TestCase
assert_equal("\x04\x03\x02\x01", [0x01020304].pack("L"+mod))
assert_equal("\x08\x07\x06\x05\x04\x03\x02\x01", [0x0102030405060708].pack("q"+mod))
assert_equal("\x08\x07\x06\x05\x04\x03\x02\x01", [0x0102030405060708].pack("Q"+mod))
- case J_SIZE
- when 4
+ psize = [nil].pack('p').bytesize
+ if psize == 4
assert_equal("\x04\x03\x02\x01", [0x01020304].pack("j"+mod))
assert_equal("\x04\x03\x02\x01", [0x01020304].pack("J"+mod))
- when 8
+ elsif psize == 8
assert_equal("\x08\x07\x06\x05\x04\x03\x02\x01", [0x0102030405060708].pack("j"+mod))
assert_equal("\x08\x07\x06\x05\x04\x03\x02\x01", [0x0102030405060708].pack("J"+mod))
end
@@ -163,11 +143,10 @@ class TestPack < Test::Unit::TestCase
assert_match(/\A\x04\x03\x02\x01\x00*\z/, [0x01020304].pack("I!"+mod))
assert_match(/\A\x04\x03\x02\x01\x00*\z/, [0x01020304].pack("l!"+mod))
assert_match(/\A\x04\x03\x02\x01\x00*\z/, [0x01020304].pack("L!"+mod))
- case J_SIZE
- when 4
+ if psize == 4
assert_match(/\A\x04\x03\x02\x01\x00*\z/, [0x01020304].pack("j!"+mod))
assert_match(/\A\x04\x03\x02\x01\x00*\z/, [0x01020304].pack("J!"+mod))
- when 8
+ elsif psize == 8
assert_match(/\A\x08\x07\x06\x05\x04\x03\x02\x01\x00*\z/, [0x0102030405060708].pack("j!"+mod))
assert_match(/\A\x08\x07\x06\x05\x04\x03\x02\x01\x00*\z/, [0x0102030405060708].pack("J!"+mod))
end
@@ -203,8 +182,8 @@ class TestPack < Test::Unit::TestCase
end
def test_integer_endian_explicit
- _integer_big_endian('>')
- _integer_little_endian('<')
+ _integer_big_endian('>')
+ _integer_little_endian('<')
end
def test_pack_U
@@ -449,6 +428,7 @@ 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*")
@@ -471,8 +451,10 @@ class TestPack < Test::Unit::TestCase
end if RbConfig::CONFIG['HAVE_LONG_LONG']
def test_pack_unpack_jJ
- case J_SIZE
- when 4
+ # Note: we assume that the size of intptr_t and uintptr_t equals to the size
+ # of real pointer.
+ psize = [nil].pack("p").bytesize
+ if psize == 4
s1 = [67305985, -50462977].pack("j*")
s2 = [67305985, 4244504319].pack("J*")
assert_equal(s1, s2)
@@ -486,7 +468,7 @@ class TestPack < Test::Unit::TestCase
assert_equal(4, [1].pack("j").bytesize)
assert_equal(4, [1].pack("J").bytesize)
- when 8
+ elsif psize == 8
s1 = [578437695752307201, -506097522914230529].pack("j*")
s2 = [578437695752307201, 17940646550795321087].pack("J*")
assert_equal(s1, s2)
@@ -781,32 +763,58 @@ EXPECTED
end
def test_pack_garbage
- assert_raise(ArgumentError, %r%unknown pack directive '\*' in '\*U'$%) do
+ verbose = $VERBOSE
+ $VERBOSE = false
+
+ assert_silent do
+ assert_equal "\000", [0].pack("*U")
+ end
+
+ $VERBOSE = true
+
+ _, err = capture_output do
assert_equal "\000", [0].pack("*U")
end
+
+ assert_match %r%unknown pack directive '\*' in '\*U'$%, err
+ ensure
+ $VERBOSE = verbose
end
def test_unpack_garbage
- assert_raise(ArgumentError, %r%unknown unpack directive '\*' in '\*U'$%) do
+ verbose = $VERBOSE
+ $VERBOSE = false
+
+ assert_silent do
assert_equal [0], "\000".unpack("*U")
end
+
+ $VERBOSE = true
+
+ _, err = capture_output do
+ assert_equal [0], "\000".unpack("*U")
+ end
+
+ assert_match %r%unknown unpack directive '\*' in '\*U'$%, err
+ ensure
+ $VERBOSE = verbose
end
def test_invalid_warning
- assert_raise(ArgumentError, /unknown pack directive ',' in ','/) {
+ assert_warning(/unknown pack directive ',' in ','/) {
[].pack(",")
}
- assert_raise(ArgumentError, /\A[ -~]+\Z/) {
+ assert_warning(/\A[ -~]+\Z/) {
[].pack("\x7f")
}
- assert_raise(ArgumentError, /\A(.* in '\u{3042}'\n)+\z/) {
+ assert_warning(/\A(.* in '\u{3042}'\n)+\z/) {
[].pack("\u{3042}")
}
- assert_raise(ArgumentError, /\A.* in '.*U'\Z/) {
+ assert_warning(/\A.* in '.*U'\Z/) {
assert_equal "\000", [0].pack("\0U")
}
- assert_raise(ArgumentError, /\A.* in '.*U'\Z/) {
+ assert_warning(/\A.* in '.*U'\Z/) {
"\000".unpack("\0U")
}
end
diff --git a/test/ruby/test_parse.rb b/test/ruby/test_parse.rb
index c2f02ff809..2841e20f6d 100644
--- a/test/ruby/test_parse.rb
+++ b/test/ruby/test_parse.rb
@@ -14,7 +14,6 @@ class TestParse < Test::Unit::TestCase
def test_error_line
assert_syntax_error('------,,', /\n\z/, 'Message to pipe should end with a newline')
- assert_syntax_error("{hello\n world}", /hello/)
end
def test_else_without_rescue
@@ -453,44 +452,10 @@ class TestParse < Test::Unit::TestCase
end
def test_define_singleton_error
- msg = /singleton method for literals/
- assert_parse_error(%q[def ("foo").foo; end], msg)
- assert_parse_error(%q[def (1).foo; end], msg)
- assert_parse_error(%q[def ((1;1)).foo; end], msg)
- assert_parse_error(%q[def ((;1)).foo; end], msg)
- assert_parse_error(%q[def ((1+1;1)).foo; end], msg)
- assert_parse_error(%q[def ((%s();1)).foo; end], msg)
- assert_parse_error(%q[def ((%w();1)).foo; end], msg)
- assert_parse_error(%q[def ("#{42}").foo; end], msg)
- assert_parse_error(%q[def (:"#{42}").foo; end], msg)
- end
-
- def test_flip_flop
- all_assertions_foreach(nil,
- ['(cond1..cond2)', true],
- ['((cond1..cond2))', true],
-
- # '(;;;cond1..cond2)', # don't care
-
- '(1; cond1..cond2)',
- '(%s(); cond1..cond2)',
- '(%w(); cond1..cond2)',
- '(1; (2; (3; 4; cond1..cond2)))',
- '(1+1; cond1..cond2)',
- ) do |code, pass|
- code = code.sub("cond1", "n==4").sub("cond2", "n==5")
- if pass
- assert_equal([4,5], eval("(1..9).select {|n| true if #{code}}"))
- else
- assert_raise_with_message(ArgumentError, /bad value for range/, code) {
- verbose_bak, $VERBOSE = $VERBOSE, nil # disable "warning: possibly useless use of a literal in void context"
- begin
- eval("[4].each {|n| true if #{code}}")
- ensure
- $VERBOSE = verbose_bak
- end
- }
- end
+ assert_syntax_error("#{<<~"begin;"}\n#{<<~'end;'}", /singleton method for literals/) do
+ begin;
+ def ("foo").foo; end
+ end;
end
end
@@ -612,10 +577,6 @@ class TestParse < Test::Unit::TestCase
assert_equal(' ^~~~~'"\n", e.message.lines.last)
e = assert_syntax_error('"\M-\U0000"', 'Invalid escape character syntax')
assert_equal(' ^~~~~'"\n", e.message.lines.last)
-
- e = assert_syntax_error(%["\\C-\u3042"], 'Invalid escape character syntax')
- assert_match(/^\s \^(?# \\ ) ~(?# C ) ~(?# - ) ~+(?# U+3042 )$/x, e.message.lines.last)
- assert_not_include(e.message, "invalid multibyte char")
end
def test_question
@@ -646,8 +607,6 @@ class TestParse < Test::Unit::TestCase
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')
-
- assert_equal("\xff", eval("# encoding: ascii-8bit\n""?\\\xFF"))
end
def test_percent
@@ -681,7 +640,6 @@ class TestParse < Test::Unit::TestCase
assert_syntax_error(':@@1', /is not allowed/)
assert_syntax_error(':@', /is not allowed/)
assert_syntax_error(':@1', /is not allowed/)
- assert_syntax_error(':$01234', /is not allowed/)
end
def test_parse_string
@@ -722,16 +680,6 @@ FOO
eval "x = <<""FOO\r\n1\r\nFOO"
end
assert_equal("1\n", x)
-
- assert_nothing_raised do
- x = eval "<<' FOO'\n""[Bug #19539]\n"" FOO\n"
- end
- assert_equal("[Bug #19539]\n", x)
-
- assert_nothing_raised do
- x = eval "<<-' FOO'\n""[Bug #19539]\n"" FOO\n"
- end
- assert_equal("[Bug #19539]\n", x)
end
def test_magic_comment
@@ -889,6 +837,7 @@ x = __ENCODING__
def test_void_expr_stmts_value
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")}
@@ -896,10 +845,10 @@ x = __ENCODING__
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(useless_use) {eval("self; nil")}
- assert_nil assert_warning(useless_use) {eval("nil; nil")}
- assert_nil assert_warning(useless_use) {eval("true; nil")}
- assert_nil assert_warning(useless_use) {eval("false; 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_equal 1, x
@@ -907,14 +856,12 @@ x = __ENCODING__
end
def test_assign_in_conditional
- # multiple assignment
assert_warning(/`= literal' in conditional/) do
eval <<-END, nil, __FILE__, __LINE__+1
(x, y = 1, 2) ? 1 : 2
END
end
- # instance variable assignment
assert_warning(/`= literal' in conditional/) do
eval <<-END, nil, __FILE__, __LINE__+1
if @x = true
@@ -924,71 +871,6 @@ x = __ENCODING__
end
END
end
-
- # local variable assignment
- assert_warning(/`= literal' in conditional/) do
- eval <<-END, nil, __FILE__, __LINE__+1
- def m
- if x = true
- 1
- else
- 2
- end
- end
- END
- end
-
- # global variable assignment
- assert_separately([], <<-RUBY)
- assert_warning(/`= literal' in conditional/) do
- eval <<-END, nil, __FILE__, __LINE__+1
- if $x = true
- 1
- else
- 2
- end
- END
- end
- RUBY
-
- # dynamic variable assignment
- assert_warning(/`= literal' in conditional/) do
- eval <<-END, nil, __FILE__, __LINE__+1
- y = 1
-
- 1.times do
- if y = true
- 1
- else
- 2
- end
- end
- END
- end
-
- # class variable assignment
- assert_warning(/`= literal' in conditional/) do
- eval <<-END, nil, __FILE__, __LINE__+1
- c = Class.new
- class << c
- if @@a = 1
- end
- end
- END
- end
-
- # constant declaration
- assert_separately([], <<-RUBY)
- assert_warning(/`= literal' in conditional/) do
- eval <<-END, nil, __FILE__, __LINE__+1
- if Const = true
- 1
- else
- 2
- end
- END
- end
- RUBY
end
def test_literal_in_conditional
@@ -1072,30 +954,6 @@ x = __ENCODING__
assert_warning('') {eval("#{a} = 1; /(?<#{a}>)/ =~ ''")}
end
- def test_named_capture_in_block
- all_assertions_foreach(nil,
- '(/(?<a>.*)/)',
- '(;/(?<a>.*)/)',
- '(%s();/(?<a>.*)/)',
- '(%w();/(?<a>.*)/)',
- '(1; (2; 3; (4; /(?<a>.*)/)))',
- '(1+1; /(?<a>.*)/)',
- '/#{""}(?<a>.*)/',
- ) do |code, pass|
- token = Random.bytes(4).unpack1("H*")
- if pass
- assert_equal(token, eval("#{code} =~ #{token.dump}; a"))
- else
- verbose_bak, $VERBOSE = $VERBOSE, nil # disable "warning: possibly useless use of a literal in void context"
- begin
- assert_nil(eval("#{code} =~ #{token.dump}; defined?(a)"), code)
- ensure
- $VERBOSE = verbose_bak
- end
- end
- end
- end
-
def test_rescue_in_command_assignment
bug = '[ruby-core:75621] [Bug #12402]'
all_assertions(bug) do |a|
@@ -1183,22 +1041,6 @@ x = __ENCODING__
assert_syntax_error(" 0b\n", /\^/)
end
- def test_unclosed_unicode_escape_at_eol_bug_19750
- assert_separately([], "#{<<-"begin;"}\n#{<<~'end;'}")
- begin;
- assert_syntax_error("/\\u", /too short escape sequence/)
- assert_syntax_error("/\\u{", /unterminated regexp meets end of file/)
- assert_syntax_error("/\\u{\\n", /invalid Unicode list/)
- assert_syntax_error("/a#\\u{\\n/", /invalid Unicode list/)
- re = eval("/a#\\u{\n$/x")
- assert_match(re, 'a')
- assert_not_match(re, 'a#')
- re = eval("/a#\\u\n$/x")
- assert_match(re, 'a')
- assert_not_match(re, 'a#')
- end;
- end
-
def test_error_def_in_argument
assert_separately([], "#{<<-"begin;"}\n#{<<~"end;"}")
begin;
@@ -1242,40 +1084,31 @@ x = __ENCODING__
end;
end
- def test_heredoc_interpolation
- var = 1
-
- v1 = <<~HEREDOC
- something
- #{"/#{var}"}
- HEREDOC
-
- v2 = <<~HEREDOC
- something
- #{_other = "/#{var}"}
- HEREDOC
+ def test_heredoc_interpolation
+ var = 1
- v3 = <<~HEREDOC
- something
- #{("/#{var}")}
- HEREDOC
+ v1 = <<~HEREDOC
+ something
+ #{"/#{var}"}
+ HEREDOC
- assert_equal "something\n/1\n", v1
- assert_equal "something\n/1\n", v2
- assert_equal "something\n/1\n", v3
- assert_equal v1, v2
- assert_equal v2, v3
- assert_equal v1, v3
- end
+ v2 = <<~HEREDOC
+ something
+ #{_other = "/#{var}"}
+ HEREDOC
- def test_heredoc_unterminated_interpolation
- code = <<~'HEREDOC'
- <<A+1
- #{
- HEREDOC
+ v3 = <<~HEREDOC
+ something
+ #{("/#{var}")}
+ HEREDOC
- assert_syntax_error(code, /can't find string "A"/)
- end
+ assert_equal "something\n/1\n", v1
+ assert_equal "something\n/1\n", v2
+ assert_equal "something\n/1\n", v3
+ assert_equal v1, v2
+ assert_equal v2, v3
+ assert_equal v1, v3
+ end
def test_unexpected_token_error
assert_syntax_error('"x"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', /unexpected/)
@@ -1285,8 +1118,6 @@ x = __ENCODING__
assert_syntax_error('0000xyz', /^ \^~~\Z/)
assert_syntax_error('1.2i1.1', /^ \^~~\Z/)
assert_syntax_error('1.2.3', /^ \^~\Z/)
- assert_syntax_error('1.', /unexpected end-of-input/)
- assert_syntax_error('1e', /expecting end-of-input/)
end
def test_truncated_source_line
@@ -1528,75 +1359,9 @@ x = __ENCODING__
end;
end
- def test_if_after_class
- assert_valid_syntax('module if true; Object end::Kernel; end')
- assert_valid_syntax('module while true; break Object end::Kernel; end')
- assert_valid_syntax('class if true; Object end::Kernel; end')
- assert_valid_syntax('class while true; break Object end::Kernel; end')
- end
-
- def test_escaped_space
- assert_syntax_error('x = \ 42', /escaped space/)
- end
-
- def test_label
- expected = {:foo => 1}
-
- code = '{"foo": 1}'
- assert_valid_syntax(code)
- assert_equal(expected, eval(code))
-
- code = '{foo: 1}'
- assert_valid_syntax(code)
- assert_equal(expected, eval(code))
-
- class << (obj = Object.new)
- attr_reader :arg
- def set(arg)
- @arg = arg
- end
- end
-
- assert_valid_syntax(code = "#{<<~"do;"}\n#{<<~'end;'}")
- do;
- obj.set foo:
- 1
- end;
- assert_equal(expected, eval(code))
- assert_equal(expected, obj.arg)
-
- assert_valid_syntax(code = "#{<<~"do;"}\n#{<<~'end;'}")
- do;
- obj.set "foo":
- 1
- end;
- assert_equal(expected, eval(code))
- assert_equal(expected, obj.arg)
- end
-
- def test_ungettable_gvar
- assert_syntax_error('$01234', /not allowed/)
- assert_syntax_error('"#$01234"', /not allowed/)
- end
-
=begin
def test_past_scope_variable
assert_warning(/past scope/) {catch {|tag| eval("BEGIN{throw tag}; tap {a = 1}; a")}}
end
=end
-
- def assert_parse(code)
- assert_kind_of(RubyVM::AbstractSyntaxTree::Node, RubyVM::AbstractSyntaxTree.parse(code))
- end
-
- def assert_parse_error(code, message)
- assert_raise_with_message(SyntaxError, message) do
- $VERBOSE, verbose_bak = nil, $VERBOSE
- begin
- RubyVM::AbstractSyntaxTree.parse(code)
- ensure
- $VERBOSE = verbose_bak
- end
- end
- end
end
diff --git a/test/ruby/test_pattern_matching.rb b/test/ruby/test_pattern_matching.rb
index 8e2806581c..4c203fb4f9 100644
--- a/test/ruby/test_pattern_matching.rb
+++ b/test/ruby/test_pattern_matching.rb
@@ -1,6 +1,8 @@
# 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 NullFormatter
def message_for(corrections)
@@ -9,14 +11,14 @@ class TestPatternMatching < Test::Unit::TestCase
end
def setup
- if defined?(DidYouMean.formatter=nil)
+ if defined?(DidYouMean)
@original_formatter = DidYouMean.formatter
DidYouMean.formatter = NullFormatter.new
end
end
def teardown
- if defined?(DidYouMean.formatter=nil)
+ if defined?(DidYouMean)
DidYouMean.formatter = @original_formatter
end
end
@@ -109,12 +111,16 @@ class TestPatternMatching < Test::Unit::TestCase
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
@@ -460,8 +466,6 @@ END
true
end
end
-
- assert_valid_syntax("1 in ^(1\n)")
end
def test_array_pattern
@@ -796,10 +800,6 @@ END
true
end
end
-
- assert_syntax_error(%q{
- 0 => [a, *a]
- }, /duplicated variable name/)
end
def test_find_pattern
@@ -868,10 +868,6 @@ END
false
end
end
-
- assert_syntax_error(%q{
- 0 => [*a, a, b, *b]
- }, /duplicated variable name/)
end
def test_hash_pattern
@@ -1161,28 +1157,6 @@ END
end
end
- bug18890 = assert_warning(/(?:.*:[47]: warning: possibly useless use of a literal in void context\n){2}/) do
- eval("#{<<~';;;'}")
- proc do |i|
- case i
- in a:
- 0 # line 4
- a
- in "b":
- 0 # line 7
- b
- else
- false
- end
- end
- ;;;
- end
- [{a: 42}, {b: 42}].each do |i|
- assert_block('newline should be significant after pattern label') do
- bug18890.call(i)
- end
- end
-
assert_syntax_error(%q{
case _
in a:, a:
@@ -1576,6 +1550,22 @@ END
assert_equal false, (1 in 2)
end
+ def assert_experimental_warning(code)
+ w = Warning[:experimental]
+
+ Warning[:experimental] = false
+ assert_warn('') {eval(code)}
+
+ Warning[:experimental] = true
+ assert_warn(/is experimental/) {eval(code)}
+ ensure
+ Warning[:experimental] = w
+ end
+
+ def test_experimental_warning
+ assert_experimental_warning("case [0]; in [*, 0, *]; end")
+ end
+
def test_bug18990
{a: 0} => a:
assert_equal 0, a
@@ -1715,3 +1705,5 @@ END
end
end
end
+END_of_GUARD
+Warning[:experimental] = experimental
diff --git a/test/ruby/test_proc.rb b/test/ruby/test_proc.rb
index 8d6ebf5dcb..51872e49be 100644
--- a/test/ruby/test_proc.rb
+++ b/test/ruby/test_proc.rb
@@ -289,6 +289,7 @@ class TestProc < Test::Unit::TestCase
assert_equal(false, l.lambda?)
assert_equal(false, l.curry.lambda?, '[ruby-core:24127]')
assert_equal(false, proc(&l).lambda?)
+ assert_equal(false, assert_deprecated_warning {lambda(&l)}.lambda?)
assert_equal(false, Proc.new(&l).lambda?)
l = lambda {}
assert_equal(true, l.lambda?)
@@ -298,21 +299,47 @@ class TestProc < Test::Unit::TestCase
assert_equal(true, Proc.new(&l).lambda?)
end
- def helper_test_warn_lambda_with_passed_block &b
+ def self.helper_test_warn_lamda_with_passed_block &b
lambda(&b)
end
- def test_lambda_warning_pass_proc
- assert_raise(ArgumentError) do
- b = proc{}
- lambda(&b)
- end
+ def self.def_lambda_warning name, warn
+ define_method(name, proc do
+ prev = Warning[:deprecated]
+ assert_warn warn do
+ Warning[:deprecated] = true
+ yield
+ end
+ ensure
+ Warning[:deprecated] = prev
+ end)
end
- def test_lambda_warning_pass_block
- assert_raise(ArgumentError) do
- helper_test_warn_lambda_with_passed_block{}
- end
+ def_lambda_warning 'test_lambda_warning_normal', '' do
+ lambda{}
+ end
+
+ def_lambda_warning 'test_lambda_warning_pass_lambda', '' do
+ b = lambda{}
+ lambda(&b)
+ end
+
+ def_lambda_warning 'test_lambda_warning_pass_symbol_proc', '' do
+ lambda(&:to_s)
+ end
+
+ def_lambda_warning 'test_lambda_warning_pass_proc', /deprecated/ do
+ b = proc{}
+ lambda(&b)
+ end
+
+ def_lambda_warning 'test_lambda_warning_pass_block', /deprecated/ do
+ helper_test_warn_lamda_with_passed_block{}
+ end
+
+ def_lambda_warning 'test_lambda_warning_pass_block_symbol_proc', '' do
+ # Symbol#to_proc returns lambda
+ helper_test_warn_lamda_with_passed_block(&:to_s)
end
def test_curry_ski_fib
@@ -385,20 +412,6 @@ class TestProc < Test::Unit::TestCase
assert_equal(:foo, bc.foo)
end
- def test_dup_subclass
- c1 = Class.new(Proc)
- assert_equal c1, c1.new{}.dup.class, '[Bug #17545]'
- c1 = Class.new(Proc) {def initialize_dup(*) throw :initialize_dup; end}
- assert_throw(:initialize_dup) {c1.new{}.dup}
- end
-
- def test_clone_subclass
- c1 = Class.new(Proc)
- assert_equal c1, c1.new{}.clone.class, '[Bug #17545]'
- c1 = Class.new(Proc) {def initialize_clone(*) throw :initialize_clone; end}
- assert_throw(:initialize_clone) {c1.new{}.clone}
- end
-
def test_binding
b = proc {|x, y, z| proc {}.binding }.call(1, 2, 3)
class << b; attr_accessor :foo; end
@@ -427,11 +440,6 @@ class TestProc < Test::Unit::TestCase
assert_equal(@@line_of_source_location_test, lineno, 'Bug #2427')
end
- def test_binding_error_unless_ruby_frame
- define_singleton_method :binding_from_c!, method(:binding).to_proc >> ->(bndg) {bndg}
- assert_raise(RuntimeError) { binding_from_c! }
- end
-
def test_proc_lambda
assert_raise(ArgumentError) { proc }
assert_raise(ArgumentError) { assert_warn(/deprecated/) {lambda} }
@@ -839,88 +847,6 @@ class TestProc < Test::Unit::TestCase
assert_equal [[1, 2], Proc, :x], (pr.call(1, 2){|x| x})
end
- def test_proc_args_single_kw_no_autosplat
- pr = proc {|c, a: 1| [c, a] }
- assert_equal [nil, 1], pr.call()
- assert_equal [1, 1], pr.call(1)
- assert_equal [[1], 1], pr.call([1])
- assert_equal [1, 1], pr.call(1,2)
- assert_equal [[1, 2], 1], pr.call([1,2])
-
- assert_equal [nil, 3], pr.call(a: 3)
- assert_equal [1, 3], pr.call(1, a: 3)
- assert_equal [[1], 3], pr.call([1], a: 3)
- assert_equal [1, 3], pr.call(1,2, a: 3)
- assert_equal [[1, 2], 3], pr.call([1,2], a: 3)
- end
-
- def test_proc_args_single_kwsplat_no_autosplat
- pr = proc {|c, **kw| [c, kw] }
- assert_equal [nil, {}], pr.call()
- assert_equal [1, {}], pr.call(1)
- assert_equal [[1], {}], pr.call([1])
- assert_equal [1, {}], pr.call(1,2)
- assert_equal [[1, 2], {}], pr.call([1,2])
-
- assert_equal [nil, {a: 3}], pr.call(a: 3)
- assert_equal [1, {a: 3}], pr.call(1, a: 3)
- assert_equal [[1], {a: 3}], pr.call([1], a: 3)
- assert_equal [1, {a: 3}], pr.call(1,2, a: 3)
- assert_equal [[1, 2], {a: 3}], pr.call([1,2], a: 3)
- end
-
- def test_proc_args_multiple_kw_autosplat
- pr = proc {|c, b, a: 1| [c, b, a] }
- assert_equal [1, 2, 1], pr.call([1,2])
-
- pr = proc {|c=nil, b=nil, a: 1| [c, b, a] }
- assert_equal [nil, nil, 1], pr.call([])
- assert_equal [1, nil, 1], pr.call([1])
- assert_equal [1, 2, 1], pr.call([1,2])
-
- pr = proc {|c, b=nil, a: 1| [c, b, a] }
- assert_equal [1, nil, 1], pr.call([1])
- assert_equal [1, 2, 1], pr.call([1,2])
-
- pr = proc {|c=nil, b, a: 1| [c, b, a] }
- assert_equal [nil, 1, 1], pr.call([1])
- assert_equal [1, 2, 1], pr.call([1,2])
-
- pr = proc {|c, *b, a: 1| [c, b, a] }
- assert_equal [1, [], 1], pr.call([1])
- assert_equal [1, [2], 1], pr.call([1,2])
-
- pr = proc {|*c, b, a: 1| [c, b, a] }
- assert_equal [[], 1, 1], pr.call([1])
- assert_equal [[1], 2, 1], pr.call([1,2])
- end
-
- def test_proc_args_multiple_kwsplat_autosplat
- pr = proc {|c, b, **kw| [c, b, kw] }
- assert_equal [1, 2, {}], pr.call([1,2])
-
- pr = proc {|c=nil, b=nil, **kw| [c, b, kw] }
- assert_equal [nil, nil, {}], pr.call([])
- assert_equal [1, nil, {}], pr.call([1])
- assert_equal [1, 2, {}], pr.call([1,2])
-
- pr = proc {|c, b=nil, **kw| [c, b, kw] }
- assert_equal [1, nil, {}], pr.call([1])
- assert_equal [1, 2, {}], pr.call([1,2])
-
- pr = proc {|c=nil, b, **kw| [c, b, kw] }
- assert_equal [nil, 1, {}], pr.call([1])
- assert_equal [1, 2, {}], pr.call([1,2])
-
- pr = proc {|c, *b, **kw| [c, b, kw] }
- assert_equal [1, [], {}], pr.call([1])
- assert_equal [1, [2], {}], pr.call([1,2])
-
- pr = proc {|*c, b, **kw| [c, b, kw] }
- assert_equal [[], 1, {}], pr.call([1])
- assert_equal [[1], 2, {}], pr.call([1,2])
- end
-
def test_proc_args_only_rest
pr = proc {|*c| c }
assert_equal [], pr.call()
@@ -1303,54 +1229,6 @@ class TestProc < Test::Unit::TestCase
assert_empty(pr.parameters.map{|_,n|n}.compact)
end
- def test_proc_autosplat_with_multiple_args_with_ruby2_keywords_splat_bug_19759
- def self.yielder_ab(splat)
- yield([:a, :b], *splat)
- end
-
- res = yielder_ab([[:aa, :bb], Hash.ruby2_keywords_hash({k: :k})]) do |a, b, k:|
- [a, b, k]
- end
- assert_equal([[:a, :b], [:aa, :bb], :k], res)
-
- def self.yielder(splat)
- yield(*splat)
- end
- res = yielder([ [:a, :b] ]){|a, b, **| [a, b]}
- assert_equal([:a, :b], res)
-
- res = yielder([ [:a, :b], Hash.ruby2_keywords_hash({}) ]){|a, b, **| [a, b]}
- assert_equal([[:a, :b], nil], res)
-
- res = yielder([ [:a, :b], Hash.ruby2_keywords_hash({c: 1}) ]){|a, b, **| [a, b]}
- assert_equal([[:a, :b], nil], res)
-
- res = yielder([ [:a, :b], Hash.ruby2_keywords_hash({}) ]){|a, b, **nil| [a, b]}
- assert_equal([[:a, :b], nil], res)
- end
-
- def test_parameters_lambda
- assert_equal([], proc {}.parameters(lambda: true))
- assert_equal([], proc {||}.parameters(lambda: true))
- assert_equal([[:req, :a]], proc {|a|}.parameters(lambda: true))
- assert_equal([[:req, :a], [:req, :b]], proc {|a, b|}.parameters(lambda: true))
- assert_equal([[:opt, :a], [:block, :b]], proc {|a=:a, &b|}.parameters(lambda: true))
- assert_equal([[:req, :a], [:opt, :b]], proc {|a, b=:b|}.parameters(lambda: true))
- assert_equal([[:rest, :a]], proc {|*a|}.parameters(lambda: true))
- assert_equal([[:req, :a], [:rest, :b], [:block, :c]], proc {|a, *b, &c|}.parameters(lambda: true))
- assert_equal([[:req, :a], [:rest, :b], [:req, :c]], proc {|a, *b, c|}.parameters(lambda: true))
- assert_equal([[:req, :a], [:rest, :b], [:req, :c], [:block, :d]], proc {|a, *b, c, &d|}.parameters(lambda: true))
- assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:block, :e]], proc {|a, b=:b, *c, d, &e|}.parameters(lambda: true))
- assert_equal([[:req], [:block, :b]], proc {|(a), &b|a}.parameters(lambda: true))
- assert_equal([[:req, :a], [:req, :b], [:opt, :c], [:opt, :d], [:rest, :e], [:req, :f], [:req, :g], [:block, :h]], proc {|a,b,c=:c,d=:d,*e,f,g,&h|}.parameters(lambda: true))
-
- pr = eval("proc{|"+"(_),"*30+"|}")
- assert_empty(pr.parameters(lambda: true).map{|_,n|n}.compact)
-
- assert_equal([[:opt, :a]], lambda {|a|}.parameters(lambda: false))
- assert_equal([[:opt, :a], [:opt, :b], [:opt, :c], [:opt, :d], [:rest, :e], [:opt, :f], [:opt, :g], [:block, :h]], lambda {|a,b,c=:c,d=:d,*e,f,g,&h|}.parameters(lambda: false))
- end
-
def pm0() end
def pm1(a) end
def pm2(a, b) end
@@ -1383,7 +1261,7 @@ class TestProc < Test::Unit::TestCase
assert_equal([[:req, :a], [:rest, :b], [:req, :c], [:block, :d]], method(:pmo6).to_proc.parameters)
assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:block, :e]], method(:pmo7).to_proc.parameters)
assert_equal([[:req], [:block, :b]], method(:pma1).to_proc.parameters)
- assert_equal([[:keyrest, :**]], method(:pmk1).to_proc.parameters)
+ assert_equal([[:keyrest]], method(:pmk1).to_proc.parameters)
assert_equal([[:keyrest, :o]], method(:pmk2).to_proc.parameters)
assert_equal([[:req, :a], [:keyrest, :o]], method(:pmk3).to_proc.parameters)
assert_equal([[:opt, :a], [:keyrest, :o]], method(:pmk4).to_proc.parameters)
diff --git a/test/ruby/test_process.rb b/test/ruby/test_process.rb
index 0416b20176..30427aeec1 100644
--- a/test/ruby/test_process.rb
+++ b/test/ruby/test_process.rb
@@ -3,6 +3,7 @@
require 'test/unit'
require 'tempfile'
require 'timeout'
+require 'io/wait'
require 'rbconfig'
class TestProcess < Test::Unit::TestCase
@@ -168,7 +169,7 @@ class TestProcess < Test::Unit::TestCase
end
def test_execopts_pgroup
- omit "system(:pgroup) is not supported" if windows?
+ skip "system(:pgroup) is not supported" if windows?
assert_nothing_raised { system(*TRUECOMMAND, :pgroup=>false) }
io = IO.popen([RUBY, "-e", "print Process.getpgrp"])
@@ -272,7 +273,7 @@ class TestProcess < Test::Unit::TestCase
end;
end
- MANDATORY_ENVS = %w[RUBYLIB RJIT_SEARCH_BUILD_DIR]
+ MANDATORY_ENVS = %w[RUBYLIB MJIT_SEARCH_BUILD_DIR]
case RbConfig::CONFIG['target_os']
when /linux/
MANDATORY_ENVS << 'LD_PRELOAD'
@@ -510,7 +511,7 @@ class TestProcess < Test::Unit::TestCase
UMASK = [RUBY, '-e', 'printf "%04o\n", File.umask']
def test_execopts_umask
- omit "umask is not supported" if windows?
+ skip "umask is not supported" if windows?
IO.popen([*UMASK, :umask => 0]) {|io|
assert_equal("0000", io.read.chomp)
}
@@ -665,7 +666,6 @@ class TestProcess < Test::Unit::TestCase
end unless windows? # does not support fifo
def test_execopts_redirect_open_fifo_interrupt_raise
- pid = nil
with_tmpchdir {|d|
begin
File.mkfifo("fifo")
@@ -683,21 +683,15 @@ class TestProcess < Test::Unit::TestCase
puts "ok"
end
EOS
- pid = io.pid
assert_equal("start\n", io.gets)
sleep 0.5
Process.kill(:USR1, io.pid)
assert_equal("ok\n", io.read)
}
- assert_equal(pid, $?.pid)
- assert_predicate($?, :success?)
}
- ensure
- assert_raise(Errno::ESRCH) {Process.kill(:KILL, pid)} if pid
end unless windows? # does not support fifo
def test_execopts_redirect_open_fifo_interrupt_print
- pid = nil
with_tmpchdir {|d|
begin
File.mkfifo("fifo")
@@ -710,25 +704,14 @@ class TestProcess < Test::Unit::TestCase
puts "start"
system("cat", :in => "fifo")
EOS
- pid = io.pid
assert_equal("start\n", io.gets)
sleep 0.2 # wait for the child to stop at opening "fifo"
Process.kill(:USR1, io.pid)
assert_equal("trap\n", io.readpartial(8))
- sleep 0.2 # wait for the child to return to opening "fifo".
- # On arm64-darwin22, often deadlocks while the child is
- # opening "fifo". Not sure to where "ok" line being written
- # at the next has gone.
File.write("fifo", "ok\n")
assert_equal("ok\n", io.read)
}
- assert_equal(pid, $?.pid)
- assert_predicate($?, :success?)
}
- ensure
- if pid
- assert_raise(Errno::ESRCH) {Process.kill(:KILL, pid)}
- end
end unless windows? # does not support fifo
def test_execopts_redirect_pipe
@@ -854,7 +837,7 @@ class TestProcess < Test::Unit::TestCase
STDERR=>"out", STDOUT=>[:child, STDERR])
assert_equal("errout", File.read("out"))
- omit "inheritance of fd other than stdin,stdout and stderr is not supported" if windows?
+ skip "inheritance of fd other than stdin,stdout and stderr is not supported" if windows?
Process.wait spawn(RUBY, "-e", "STDERR.print 'err'; STDOUT.print 'out'",
STDOUT=>"out",
STDERR=>[:child, 3],
@@ -906,7 +889,7 @@ class TestProcess < Test::Unit::TestCase
end
def test_execopts_popen_extra_fd
- omit "inheritance of fd other than stdin,stdout and stderr is not supported" if windows?
+ skip "inheritance of fd other than stdin,stdout and stderr is not supported" if windows?
with_tmpchdir {|d|
with_pipe {|r, w|
IO.popen([RUBY, '-e', 'IO.new(3, "w").puts("a"); puts "b"', 3=>w]) {|io|
@@ -935,7 +918,7 @@ class TestProcess < Test::Unit::TestCase
end
def test_fd_inheritance
- omit "inheritance of fd other than stdin,stdout and stderr is not supported" if windows?
+ skip "inheritance of fd other than stdin,stdout and stderr is not supported" if windows?
with_pipe {|r, w|
system(RUBY, '-e', 'IO.new(ARGV[0].to_i, "w").puts(:ba)', w.fileno.to_s, w=>w)
w.close
@@ -981,7 +964,7 @@ class TestProcess < Test::Unit::TestCase
end
def test_execopts_close_others
- omit "inheritance of fd other than stdin,stdout and stderr is not supported" if windows?
+ skip "inheritance of fd other than stdin,stdout and stderr is not supported" if windows?
with_tmpchdir {|d|
with_pipe {|r, w|
system(RUBY, '-e', 'STDERR.reopen("err", "w"); IO.new(ARGV[0].to_i, "w").puts("ma")', w.fileno.to_s, :close_others=>true)
@@ -1075,7 +1058,7 @@ class TestProcess < Test::Unit::TestCase
}
}
rescue NotImplementedError
- omit "IO#close_on_exec= is not supported"
+ skip "IO#close_on_exec= is not supported"
end
end unless windows? # passing non-stdio fds is not supported on Windows
@@ -1442,11 +1425,6 @@ class TestProcess < Test::Unit::TestCase
REPRO
end
- def test_argv0_frozen
- assert_predicate Process.argv0, :frozen?
- assert_predicate $0, :frozen?
- end
-
def test_status
with_tmpchdir do
s = run_in_child("exit 1")
@@ -1455,15 +1433,8 @@ class TestProcess < Test::Unit::TestCase
assert_equal(s, s)
assert_equal(s, s.to_i)
- assert_deprecated_warn(/\buse .*Process::Status/) do
- assert_equal(s.to_i & 0x55555555, s & 0x55555555)
- end
- assert_deprecated_warn(/\buse .*Process::Status/) do
- assert_equal(s.to_i >> 1, s >> 1)
- end
- assert_raise(ArgumentError) do
- s >> -1
- end
+ assert_equal(s.to_i & 0x55555555, s & 0x55555555)
+ assert_equal(s.to_i >> 1, s >> 1)
assert_equal(false, s.stopped?)
assert_equal(nil, s.stopsig)
@@ -1576,8 +1547,6 @@ class TestProcess < Test::Unit::TestCase
assert_operator(diff, :<, sec,
->{"#{bug11340}: #{diff} seconds to interrupt Process.wait"})
f.puts
- rescue Errno::EPIPE
- omit "child process exited already in #{diff} seconds"
end
end
@@ -1641,7 +1610,7 @@ class TestProcess < Test::Unit::TestCase
else
assert_kind_of(Integer, max)
assert_predicate(max, :positive?)
- omit "not limited to NGROUPS_MAX" if /darwin/ =~ RUBY_PLATFORM
+ skip "not limited to NGROUPS_MAX" if /darwin/ =~ RUBY_PLATFORM
gs = Process.groups
assert_operator(gs.size, :<=, max)
gs[0] ||= 0
@@ -1668,7 +1637,7 @@ class TestProcess < Test::Unit::TestCase
end
def test_setegid
- omit "root can use Process.egid on Android platform" if RUBY_PLATFORM =~ /android/
+ skip "root can use Process.egid on Android platform" if RUBY_PLATFORM =~ /android/
assert_nothing_raised(TypeError) {Process.egid += 0}
rescue NotImplementedError
end
@@ -1726,6 +1695,11 @@ class TestProcess < Test::Unit::TestCase
end
def test_wait_and_sigchild
+ if /freebsd|openbsd/ =~ RUBY_PLATFORM
+ # this relates #4173
+ # When ruby can use 2 cores, signal and wait4 may miss the signal.
+ skip "this fails on FreeBSD and OpenBSD on multithreaded environment"
+ end
signal_received = []
IO.pipe do |sig_r, sig_w|
Signal.trap(:CHLD) do
@@ -1744,7 +1718,7 @@ class TestProcess < Test::Unit::TestCase
Process.wait pid
assert_send [sig_r, :wait_readable, 5], 'self-pipe not readable'
end
- if defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled? # checking -DRJIT_FORCE_ENABLE. It may trigger extra SIGCHLD.
+ if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # checking -DMJIT_FORCE_ENABLE. It may trigger extra SIGCHLD.
assert_equal [true], signal_received.uniq, "[ruby-core:19744]"
else
assert_equal [true], signal_received, "[ruby-core:19744]"
@@ -1759,7 +1733,7 @@ class TestProcess < Test::Unit::TestCase
def test_no_curdir
if /solaris/i =~ RUBY_PLATFORM
- omit "Temporary omit to avoid CI failures after commit to use realpath on required files"
+ skip "Temporary skip to avoid CI failures after commit to use realpath on required files"
end
with_tmpchdir {|d|
Dir.mkdir("vd")
@@ -1801,7 +1775,7 @@ class TestProcess < Test::Unit::TestCase
def test_aspawn_too_long_path
if /solaris/i =~ RUBY_PLATFORM && !defined?(Process::RLIMIT_NPROC)
- omit "Too exhaustive test on platforms without Process::RLIMIT_NPROC such as Solaris 10"
+ skip "Too exhaustive test on platforms without Process::RLIMIT_NPROC such as Solaris 10"
end
bug4315 = '[ruby-core:34833] #7904 [ruby-core:52628] #11613'
assert_fail_too_long_path(%w"echo |", bug4315)
@@ -1815,20 +1789,14 @@ class TestProcess < Test::Unit::TestCase
exs << Errno::EINVAL if windows?
exs << Errno::E2BIG if defined?(Errno::E2BIG)
opts = {[STDOUT, STDERR]=>File::NULL}
- if defined?(Process::RLIMIT_NPROC)
- opts[:rlimit_nproc] = /openbsd/i =~ RUBY_PLATFORM ? 64 : 128
- end
+ opts[:rlimit_nproc] = 128 if defined?(Process::RLIMIT_NPROC)
EnvUtil.suppress_warning do
assert_raise(*exs, mesg) do
begin
loop do
Process.spawn(cmds.join(sep), opts)
min = [cmds.size, min].max
- begin
- cmds *= 100
- rescue ArgumentError
- raise NoMemoryError
- end
+ cmds *= 100
end
rescue NoMemoryError
size = cmds.size
@@ -1849,7 +1817,7 @@ class TestProcess < Test::Unit::TestCase
with_tmpchdir do
assert_nothing_raised('[ruby-dev:12261]') do
- EnvUtil.timeout(10) do
+ EnvUtil.timeout(3) do
pid = spawn('yes | ls')
Process.waitpid pid
end
@@ -1870,6 +1838,8 @@ class TestProcess < Test::Unit::TestCase
end
def test_daemon_noclose
+ pend "macOS 15 beta is not working with this test" if /darwin/ =~ RUBY_PLATFORM && /15/ =~ `sw_vers -productVersion`
+
data = IO.popen("-", "r+") do |f|
break f.read if f
Process.daemon(false, true)
@@ -1908,28 +1878,6 @@ class TestProcess < Test::Unit::TestCase
assert_not_equal(cpid, dpid)
end
- def test_daemon_detached
- IO.popen("-", "r+") do |f|
- if f
- assert_equal(f.pid, Process.wait(f.pid))
-
- dpid, ppid, dsid = 3.times.map {Integer(f.gets)}
-
- message = "daemon #{dpid} should be detached"
- assert_not_equal($$, ppid, message) # would be 1 almost always
- assert_raise(Errno::ECHILD, message) {Process.wait(dpid)}
- assert_kind_of(Integer, Process.kill(0, dpid), message)
- assert_equal(dpid, dsid)
-
- break # close f, and let the daemon resume and exit
- end
- Process.setsid rescue nil
- Process.daemon(false, true)
- puts $$, Process.ppid, Process.getsid
- $stdin.gets # wait for the above assertions using signals
- end
- end
-
if File.directory?("/proc/self/task") && /netbsd[a-z]*[1-6]/ !~ RUBY_PLATFORM
def test_daemon_no_threads
pid, data = IO.popen("-", "r+") do |f|
@@ -2012,7 +1960,7 @@ class TestProcess < Test::Unit::TestCase
end
def test_execopts_uid
- omit "root can use uid option of Kernel#system on Android platform" if RUBY_PLATFORM =~ /android/
+ 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|
@@ -2043,8 +1991,8 @@ class TestProcess < Test::Unit::TestCase
end
def test_execopts_gid
- omit "Process.groups not implemented on Windows platform" if windows?
- omit "root can use Process.groups on Android platform" if RUBY_PLATFORM =~ /android/
+ 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|
@@ -2188,9 +2136,7 @@ EOS
t3 = Process.clock_gettime(Process::CLOCK_REALTIME, :nanosecond)
assert_operator(t1, :<=, t2)
assert_operator(t2, :<=, t3)
- assert_raise_with_message(Errno::EINVAL, /:foo/) do
- Process.clock_gettime(:foo)
- end
+ assert_raise(Errno::EINVAL) { Process.clock_gettime(:foo) }
end
def test_clock_gettime_unit
@@ -2295,9 +2241,7 @@ EOS
rescue Errno::EINVAL
else
assert_kind_of(Integer, r)
- assert_raise_with_message(Errno::EINVAL, /:foo/) do
- Process.clock_getres(:foo)
- end
+ assert_raise(Errno::EINVAL) { Process.clock_getres(:foo) }
end
def test_clock_getres_constants
@@ -2384,7 +2328,7 @@ EOS
end
def test_deadlock_by_signal_at_forking
- assert_separately(%W(- #{RUBY}), <<-INPUT, timeout: 100)
+ assert_separately(%W(--disable=gems - #{RUBY}), <<-INPUT, timeout: 100)
ruby = ARGV.shift
GC.start # reduce garbage
GC.disable # avoid triggering CoW after forks
@@ -2569,7 +2513,7 @@ EOS
end
def test_forked_child_handles_signal
- omit "fork not supported" unless Process.respond_to?(:fork)
+ skip "fork not supported" unless Process.respond_to?(:fork)
assert_normal_exit(<<-"end;", '[ruby-core:82883] [Bug #13916]')
require 'timeout'
pid = fork { sleep }
@@ -2623,26 +2567,6 @@ EOS
end
end if Process.respond_to?(:_fork)
- def test__fork_pid_cache
- _parent_pid = Process.pid
- r, w = IO.pipe
- pid = Process._fork
- if pid == 0
- begin
- r.close
- w << "ok: #{Process.pid}"
- w.close
- ensure
- exit!
- end
- else
- w.close
- assert_equal("ok: #{pid}", r.read)
- r.close
- Process.waitpid(pid)
- end
- end if Process.respond_to?(:_fork)
-
def test__fork_hook
%w(fork Process.fork).each do |method|
feature17795 = '[ruby-core:103400] [Feature #17795]'
@@ -2716,69 +2640,58 @@ EOS
end;
end if Process.respond_to?(:_fork)
- def test_warmup_promote_all_objects_to_oldgen
- assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
- require 'objspace'
- begin;
- obj = Object.new
-
- assert_not_include(ObjectSpace.dump(obj), '"old":true')
- Process.warmup
- assert_include(ObjectSpace.dump(obj), '"old":true')
- end;
- end
-
- def test_warmup_run_major_gc_and_compact
- assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- # Run a GC to ensure that we are not in the middle of a GC run
- GC.start
-
- major_gc_count = GC.stat(:major_gc_count)
- compact_count = GC.stat(:compact_count)
- Process.warmup
- assert_equal major_gc_count + 1, GC.stat(:major_gc_count)
- assert_equal compact_count + 1, GC.stat(:compact_count)
- end;
- end
-
- def test_warmup_precompute_string_coderange
- assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
- require 'objspace'
- begin;
- obj = "a" * 12
- obj.force_encoding(Encoding::UTF_16LE)
- obj.force_encoding(Encoding::BINARY)
- assert_include(ObjectSpace.dump(obj), '"coderange":"unknown"')
- Process.warmup
- assert_include(ObjectSpace.dump(obj), '"coderange":"7bit"')
- end;
- end
-
- def test_warmup_frees_pages
- assert_separately([{"RUBY_GC_HEAP_FREE_SLOTS_MAX_RATIO" => "1.0"}, "-W0"], "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- GC.start
-
- TIMES = 10_000
- ary = Array.new(TIMES)
- TIMES.times do |i|
- ary[i] = Object.new
- end
- ary.clear
- ary = nil
-
- # Disable GC so we can make sure GC only runs in Process.warmup
- GC.disable
-
- total_pages_before = GC.stat(:heap_eden_pages) + GC.stat(:heap_allocatable_pages)
-
- Process.warmup
-
- # Number of pages freed should cause equal increase in number of allocatable pages.
- assert_equal(total_pages_before, GC.stat(:heap_eden_pages) + GC.stat(:heap_allocatable_pages))
- assert_equal(0, GC.stat(:heap_tomb_pages))
- assert_operator(GC.stat(:total_freed_pages), :>, 0)
- end;
- end
+ def test_concurrent_group_and_pid_wait
+ # Use a pair of pipes that will make long_pid exit when this test exits, to avoid
+ # leaking temp processes.
+ long_rpipe, long_wpipe = IO.pipe
+ short_rpipe, short_wpipe = IO.pipe
+ # This process should run forever
+ long_pid = fork do
+ [short_rpipe, short_wpipe, long_wpipe].each(&:close)
+ long_rpipe.read
+ end
+ # This process will exit
+ short_pid = fork do
+ [long_rpipe, long_wpipe, short_wpipe].each(&:close)
+ short_rpipe.read
+ end
+ t1, t2, t3 = nil
+ EnvUtil.timeout(5) do
+ t1 = Thread.new do
+ Process.waitpid long_pid
+ end
+ # Wait for us to be blocking in a call to waitpid2
+ Thread.pass until t1.stop?
+ short_wpipe.close # Make short_pid exit
+
+ # The short pid has exited, so -1 should pick that up.
+ assert_equal short_pid, Process.waitpid(-1)
+
+ # Terminate t1 for the next phase of the test.
+ t1.kill
+ t1.join
+
+ t2 = Thread.new do
+ Process.waitpid -1
+ rescue Errno::ECHILD
+ nil
+ end
+ Thread.pass until t2.stop?
+ t3 = Thread.new do
+ Process.waitpid long_pid
+ rescue Errno::ECHILD
+ nil
+ end
+ Thread.pass until t3.stop?
+
+ # it's actually nondeterministic which of t2 or t3 will receive the wait (this
+ # nondeterminism comes from the behaviour of the underlying system calls)
+ long_wpipe.close
+ assert_equal [long_pid], [t2, t3].map(&:value).compact
+ end
+ ensure
+ [t1, t2, t3].each { _1&.kill rescue nil }
+ [t1, t2, t3].each { _1&.join rescue nil }
+ [long_rpipe, long_wpipe, short_rpipe, short_wpipe].each { _1&.close rescue nil }
+ end if defined?(fork)
end
diff --git a/test/ruby/test_rand.rb b/test/ruby/test_rand.rb
index a4beffd689..13b7329269 100644
--- a/test/ruby/test_rand.rb
+++ b/test/ruby/test_rand.rb
@@ -317,7 +317,7 @@ class TestRand < Test::Unit::TestCase
assert_equal(r1, r2, bug5661)
assert_fork_status(1, '[ruby-core:82100] [Bug #13753]') do
- Random.rand(4)
+ Random::DEFAULT.rand(4)
end
rescue NotImplementedError
end
@@ -336,14 +336,6 @@ class TestRand < Test::Unit::TestCase
}
end
- def test_seed_leading_zero_guard
- guard = 1<<32
- range = 0...(1<<32)
- all_assertions_foreach(nil, 0, 1, 2) do |i|
- assert_not_equal(Random.new(i).rand(range), Random.new(i+guard).rand(range))
- end
- end
-
def test_marshal
bug3656 = '[ruby-core:31622]'
assert_raise(TypeError, bug3656) {
@@ -403,8 +395,8 @@ class TestRand < Test::Unit::TestCase
assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
begin;
verbose, $VERBOSE = $VERBOSE, nil
- seed = Random.seed
- rand1 = Random.rand
+ seed = Random::DEFAULT::seed
+ rand1 = Random::DEFAULT::rand
$VERBOSE = verbose
rand2 = Random.new(seed).rand
assert_equal(rand1, rand2)
diff --git a/test/ruby/test_random_formatter.rb b/test/ruby/test_random_formatter.rb
index f927522d96..a5072099e1 100644
--- a/test/ruby/test_random_formatter.rb
+++ b/test/ruby/test_random_formatter.rb
@@ -75,47 +75,6 @@ module Random::Formatter
assert_match(/\A\h{8}-\h{4}-\h{4}-\h{4}-\h{12}\z/, uuid)
end
- def assert_uuid_v7(**opts)
- t1 = current_uuid7_time(**opts)
- uuid = @it.uuid_v7(**opts)
- t3 = current_uuid7_time(**opts)
-
- assert_match(/\A\h{8}-\h{4}-7\h{3}-[89ab]\h{3}-\h{12}\z/, uuid)
-
- t2 = get_uuid7_time(uuid, **opts)
- assert_operator(t1, :<=, t2)
- assert_operator(t2, :<=, t3)
- end
-
- def test_uuid_v7
- assert_uuid_v7
- 0.upto(12) do |extra_timestamp_bits|
- assert_uuid_v7 extra_timestamp_bits: extra_timestamp_bits
- end
- end
-
- # It would be nice to simply use Time#floor here. But that is problematic
- # due to the difference between decimal vs binary fractions.
- def current_uuid7_time(extra_timestamp_bits: 0)
- denominator = (1 << extra_timestamp_bits).to_r
- Process.clock_gettime(Process::CLOCK_REALTIME, :nanosecond)
- .then {|ns| ((ns / 1_000_000r) * denominator).floor / denominator }
- .then {|ms| Time.at(ms / 1000r, in: "+00:00") }
- end
-
- def get_uuid7_time(uuid, extra_timestamp_bits: 0)
- denominator = (1 << extra_timestamp_bits) * 1000r
- extra_chars = extra_timestamp_bits / 4
- last_char_bits = extra_timestamp_bits % 4
- extra_chars += 1 if last_char_bits != 0
- timestamp_re = /\A(\h{8})-(\h{4})-7(\h{#{extra_chars}})/
- timestamp_chars = uuid.match(timestamp_re).captures.join
- timestamp = timestamp_chars.to_i(16)
- timestamp >>= 4 - last_char_bits unless last_char_bits == 0
- timestamp /= denominator
- Time.at timestamp, in: "+00:00"
- end
-
def test_alphanumeric
65.times do |n|
an = @it.alphanumeric(n)
@@ -124,20 +83,6 @@ module Random::Formatter
end
end
- def test_alphanumeric_chars
- [
- [[*"0".."9"], /\A\d*\z/],
- [[*"a".."t"], /\A[a-t]*\z/],
- ["一二三四五六七八九十".chars, /\A[一二三四五六七八九十]*\z/],
- ].each do |chars, pattern|
- 10.times do |n|
- an = @it.alphanumeric(n, chars: chars)
- assert_match(pattern, an)
- assert_equal(n, an.length)
- end
- end
- end
-
def assert_in_range(range, result, mesg = nil)
assert(range.cover?(result), build_message(mesg, "Expected #{result} to be in #{range}"))
end
diff --git a/test/ruby/test_range.rb b/test/ruby/test_range.rb
index 2aa69dc6a4..dc591b0604 100644
--- a/test/ruby/test_range.rb
+++ b/test/ruby/test_range.rb
@@ -2,7 +2,7 @@
require 'test/unit'
require 'delegate'
require 'timeout'
-require 'date'
+require 'bigdecimal'
require 'rbconfig/sizeof'
class TestRange < Test::Unit::TestCase
@@ -392,26 +392,6 @@ class TestRange < Test::Unit::TestCase
assert_equal(4, (1.0...5.6).step(1.5).to_a.size)
end
- def test_step_with_succ
- c = Struct.new(:i) do
- def succ; self.class.new(i+1); end
- def <=>(other) i <=> other.i;end
- end.new(0)
-
- result = []
- (c..c.succ).step(2) do |d|
- result << d.i
- end
- assert_equal([0], result)
-
- result = []
- (c..).step(2) do |d|
- result << d.i
- break if d.i >= 4
- end
- assert_equal([0, 2, 4], result)
- end
-
def test_each
a = []
(0..10).each {|x| a << x }
@@ -476,171 +456,6 @@ class TestRange < Test::Unit::TestCase
assert_equal(["a", "b", "c"], a)
end
- def test_each_with_succ
- c = Struct.new(:i) do
- def succ; self.class.new(i+1); end
- def <=>(other) i <=> other.i;end
- end.new(0)
-
- result = []
- (c..c.succ).each do |d|
- result << d.i
- end
- assert_equal([0, 1], result)
-
- result = []
- (c..).each do |d|
- result << d.i
- break if d.i >= 4
- end
- assert_equal([0, 1, 2, 3, 4], result)
- end
-
- def test_reverse_each
- a = []
- (1..3).reverse_each {|x| a << x }
- assert_equal([3, 2, 1], a)
-
- a = []
- (1...3).reverse_each {|x| a << x }
- assert_equal([2, 1], a)
-
- fmax = RbConfig::LIMITS['FIXNUM_MAX']
- fmin = RbConfig::LIMITS['FIXNUM_MIN']
-
- a = []
- (fmax+1..fmax+3).reverse_each {|x| a << x }
- assert_equal([fmax+3, fmax+2, fmax+1], a)
-
- a = []
- (fmax+1...fmax+3).reverse_each {|x| a << x }
- assert_equal([fmax+2, fmax+1], a)
-
- a = []
- (fmax-1..fmax+1).reverse_each {|x| a << x }
- assert_equal([fmax+1, fmax, fmax-1], a)
-
- a = []
- (fmax-1...fmax+1).reverse_each {|x| a << x }
- assert_equal([fmax, fmax-1], a)
-
- a = []
- (fmin-1..fmin+1).reverse_each{|x| a << x }
- assert_equal([fmin+1, fmin, fmin-1], a)
-
- a = []
- (fmin-1...fmin+1).reverse_each{|x| a << x }
- assert_equal([fmin, fmin-1], a)
-
- a = []
- (fmin-3..fmin-1).reverse_each{|x| a << x }
- assert_equal([fmin-1, fmin-2, fmin-3], a)
-
- a = []
- (fmin-3...fmin-1).reverse_each{|x| a << x }
- assert_equal([fmin-2, fmin-3], a)
-
- a = []
- ("a".."c").reverse_each {|x| a << x }
- assert_equal(["c", "b", "a"], a)
- end
-
- def test_reverse_each_for_beginless_range
- fmax = RbConfig::LIMITS['FIXNUM_MAX']
- fmin = RbConfig::LIMITS['FIXNUM_MIN']
-
- a = []
- (..3).reverse_each {|x| a << x; break if x <= 0 }
- assert_equal([3, 2, 1, 0], a)
-
- a = []
- (...3).reverse_each {|x| a << x; break if x <= 0 }
- assert_equal([2, 1, 0], a)
-
- a = []
- (..fmax+1).reverse_each {|x| a << x; break if x <= fmax-1 }
- assert_equal([fmax+1, fmax, fmax-1], a)
-
- a = []
- (...fmax+1).reverse_each {|x| a << x; break if x <= fmax-1 }
- assert_equal([fmax, fmax-1], a)
-
- a = []
- (..fmin+1).reverse_each {|x| a << x; break if x <= fmin-1 }
- assert_equal([fmin+1, fmin, fmin-1], a)
-
- a = []
- (...fmin+1).reverse_each {|x| a << x; break if x <= fmin-1 }
- assert_equal([fmin, fmin-1], a)
-
- a = []
- (..fmin-1).reverse_each {|x| a << x; break if x <= fmin-3 }
- assert_equal([fmin-1, fmin-2, fmin-3], a)
-
- a = []
- (...fmin-1).reverse_each {|x| a << x; break if x <= fmin-3 }
- assert_equal([fmin-2, fmin-3], a)
- end
-
- def test_reverse_each_for_endless_range
- assert_raise(TypeError) { (1..).reverse_each {} }
-
- enum = nil
- assert_nothing_raised { enum = (1..).reverse_each }
- assert_raise(TypeError) { enum.each {} }
- end
-
- def test_reverse_each_for_single_point_range
- fmin = RbConfig::LIMITS['FIXNUM_MIN']
- fmax = RbConfig::LIMITS['FIXNUM_MAX']
-
- values = [fmin*2, fmin-1, fmin, 0, fmax, fmax+1, fmax*2]
-
- values.each do |b|
- r = b..b
- a = []
- r.reverse_each {|x| a << x }
- assert_equal([b], a, "failed on #{r}")
-
- r = b...b+1
- a = []
- r.reverse_each {|x| a << x }
- assert_equal([b], a, "failed on #{r}")
- end
- end
-
- def test_reverse_each_for_empty_range
- fmin = RbConfig::LIMITS['FIXNUM_MIN']
- fmax = RbConfig::LIMITS['FIXNUM_MAX']
-
- values = [fmin*2, fmin-1, fmin, 0, fmax, fmax+1, fmax*2]
-
- values.each do |b|
- r = b..b-1
- a = []
- r.reverse_each {|x| a << x }
- assert_equal([], a, "failed on #{r}")
- end
-
- values.repeated_permutation(2).to_a.product([true, false]).each do |(b, e), excl|
- next unless b > e || (b == e && excl)
-
- r = Range.new(b, e, excl)
- a = []
- r.reverse_each {|x| a << x }
- assert_equal([], a, "failed on #{r}")
- end
- end
-
- def test_reverse_each_with_no_block
- enum = (1..5).reverse_each
- assert_equal 5, enum.size
-
- a = []
- enum.each {|x| a << x }
- assert_equal [5, 4, 3, 2, 1], a
- end
-
def test_begin_end
assert_equal(0, (0..1).begin)
assert_equal(1, (0..1).end)
@@ -724,10 +539,6 @@ class TestRange < Test::Unit::TestCase
assert_not_operator(0..10, :===, 11)
assert_operator(5..nil, :===, 11)
assert_not_operator(5..nil, :===, 0)
- assert_operator(nil..10, :===, 0)
- assert_operator(nil..nil, :===, 0)
- assert_operator(nil..nil, :===, Object.new)
- assert_not_operator(0..10, :===, 0..10)
end
def test_eqq_string
@@ -772,28 +583,6 @@ class TestRange < Test::Unit::TestCase
assert_operator(c.new(0)..c.new(10), :===, c.new(5), bug12003)
end
- def test_eqq_unbounded_ruby_bug_19864
- t1 = Date.today
- t2 = t1 + 1
- assert_equal(true, (..t1) === t1)
- assert_equal(false, (..t1) === t2)
- assert_equal(true, (..t2) === t1)
- assert_equal(true, (..t2) === t2)
- assert_equal(false, (...t1) === t1)
- assert_equal(false, (...t1) === t2)
- assert_equal(true, (...t2) === t1)
- assert_equal(false, (...t2) === t2)
-
- assert_equal(true, (t1..) === t1)
- assert_equal(true, (t1..) === t2)
- assert_equal(false, (t2..) === t1)
- assert_equal(true, (t2..) === t2)
- assert_equal(true, (t1...) === t1)
- assert_equal(true, (t1...) === t2)
- assert_equal(false, (t2...) === t1)
- assert_equal(true, (t2...) === t2)
- end
-
def test_eqq_non_iteratable
k = Class.new do
include Comparable
@@ -810,16 +599,11 @@ class TestRange < Test::Unit::TestCase
assert_include("a"..."z", "y")
assert_not_include("a"..."z", "z")
assert_not_include("a".."z", "cc")
- assert_raise(TypeError) {("a"..).include?("c")}
- assert_raise(TypeError) {("a"..).include?("5")}
-
+ assert_include("a".., "c")
+ assert_not_include("a".., "5")
assert_include(0...10, 5)
assert_include(5..., 10)
assert_not_include(5..., 0)
- assert_raise(TypeError) {(.."z").include?("z")}
- assert_raise(TypeError) {(..."z").include?("z")}
- assert_include(..10, 10)
- assert_not_include(...10, 10)
end
def test_cover
@@ -987,22 +771,14 @@ class TestRange < Test::Unit::TestCase
assert_equal 41, (1...42).size
assert_equal 6, (1...6.3).size
assert_equal 5, (1.1...6).size
- assert_equal 3, (1..3r).size
- assert_equal 2, (1...3r).size
- assert_equal 3, (1..3.1r).size
- assert_equal 3, (1...3.1r).size
assert_equal 42, (1..42).each.size
assert_nil ("a"..."z").size
- assert_nil ("a"...).size
- assert_nil (..."z").size # [Bug #18983]
- assert_nil (nil...nil).size # [Bug #18983]
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
- assert_nil (..."z").size
end
def test_bsearch_typechecks_return_values
@@ -1026,6 +802,9 @@ class TestRange < Test::Unit::TestCase
assert_raise(TypeError) {
(Rational(-1,2)..Rational(9,4)).bsearch
}
+ assert_raise(TypeError) {
+ (BigDecimal('0.5')..BigDecimal('2.25')).bsearch
+ }
end
def test_bsearch_for_fixnum
@@ -1199,10 +978,7 @@ 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, (0...).bsearch {|i| i > bignum * 2 })
assert_equal(bignum * 2 + 1, (bignum...).bsearch {|i| i > bignum * 2 })
- assert_equal(-bignum * 2 + 1, (...0).bsearch {|i| i > -bignum * 2 })
assert_equal(-bignum * 2 + 1, (...-bignum).bsearch {|i| i > -bignum * 2 })
assert_raise(TypeError) { ("a".."z").bsearch {} }
@@ -1227,81 +1003,6 @@ class TestRange < Test::Unit::TestCase
end
def test_count
- assert_equal 42, (1..42).count
- assert_equal 41, (1...42).count
- assert_equal 0, (42..1).count
- assert_equal 0, (42...1).count
- assert_equal 2**100, (1..2**100).count
- assert_equal 6, (1...6.3).count
- assert_equal 4, ('a'..'d').count
- assert_equal 3, ('a'...'d').count
-
assert_equal(Float::INFINITY, (1..).count)
- assert_equal(Float::INFINITY, (..1).count)
- end
-
- def test_overlap?
- assert_not_operator(0..2, :overlap?, -2..-1)
- assert_not_operator(0..2, :overlap?, -2...0)
- assert_operator(0..2, :overlap?, -1..0)
- assert_operator(0..2, :overlap?, 1..2)
- assert_operator(0..2, :overlap?, 2..3)
- assert_not_operator(0..2, :overlap?, 3..4)
- assert_not_operator(0...2, :overlap?, 2..3)
-
- assert_operator(..0, :overlap?, -1..0)
- assert_operator(...0, :overlap?, -1..0)
- assert_operator(..0, :overlap?, 0..1)
- assert_operator(..0, :overlap?, ..1)
- assert_not_operator(..0, :overlap?, 1..2)
- assert_not_operator(...0, :overlap?, 0..1)
-
- assert_not_operator(0.., :overlap?, -2..-1)
- assert_not_operator(0.., :overlap?, ...0)
- assert_operator(0.., :overlap?, -1..0)
- assert_operator(0.., :overlap?, ..0)
- assert_operator(0.., :overlap?, 0..1)
- assert_operator(0.., :overlap?, 1..2)
- assert_operator(0.., :overlap?, 1..)
-
- assert_not_operator((1..3), :overlap?, ('a'..'d'))
- assert_not_operator((1..), :overlap?, ('a'..))
- assert_not_operator((..1), :overlap?, (..'a'))
-
- assert_raise(TypeError) { (0..).overlap?(1) }
- assert_raise(TypeError) { (0..).overlap?(nil) }
-
- assert_operator((1..3), :overlap?, (2..4))
- assert_operator((1...3), :overlap?, (2..3))
- assert_operator((2..3), :overlap?, (1..2))
- assert_operator((..3), :overlap?, (3..))
- assert_operator((nil..nil), :overlap?, (3..))
- assert_operator((nil...nil), :overlap?, (nil..))
-
- assert_raise(TypeError) { (1..3).overlap?(1) }
-
- assert_not_operator((1..2), :overlap?, (2...2))
- assert_not_operator((2...2), :overlap?, (1..2))
-
- assert_not_operator((4..1), :overlap?, (2..3))
- assert_not_operator((4..1), :overlap?, (..3))
- assert_not_operator((4..1), :overlap?, (2..))
-
- assert_not_operator((1..4), :overlap?, (3..2))
- assert_not_operator((..4), :overlap?, (3..2))
- assert_not_operator((1..), :overlap?, (3..2))
-
- assert_not_operator((4..5), :overlap?, (2..3))
- assert_not_operator((4..5), :overlap?, (2...4))
-
- assert_not_operator((1..2), :overlap?, (3..4))
- assert_not_operator((1...3), :overlap?, (3..4))
-
- assert_not_operator((4..5), :overlap?, (2..3))
- assert_not_operator((4..5), :overlap?, (2...4))
-
- assert_not_operator((1..2), :overlap?, (3..4))
- assert_not_operator((1...3), :overlap?, (3..4))
- assert_not_operator((...3), :overlap?, (3..))
end
end
diff --git a/test/ruby/test_rational.rb b/test/ruby/test_rational.rb
index a51ce3dc99..fe9de64c4c 100644
--- a/test/ruby/test_rational.rb
+++ b/test/ruby/test_rational.rb
@@ -823,8 +823,6 @@ class Rational_Test < Test::Unit::TestCase
ng[5, 1, '5/_3']
ng[5, 3, '5/3_']
ng[5, 3, '5/3x']
-
- ng[5, 1, '5/-3']
end
def test_parse_zero_denominator
diff --git a/test/ruby/test_refinement.rb b/test/ruby/test_refinement.rb
index d081bc9127..19857b035c 100644
--- a/test/ruby/test_refinement.rb
+++ b/test/ruby/test_refinement.rb
@@ -225,7 +225,7 @@ class TestRefinement < Test::Unit::TestCase
end
end
def test_method_should_use_refinements
- omit if Test::Unit::Runner.current_repeat_count > 0
+ skip if Test::Unit::Runner.current_repeat_count > 0
foo = Foo.new
assert_raise(NameError) { foo.method(:z) }
@@ -248,7 +248,7 @@ class TestRefinement < Test::Unit::TestCase
end
end
def test_instance_method_should_use_refinements
- omit if Test::Unit::Runner.current_repeat_count > 0
+ skip if Test::Unit::Runner.current_repeat_count > 0
foo = Foo.new
assert_raise(NameError) { Foo.instance_method(:z) }
@@ -754,32 +754,136 @@ class TestRefinement < Test::Unit::TestCase
$VERBOSE = verbose
end
- def test_include_into_refinement
- assert_raise(TypeError) do
- c = Class.new
- mixin = Module.new
+ module IncludeIntoRefinement
+ class C
+ def bar
+ return "C#bar"
+ end
- Module.new do
- refine c do
- include mixin
+ def baz
+ return "C#baz"
+ end
+ end
+
+ module Mixin
+ def foo
+ return "Mixin#foo"
+ end
+
+ def bar
+ return super << " Mixin#bar"
+ end
+
+ def baz
+ return super << " Mixin#baz"
+ end
+ end
+
+ module M
+ refine C do
+ TestRefinement.suppress_verbose do
+ include Mixin
+ end
+
+ def baz
+ return super << " M#baz"
end
end
end
end
- def test_prepend_into_refinement
- assert_raise(TypeError) do
- c = Class.new
- mixin = Module.new
+ eval <<-EOF, Sandbox::BINDING
+ using TestRefinement::IncludeIntoRefinement::M
- Module.new do
- refine c do
- prepend mixin
+ module TestRefinement::IncludeIntoRefinement::User
+ def self.invoke_foo_on(x)
+ x.foo
+ end
+
+ def self.invoke_bar_on(x)
+ x.bar
+ end
+
+ def self.invoke_baz_on(x)
+ x.baz
+ end
+ end
+ EOF
+
+ def test_include_into_refinement
+ x = IncludeIntoRefinement::C.new
+ assert_equal("Mixin#foo", IncludeIntoRefinement::User.invoke_foo_on(x))
+ assert_equal("C#bar Mixin#bar",
+ IncludeIntoRefinement::User.invoke_bar_on(x))
+ assert_equal("C#baz Mixin#baz M#baz",
+ IncludeIntoRefinement::User.invoke_baz_on(x))
+ end
+
+ module PrependIntoRefinement
+ class C
+ def bar
+ return "C#bar"
+ end
+
+ def baz
+ return "C#baz"
+ end
+ end
+
+ module Mixin
+ def foo
+ return "Mixin#foo"
+ end
+
+ def bar
+ return super << " Mixin#bar"
+ end
+
+ def baz
+ return super << " Mixin#baz"
+ end
+ end
+
+ module M
+ refine C do
+ TestRefinement.suppress_verbose do
+ prepend Mixin
+ end
+
+ def baz
+ return super << " M#baz"
end
end
end
end
+ eval <<-EOF, Sandbox::BINDING
+ using TestRefinement::PrependIntoRefinement::M
+
+ module TestRefinement::PrependIntoRefinement::User
+ def self.invoke_foo_on(x)
+ x.foo
+ end
+
+ def self.invoke_bar_on(x)
+ x.bar
+ end
+
+ def self.invoke_baz_on(x)
+ x.baz
+ end
+ end
+ EOF
+
+ def test_prepend_into_refinement
+ x = PrependIntoRefinement::C.new
+ assert_equal("Mixin#foo", PrependIntoRefinement::User.invoke_foo_on(x))
+ assert_equal("C#bar Mixin#bar",
+ PrependIntoRefinement::User.invoke_bar_on(x))
+ assert_equal("C#baz M#baz Mixin#baz",
+ PrependIntoRefinement::User.invoke_baz_on(x))
+ end
+
PrependAfterRefine_CODE = <<-EOC
module PrependAfterRefine
class C
@@ -819,7 +923,7 @@ class TestRefinement < Test::Unit::TestCase
def test_prepend_after_refine_wb_miss
if /\A(arm|mips)/ =~ RUBY_PLATFORM
- omit "too slow cpu"
+ skip "too slow cpu"
end
assert_normal_exit %Q{
GC.stress = true
@@ -1206,41 +1310,6 @@ class TestRefinement < Test::Unit::TestCase
INPUT
end
- def test_refined_protected_methods
- assert_separately([], <<-"end;")
- bug18806 = '[ruby-core:108705] [Bug #18806]'
- class C; end
-
- module R
- refine C do
- def refined_call_foo = foo
- def refined_call_foo_on(other) = other.foo
-
- protected
-
- def foo = :foo
- end
- end
-
- class C
- using R
-
- def call_foo = foo
- def call_foo_on(other) = other.foo
- end
-
- c = C.new
- assert_equal :foo, c.call_foo, bug18806
- assert_equal :foo, c.call_foo_on(c), bug18806
- assert_equal :foo, c.call_foo_on(C.new), bug18806
-
- using R
- assert_equal :foo, c.refined_call_foo, bug18806
- assert_equal :foo, c.refined_call_foo_on(c), bug18806
- assert_equal :foo, c.refined_call_foo_on(C.new), bug18806
- end;
- end
-
def test_refine_basic_object
assert_separately([], <<-"end;")
bug10106 = '[ruby-core:64166] [Bug #10106]'
@@ -1606,35 +1675,18 @@ class TestRefinement < Test::Unit::TestCase
end
using R
- def m
- C.new.m
- end
-
assert_equal(:foo, C.new.m)
- assert_equal(:foo, m)
module R
refine C do
-
- assert_equal(:foo, C.new.m)
- assert_equal(:foo, m)
-
alias m m
-
- assert_equal(:foo, C.new.m)
- assert_equal(:foo, m)
-
def m
:bar
end
-
- assert_equal(:bar, C.new.m, "[ruby-core:71423] [Bug #11672]")
- assert_equal(:bar, m, "[Bug #20285]")
end
end
assert_equal(:bar, C.new.m, "[ruby-core:71423] [Bug #11672]")
- assert_equal(:bar, m, "[Bug #20285]")
end;
end
@@ -1739,8 +1791,6 @@ class TestRefinement < Test::Unit::TestCase
refine Object do
def in_ref_a
end
-
- RefA.const_set(:REF, self)
end
end
@@ -1748,8 +1798,6 @@ class TestRefinement < Test::Unit::TestCase
refine Object do
def in_ref_b
end
-
- RefB.const_set(:REF, self)
end
end
@@ -1759,28 +1807,23 @@ class TestRefinement < Test::Unit::TestCase
refine Object do
def in_ref_c
end
-
- RefC.const_set(:REF, self)
end
end
module Foo
using RefB
USED_MODS = Module.used_modules
- USED_REFS = Module.used_refinements
end
module Bar
using RefC
USED_MODS = Module.used_modules
- USED_REFS = Module.used_refinements
end
module Combined
using RefA
using RefB
USED_MODS = Module.used_modules
- USED_REFS = Module.used_refinements
end
end
@@ -1792,47 +1835,6 @@ class TestRefinement < Test::Unit::TestCase
assert_equal [ref::RefB, ref::RefA], ref::Combined::USED_MODS
end
- def test_used_refinements
- ref = VisibleRefinements
- assert_equal [], Module.used_refinements
- assert_equal [ref::RefB::REF], ref::Foo::USED_REFS
- assert_equal [ref::RefC::REF], ref::Bar::USED_REFS
- assert_equal [ref::RefB::REF, ref::RefA::REF], ref::Combined::USED_REFS
- end
-
- def test_refinements
- int_refinement = nil
- str_refinement = nil
- m = Module.new {
- refine Integer do
- int_refinement = self
- end
-
- refine String do
- str_refinement = self
- end
- }
- assert_equal([int_refinement, str_refinement], m.refinements)
- end
-
- def test_target
- refinements = Module.new {
- refine Integer do
- end
-
- refine String do
- end
- }.refinements
- assert_equal(Integer, refinements[0].target)
- assert_warn(/Refinement#refined_class is deprecated and will be removed in Ruby 3.4; use Refinement#target instead/) do
- assert_equal(Integer, refinements[0].refined_class)
- end
- assert_equal(String, refinements[1].target)
- assert_warn(/Refinement#refined_class is deprecated and will be removed in Ruby 3.4; use Refinement#target instead/) do
- assert_equal(String, refinements[1].refined_class)
- end
- end
-
def test_warn_setconst_in_refinmenet
bug10103 = '[ruby-core:64143] [Bug #10103]'
warnings = [
@@ -1977,10 +1979,10 @@ class TestRefinement < Test::Unit::TestCase
m = Module.new do
r = refine(String) {def test;:ok end}
end
- assert_raise_with_message(TypeError, /refinement/, bug) do
+ assert_raise_with_message(ArgumentError, /refinement/, bug) do
m.module_eval {include r}
end
- assert_raise_with_message(TypeError, /refinement/, bug) do
+ assert_raise_with_message(ArgumentError, /refinement/, bug) do
m.module_eval {prepend r}
end
end
@@ -2624,6 +2626,18 @@ class TestRefinement < Test::Unit::TestCase
end
end
+ module D
+ refine A do
+ TestRefinement.suppress_verbose do
+ include B
+ end
+
+ def foo
+ "refined"
+ end
+ end
+ end
+
module UsingC
using C
@@ -2631,10 +2645,19 @@ class TestRefinement < Test::Unit::TestCase
A.new.bar
end
end
+
+ module UsingD
+ using D
+
+ def self.call_bar
+ A.new.bar
+ end
+ end
end
def test_import_methods
assert_equal("refined:bar", TestImport::UsingC.call_bar)
+ assert_equal("original:bar", TestImport::UsingD.call_bar)
assert_raise(ArgumentError) do
Module.new do
@@ -2649,46 +2672,6 @@ class TestRefinement < Test::Unit::TestCase
assert_equal([], Refinement.used_modules)
end
- def test_inlinecache
- assert_separately([], <<-"end;")
- module R
- refine String do
- def to_s = :R
- end
- end
-
- 2.times{|i|
- s = ''.to_s
- assert_equal '', s if i == 0
- assert_equal :R, s if i == 1
- using R if i == 0
- assert_equal :R, ''.to_s
- }
- end;
- end
-
- def test_inline_cache_invalidation
- klass = Class.new do
- def cached_foo_callsite = foo
-
- def foo = :v1
-
- host = self
- @refinement = Module.new do
- refine(host) do
- def foo = :unused
- end
- end
- end
-
- obj = klass.new
- obj.cached_foo_callsite # prime cache
- klass.class_eval do
- def foo = :v2 # invalidate
- end
- assert_equal(:v2, obj.cached_foo_callsite)
- end
-
private
def eval_using(mod, s)
diff --git a/test/ruby/test_regexp.rb b/test/ruby/test_regexp.rb
index 74425c4b31..16a6ed921f 100644
--- a/test/ruby/test_regexp.rb
+++ b/test/ruby/test_regexp.rb
@@ -40,6 +40,19 @@ class TestRegexp < Test::Unit::TestCase
assert_equal("a".gsub(/a\Z/, ""), "")
end
+ def test_yoshidam_net_20041111_1
+ s = "[\xC2\xA0-\xC3\xBE]"
+ r = assert_deprecated_warning(/ignored/) {Regexp.new(s, nil, "u")}
+ assert_match(r, "\xC3\xBE")
+ end
+
+ def test_yoshidam_net_20041111_2
+ assert_raise(RegexpError) do
+ s = "[\xFF-\xFF]".force_encoding("utf-8")
+ assert_warning(/ignored/) {Regexp.new(s, nil, "u")}
+ end
+ end
+
def test_ruby_dev_31309
assert_equal('Ruby', 'Ruby'.sub(/[^a-z]/i, '-'))
end
@@ -72,140 +85,12 @@ class TestRegexp < Test::Unit::TestCase
end
end
- def test_to_s_under_gc_compact_stress
- EnvUtil.under_gc_compact_stress do
- str = "abcd\u3042"
- [:UTF_16BE, :UTF_16LE, :UTF_32BE, :UTF_32LE].each do |es|
- enc = Encoding.const_get(es)
- rs = Regexp.new(str.encode(enc)).to_s
- assert_equal("(?-mix:abcd\u3042)".encode(enc), rs)
- assert_equal(enc, rs.encoding)
- end
- end
- end
-
def test_to_s_extended_subexp
re = /#\g#{"\n"}/x
re = /#{re}/
assert_warn('', '[ruby-core:82328] [Bug #13798]') {re.to_s}
end
- def test_extended_comment_invalid_escape_bug_18294
- assert_separately([], <<-RUBY)
- re = / C:\\\\[a-z]{5} # e.g. C:\\users /x
- assert_match(re, 'C:\\users')
- assert_not_match(re, 'C:\\user')
-
- re = /
- foo # \\M-ca
- bar
- /x
- assert_match(re, 'foobar')
- assert_not_match(re, 'foobaz')
-
- re = /
- f[#o]o # \\M-ca
- bar
- /x
- assert_match(re, 'foobar')
- assert_not_match(re, 'foobaz')
-
- re = /
- f[[:alnum:]#]o # \\M-ca
- bar
- /x
- assert_match(re, 'foobar')
- assert_not_match(re, 'foobaz')
-
- re = /
- f(?# \\M-ca)oo # \\M-ca
- bar
- /x
- assert_match(re, 'foobar')
- assert_not_match(re, 'foobaz')
-
- re = /f(?# \\M-ca)oobar/
- assert_match(re, 'foobar')
- assert_not_match(re, 'foobaz')
-
- re = /[-(?# fca)]oobar/
- assert_match(re, 'foobar')
- assert_not_match(re, 'foobaz')
-
- re = /f(?# ca\0\\M-ca)oobar/
- assert_match(re, 'foobar')
- assert_not_match(re, 'foobaz')
- RUBY
-
- assert_raise(SyntaxError) {eval "/\\users/x"}
- assert_raise(SyntaxError) {eval "/[\\users]/x"}
- assert_raise(SyntaxError) {eval "/(?<\\users)/x"}
- assert_raise(SyntaxError) {eval "/# \\users/"}
- end
-
- def test_nonextended_section_of_extended_regexp_bug_19379
- assert_separately([], <<-'RUBY')
- re = /(?-x:#)/x
- assert_match(re, '#')
- assert_not_match(re, '-')
-
- re = /(?xi:#
- y)/
- assert_match(re, 'Y')
- assert_not_match(re, '-')
-
- re = /(?mix:#
- y)/
- assert_match(re, 'Y')
- assert_not_match(re, '-')
-
- re = /(?x-im:#
- y)/i
- assert_match(re, 'y')
- assert_not_match(re, 'Y')
-
- re = /(?-imx:(?xim:#
- y))/x
- assert_match(re, 'y')
- assert_not_match(re, '-')
-
- re = /(?x)#
- y/
- assert_match(re, 'y')
- assert_not_match(re, 'Y')
-
- re = /(?mx-i)#
- y/i
- assert_match(re, 'y')
- assert_not_match(re, 'Y')
-
- re = /(?-imx:(?xim:#
- (?-x)y#))/x
- assert_match(re, 'Y#')
- assert_not_match(re, '-#')
-
- re = /(?imx:#
- (?-xim:#(?im)#(?x)#
- )#
- (?x)#
- y)/
- assert_match(re, '###Y')
- assert_not_match(re, '###-')
-
- re = %r{#c-\w+/comment/[\w-]+}
- re = %r{https?://[^/]+#{re}}x
- assert_match(re, 'http://foo#c-x/comment/bar')
- assert_not_match(re, 'http://foo#cx/comment/bar')
- RUBY
- end
-
- def test_utf8_comment_in_usascii_extended_regexp_bug_19455
- assert_separately([], <<-RUBY)
- assert_equal(Encoding::UTF_8, /(?#\u1000)/x.encoding)
- assert_equal(Encoding::UTF_8, /#\u1000/x.encoding)
- RUBY
- end
-
def test_union
assert_equal :ok, begin
Regexp.union(
@@ -323,9 +208,6 @@ class TestRegexp < Test::Unit::TestCase
assert_equal({'a' => '1', 'b' => '2', 'c' => '3'}, /^(?<a>.)(?<b>.)(?<c>.)?/.match('123').named_captures)
assert_equal({'a' => '1', 'b' => '2', 'c' => ''}, /^(?<a>.)(?<b>.)(?<c>.?)/.match('12').named_captures)
- assert_equal({a: '1', b: '2', c: ''}, /^(?<a>.)(?<b>.)(?<c>.?)/.match('12').named_captures(symbolize_names: true))
- assert_equal({'a' => '1', 'b' => '2', 'c' => ''}, /^(?<a>.)(?<b>.)(?<c>.?)/.match('12').named_captures(symbolize_names: false))
-
assert_equal({'a' => 'x'}, /(?<a>x)|(?<a>y)/.match('x').named_captures)
assert_equal({'a' => 'y'}, /(?<a>x)|(?<a>y)/.match('y').named_captures)
@@ -469,12 +351,6 @@ class TestRegexp < Test::Unit::TestCase
assert_equal('/\/\xF1\xF2\xF3/i', /\/#{s}/i.inspect)
end
- def test_inspect_under_gc_compact_stress
- EnvUtil.under_gc_compact_stress do
- assert_equal('/(?-mix:\\/)|/', Regexp.union(/\//, "").inspect)
- end
- end
-
def test_char_to_option
assert_equal("BAR", "FOOBARBAZ"[/b../i])
assert_equal("bar", "foobarbaz"[/ b . . /x])
@@ -548,27 +424,6 @@ class TestRegexp < Test::Unit::TestCase
assert_equal([2, 3], m.offset(3))
end
- def test_match_byteoffset_begin_end
- m = /(?<x>b..)/.match("foobarbaz")
- assert_equal([3, 6], m.byteoffset("x"))
- assert_equal(3, m.begin("x"))
- assert_equal(6, m.end("x"))
- assert_raise(IndexError) { m.byteoffset("y") }
- assert_raise(IndexError) { m.byteoffset(2) }
- assert_raise(IndexError) { m.begin(2) }
- assert_raise(IndexError) { m.end(2) }
-
- m = /(?<x>q..)?/.match("foobarbaz")
- assert_equal([nil, nil], m.byteoffset("x"))
- assert_equal(nil, m.begin("x"))
- assert_equal(nil, m.end("x"))
-
- m = /\A\u3042(.)(.)?(.)\z/.match("\u3042\u3043\u3044")
- assert_equal([3, 6], m.byteoffset(1))
- assert_equal([nil, nil], m.byteoffset(2))
- assert_equal([6, 9], m.byteoffset(3))
- end
-
def test_match_to_s
m = /(?<x>b..)/.match("foobarbaz")
assert_equal("bar", m.to_s)
@@ -679,73 +534,17 @@ class TestRegexp < Test::Unit::TestCase
assert_equal('#<MatchData "foobarbaz" 1:"foo" 2:"bar" 3:"baz" 4:nil>', m.inspect)
end
- def test_match_data_deconstruct
- m = /foo.+/.match("foobarbaz")
- assert_equal([], m.deconstruct)
-
- m = /(foo).+(baz)/.match("foobarbaz")
- assert_equal(["foo", "baz"], m.deconstruct)
-
- m = /(...)(...)(...)(...)?/.match("foobarbaz")
- assert_equal(["foo", "bar", "baz", nil], m.deconstruct)
- end
-
- def test_match_data_deconstruct_keys
- m = /foo.+/.match("foobarbaz")
- assert_equal({}, m.deconstruct_keys([:a]))
-
- m = /(?<a>foo).+(?<b>baz)/.match("foobarbaz")
- assert_equal({a: "foo", b: "baz"}, m.deconstruct_keys(nil))
- assert_equal({a: "foo", b: "baz"}, m.deconstruct_keys([:a, :b]))
- assert_equal({b: "baz"}, m.deconstruct_keys([:b]))
- assert_equal({}, m.deconstruct_keys([:c, :a]))
- assert_equal({a: "foo"}, m.deconstruct_keys([:a, :c]))
- assert_equal({}, m.deconstruct_keys([:a, :b, :c]))
-
- assert_raise(TypeError) {
- m.deconstruct_keys(0)
- }
-
- assert_raise(TypeError) {
- m.deconstruct_keys(["a", "b"])
- }
- end
-
- def test_match_no_match_no_matchdata
- EnvUtil.without_gc do
- h = {}
- ObjectSpace.count_objects(h)
- prev_matches = h[:T_MATCH] || 0
- md = /[A-Z]/.match('1') # no match
- ObjectSpace.count_objects(h)
- new_matches = h[:T_MATCH] || 0
- assert_equal prev_matches, new_matches, "Bug [#20104]"
- end
- end
-
def test_initialize
assert_raise(ArgumentError) { Regexp.new }
assert_equal(/foo/, assert_warning(/ignored/) {Regexp.new(/foo/, Regexp::IGNORECASE)})
- assert_equal(/foo/, assert_no_warning(/ignored/) {Regexp.new(/foo/)})
- assert_equal(/foo/, assert_no_warning(/ignored/) {Regexp.new(/foo/, timeout: nil)})
- arg_encoding_none = //n.options # ARG_ENCODING_NONE is implementation defined value
+ assert_equal(Encoding.find("US-ASCII"), Regexp.new("b..", nil, "n").encoding)
+ assert_equal("bar", "foobarbaz"[Regexp.new("b..", nil, "n")])
+ assert_equal(//n, Regexp.new("", nil, "n"))
- assert_deprecated_warning('') do
- assert_equal(Encoding.find("US-ASCII"), Regexp.new("b..", Regexp::NOENCODING).encoding)
- assert_equal("bar", "foobarbaz"[Regexp.new("b..", Regexp::NOENCODING)])
- assert_equal(//, Regexp.new(""))
- assert_equal(//, Regexp.new("", timeout: 1))
- assert_equal(//n, Regexp.new("", Regexp::NOENCODING))
- assert_equal(//n, Regexp.new("", Regexp::NOENCODING, timeout: 1))
-
- assert_equal(arg_encoding_none, Regexp.new("", Regexp::NOENCODING).options)
-
- assert_nil(Regexp.new("").timeout)
- assert_equal(1.0, Regexp.new("", timeout: 1.0).timeout)
- assert_nil(Regexp.compile("").timeout)
- assert_equal(1.0, Regexp.compile("", timeout: 1.0).timeout)
- end
+ arg_encoding_none = 32 # ARG_ENCODING_NONE is implementation defined value
+ assert_equal(arg_encoding_none, Regexp.new("", nil, "n").options)
+ assert_equal(arg_encoding_none, Regexp.new("", nil, "N").options)
assert_raise(RegexpError) { Regexp.new(")(") }
assert_raise(RegexpError) { Regexp.new('[\\40000000000') }
@@ -753,35 +552,6 @@ class TestRegexp < Test::Unit::TestCase
assert_raise(RegexpError) { Regexp.new("((?<v>))\\g<0>") }
end
- def test_initialize_from_regex_memory_corruption
- assert_ruby_status([], <<-'end;')
- 10_000.times { Regexp.new(Regexp.new("(?<name>)")) }
- end;
- end
-
- def test_initialize_bool_warning
- assert_warning(/expected true or false as ignorecase/) do
- Regexp.new("foo", :i)
- end
- end
-
- def test_initialize_option
- assert_equal(//i, Regexp.new("", "i"))
- assert_equal(//m, Regexp.new("", "m"))
- assert_equal(//x, Regexp.new("", "x"))
- assert_equal(//imx, Regexp.new("", "imx"))
- assert_equal(//, Regexp.new("", ""))
- assert_equal(//imx, Regexp.new("", "mimix"))
-
- assert_raise(ArgumentError) { Regexp.new("", "e") }
- assert_raise(ArgumentError) { Regexp.new("", "n") }
- assert_raise(ArgumentError) { Regexp.new("", "s") }
- assert_raise(ArgumentError) { Regexp.new("", "u") }
- assert_raise(ArgumentError) { Regexp.new("", "o") }
- assert_raise(ArgumentError) { Regexp.new("", "j") }
- assert_raise(ArgumentError) { Regexp.new("", "xmen") }
- end
-
def test_match_control_meta_escape
assert_equal(0, /\c\xFF/ =~ "\c\xFF")
assert_equal(0, /\c\M-\xFF/ =~ "\c\M-\xFF")
@@ -890,13 +660,6 @@ class TestRegexp < Test::Unit::TestCase
$_ = nil; assert_nil(~/./)
end
- def test_match_under_gc_compact_stress
- EnvUtil.under_gc_compact_stress do
- m = /(?<foo>.)(?<n>[^aeiou])?(?<bar>.+)/.match("hoge\u3042")
- assert_equal("h", m.match(:foo))
- end
- end
-
def test_match_p
/backref/ =~ 'backref'
# must match here, but not in a separate method, e.g., assert_send,
@@ -1403,109 +1166,25 @@ class TestRegexp < Test::Unit::TestCase
end
def test_unicode_age
- assert_unicode_age("\u261c", matches: %w"6.0 1.1", unmatches: [])
-
- assert_unicode_age("\u31f6", matches: %w"6.0 3.2", unmatches: %w"3.1 3.0 1.1")
- assert_unicode_age("\u2754", matches: %w"6.0", unmatches: %w"5.0 4.0 3.0 2.0 1.1")
-
- assert_unicode_age("\u32FF", matches: %w"12.1", unmatches: %w"12.0")
- end
-
- def test_unicode_age_14_0
- @matches = %w"14.0"
- @unmatches = %w"13.0"
-
- assert_unicode_age("\u{10570}")
- assert_unicode_age("\u9FFF")
- assert_unicode_age("\u{2A6DF}")
- assert_unicode_age("\u{2B738}")
- end
-
- def test_unicode_age_15_0
- @matches = %w"15.0"
- @unmatches = %w"14.0"
-
- assert_unicode_age("\u{0CF3}",
- "KANNADA SIGN COMBINING ANUSVARA ABOVE RIGHT")
- assert_unicode_age("\u{0ECE}", "LAO YAMAKKAN")
- assert_unicode_age("\u{10EFD}".."\u{10EFF}",
- "ARABIC SMALL LOW WORD SAKTA..ARABIC SMALL LOW WORD MADDA")
- assert_unicode_age("\u{1123F}".."\u{11241}",
- "KHOJKI LETTER QA..KHOJKI VOWEL SIGN VOCALIC R")
- assert_unicode_age("\u{11B00}".."\u{11B09}",
- "DEVANAGARI HEAD MARK..DEVANAGARI SIGN MINDU")
- assert_unicode_age("\u{11F00}".."\u{11F10}",
- "KAWI SIGN CANDRABINDU..KAWI LETTER O")
- assert_unicode_age("\u{11F12}".."\u{11F3A}",
- "KAWI LETTER KA..KAWI VOWEL SIGN VOCALIC R")
- assert_unicode_age("\u{11F3E}".."\u{11F59}",
- "KAWI VOWEL SIGN E..KAWI DIGIT NINE")
- assert_unicode_age("\u{1342F}",
- "EGYPTIAN HIEROGLYPH V011D")
- assert_unicode_age("\u{13439}".."\u{1343F}",
- "EGYPTIAN HIEROGLYPH INSERT AT MIDDLE..EGYPTIAN HIEROGLYPH END WALLED ENCLOSURE")
- assert_unicode_age("\u{13440}".."\u{13455}",
- "EGYPTIAN HIEROGLYPH MIRROR HORIZONTALLY..EGYPTIAN HIEROGLYPH MODIFIER DAMAGED")
- assert_unicode_age("\u{1B132}", "HIRAGANA LETTER SMALL KO")
- assert_unicode_age("\u{1B155}", "KATAKANA LETTER SMALL KO")
- assert_unicode_age("\u{1D2C0}".."\u{1D2D3}",
- "KAKTOVIK NUMERAL ZERO..KAKTOVIK NUMERAL NINETEEN")
- assert_unicode_age("\u{1DF25}".."\u{1DF2A}",
- "LATIN SMALL LETTER D WITH MID-HEIGHT LEFT HOOK..LATIN SMALL LETTER T WITH MID-HEIGHT LEFT HOOK")
- assert_unicode_age("\u{1E030}".."\u{1E06D}",
- "MODIFIER LETTER CYRILLIC SMALL A..MODIFIER LETTER CYRILLIC SMALL STRAIGHT U WITH STROKE")
- assert_unicode_age("\u{1E08F}",
- "COMBINING CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I")
- assert_unicode_age("\u{1E4D0}".."\u{1E4F9}",
- "NAG MUNDARI LETTER O..NAG MUNDARI DIGIT NINE")
- assert_unicode_age("\u{1F6DC}", "WIRELESS")
- assert_unicode_age("\u{1F774}".."\u{1F776}",
- "LOT OF FORTUNE..LUNAR ECLIPSE")
- assert_unicode_age("\u{1F77B}".."\u{1F77F}",
- "HAUMEA..ORCUS")
- assert_unicode_age("\u{1F7D9}", "NINE POINTED WHITE STAR")
- assert_unicode_age("\u{1FA75}".."\u{1FA77}",
- "LIGHT BLUE HEART..PINK HEART")
- assert_unicode_age("\u{1FA87}".."\u{1FA88}",
- "MARACAS..FLUTE")
- assert_unicode_age("\u{1FAAD}".."\u{1FAAF}",
- "FOLDING HAND FAN..KHANDA")
- assert_unicode_age("\u{1FABB}".."\u{1FABD}",
- "HYACINTH..WING")
- assert_unicode_age("\u{1FABF}", "GOOSE")
- assert_unicode_age("\u{1FACE}".."\u{1FACF}",
- "MOOSE..DONKEY")
- assert_unicode_age("\u{1FADA}".."\u{1FADB}",
- "GINGER ROOT..PEA POD")
- assert_unicode_age("\u{1FAE8}", "SHAKING FACE")
- assert_unicode_age("\u{1FAF7}".."\u{1FAF8}",
- "LEFTWARDS PUSHING HAND..RIGHTWARDS PUSHING HAND")
- assert_unicode_age("\u{2B739}",
- "CJK UNIFIED IDEOGRAPH-2B739")
- assert_unicode_age("\u{31350}".."\u{323AF}",
- "CJK UNIFIED IDEOGRAPH-31350..CJK UNIFIED IDEOGRAPH-323AF")
- end
-
- UnicodeAgeRegexps = Hash.new do |h, age|
- h[age] = [/\A\p{age=#{age}}+\z/u, /\A\P{age=#{age}}+\z/u].freeze
- end
-
- def assert_unicode_age(char, mesg = nil, matches: @matches, unmatches: @unmatches)
- if Range === char
- char = char.to_a.join("")
- end
+ assert_match(/^\p{Age=6.0}$/u, "\u261c")
+ assert_match(/^\p{Age=1.1}$/u, "\u261c")
+ assert_no_match(/^\P{age=6.0}$/u, "\u261c")
- matches.each do |age|
- pos, neg = UnicodeAgeRegexps[age]
- assert_match(pos, char, mesg)
- assert_not_match(neg, char, mesg)
- end
+ assert_match(/^\p{age=6.0}$/u, "\u31f6")
+ assert_match(/^\p{age=3.2}$/u, "\u31f6")
+ assert_no_match(/^\p{age=3.1}$/u, "\u31f6")
+ assert_no_match(/^\p{age=3.0}$/u, "\u31f6")
+ assert_no_match(/^\p{age=1.1}$/u, "\u31f6")
- unmatches.each do |age|
- pos, neg = UnicodeAgeRegexps[age]
- assert_not_match(pos, char, mesg)
- assert_match(neg, char, mesg)
- end
+ assert_match(/^\p{age=6.0}$/u, "\u2754")
+ assert_no_match(/^\p{age=5.0}$/u, "\u2754")
+ assert_no_match(/^\p{age=4.0}$/u, "\u2754")
+ 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")
@@ -1710,9 +1389,6 @@ class TestRegexp < Test::Unit::TestCase
assert_equal(0, /(?~(a)c)/ =~ "abb")
assert_nil($1)
-
- assert_equal(0, /(?~(a))/ =~ "")
- assert_nil($1)
end
def test_backref_overrun
@@ -1721,12 +1397,6 @@ class TestRegexp < Test::Unit::TestCase
end
end
- def test_bug18631
- assert_kind_of MatchData, /(?<x>a)(?<x>aa)\k<x>/.match("aaaaa")
- assert_kind_of MatchData, /(?<x>a)(?<x>aa)\k<x>/.match("aaaa")
- assert_kind_of MatchData, /(?<x>a)(?<x>aa)\k<x>/.match("aaaab")
- end
-
def test_invalid_group
assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
begin;
@@ -1736,6 +1406,12 @@ class TestRegexp < Test::Unit::TestCase
end;
end
+ def test_bug18631
+ assert_kind_of MatchData, /(?<x>a)(?<x>aa)\k<x>/.match("aaaaa")
+ assert_kind_of MatchData, /(?<x>a)(?<x>aa)\k<x>/.match("aaaa")
+ assert_kind_of MatchData, /(?<x>a)(?<x>aa)\k<x>/.match("aaaab")
+ end
+
# This assertion is for porting x2() tests in testpy.py of Onigmo.
def assert_match_at(re, str, positions, msg = nil)
re = Regexp.new(re) unless re.is_a?(Regexp)
@@ -1765,309 +1441,4 @@ class TestRegexp < Test::Unit::TestCase
}
assert_empty(errs, msg)
end
-
- def test_s_timeout
- assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
- timeout = #{ EnvUtil.apply_timeout_scale(0.2).inspect }
- begin;
- Regexp.timeout = timeout
- assert_in_delta(timeout, Regexp.timeout, timeout * 2 * Float::EPSILON)
-
- t = Time.now
- assert_raise_with_message(Regexp::TimeoutError, "regexp match timeout") do
- # A typical ReDoS case
- /^(a*)*\1$/ =~ "a" * 1000000 + "x"
- end
- t = Time.now - t
-
- assert_in_delta(timeout, t, timeout / 2)
- end;
- end
-
- def test_s_timeout_corner_cases
- assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
- begin;
- assert_nil(Regexp.timeout)
-
- # This is just an implementation detail that users should not depend on:
- # If Regexp.timeout is set to a value greater than the value that can be
- # represented in the internal representation of timeout, it uses the
- # maximum value that can be represented.
- Regexp.timeout = Float::INFINITY
- assert_equal(((1<<64)-1) / 1000000000.0, Regexp.timeout)
-
- Regexp.timeout = 1e300
- assert_equal(((1<<64)-1) / 1000000000.0, Regexp.timeout)
-
- assert_raise(ArgumentError) { Regexp.timeout = 0 }
- assert_raise(ArgumentError) { Regexp.timeout = -1 }
-
- Regexp.timeout = nil
- assert_nil(Regexp.timeout)
- end;
- end
-
- def test_s_timeout_memory_leak
- assert_no_memory_leak([], "#{<<~"begin;"}", "#{<<~"end;"}", "[Bug #20228]", rss: true)
- Regexp.timeout = 0.001
- regex = /^(a*)*$/
- str = "a" * 1000000 + "x"
-
- code = proc do
- regex =~ str
- rescue
- end
-
- 10.times(&code)
- begin;
- 1_000.times(&code)
- end;
- end
-
- def per_instance_redos_test(global_timeout, per_instance_timeout, expected_timeout)
- assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
- global_timeout = #{ EnvUtil.apply_timeout_scale(global_timeout).inspect }
- per_instance_timeout = #{ (per_instance_timeout ? EnvUtil.apply_timeout_scale(per_instance_timeout) : nil).inspect }
- expected_timeout = #{ EnvUtil.apply_timeout_scale(expected_timeout).inspect }
- begin;
- Regexp.timeout = global_timeout
-
- re = Regexp.new("^(a*)\\1b?a*$", timeout: per_instance_timeout)
- if per_instance_timeout
- assert_in_delta(per_instance_timeout, re.timeout, per_instance_timeout * 2 * Float::EPSILON)
- else
- assert_nil(re.timeout)
- end
-
- t = Time.now
- assert_raise_with_message(Regexp::TimeoutError, "regexp match timeout") do
- re =~ "a" * 1000000 + "x"
- end
- t = Time.now - t
-
- assert_in_delta(expected_timeout, t, expected_timeout * 3 / 4)
- end;
- end
-
- def test_timeout_shorter_than_global
- omit "timeout test is too unstable on s390x" if RUBY_PLATFORM =~ /s390x/
- per_instance_redos_test(10, 0.2, 0.2)
- end
-
- def test_timeout_longer_than_global
- omit "timeout test is too unstable on s390x" if RUBY_PLATFORM =~ /s390x/
- per_instance_redos_test(0.01, 0.5, 0.5)
- end
-
- def test_timeout_nil
- per_instance_redos_test(0.5, nil, 0.5)
- end
-
- def test_timeout_corner_cases
- assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
- begin;
- assert_nil(//.timeout)
-
- # This is just an implementation detail that users should not depend on:
- # If Regexp.timeout is set to a value greater than the value that can be
- # represented in the internal representation of timeout, it uses the
- # maximum value that can be represented.
- assert_equal(((1<<64)-1) / 1000000000.0, Regexp.new("foo", timeout: Float::INFINITY).timeout)
-
- assert_equal(((1<<64)-1) / 1000000000.0, Regexp.new("foo", timeout: 1e300).timeout)
-
- assert_raise(ArgumentError) { Regexp.new("foo", timeout: 0) }
- assert_raise(ArgumentError) { Regexp.new("foo", timeout: -1) }
- end;
- end
-
- def test_match_cache_exponential
- assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
- timeout = #{ EnvUtil.apply_timeout_scale(10).inspect }
- begin;
- Regexp.timeout = timeout
- assert_nil(/^(a*)*$/ =~ "a" * 1000000 + "x")
- end;
- end
-
- def test_match_cache_square
- assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
- timeout = #{ EnvUtil.apply_timeout_scale(10).inspect }
- begin;
- Regexp.timeout = timeout
- assert_nil(/^a*b?a*$/ =~ "a" * 1000000 + "x")
- end;
- end
-
- def test_match_cache_atomic
- assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
- timeout = #{ EnvUtil.apply_timeout_scale(10).inspect }
- begin;
- Regexp.timeout = timeout
- assert_nil(/^a*?(?>a*a*)$/ =~ "a" * 1000000 + "x")
- end;
- end
-
- def test_match_cache_atomic_complex
- assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
- timeout = #{ EnvUtil.apply_timeout_scale(10).inspect }
- begin;
- Regexp.timeout = timeout
- assert_nil(/a*(?>a*)ab/ =~ "a" * 1000000 + "b")
- end;
- end
-
- def test_match_cache_positive_look_ahead
- assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
- timeout = #{ EnvUtil.apply_timeout_scale(10).inspect }
- begin;
- Regexp.timeout = timeout
- assert_nil(/^a*?(?=a*a*)$/ =~ "a" * 1000000 + "x")
- end;
- end
-
- def test_match_cache_positive_look_ahead_complex
- assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
- timeout = #{ EnvUtil.apply_timeout_scale(10).inspect }
- begin;
- Regexp.timeout = timeout
- assert_equal(/(?:(?=a*)a)*/ =~ "a" * 1000000, 0)
- end;
- end
-
- def test_match_cache_negative_look_ahead
- assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
- timeout = #{ EnvUtil.apply_timeout_scale(10).inspect }
- begin;
- Regexp.timeout = timeout
- assert_nil(/^a*?(?!a*a*)$/ =~ "a" * 1000000 + "x")
- end;
- end
-
- def test_match_cache_positive_look_behind
- assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
- timeout = #{ EnvUtil.apply_timeout_scale(10).inspect }
- begin;
- Regexp.timeout = timeout
- assert_nil(/(?<=abc|def)(a|a)*$/ =~ "abc" + "a" * 1000000 + "x")
- end;
- end
-
- def test_match_cache_negative_look_behind
- assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
- timeout = #{ EnvUtil.apply_timeout_scale(10).inspect }
- begin;
- Regexp.timeout = timeout
- assert_nil(/(?<!x)(a|a)*$/ =~ "a" * 1000000 + "x")
- end;
- end
-
- def test_match_cache_with_peek_optimization
- assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
- timeout = #{ EnvUtil.apply_timeout_scale(10).inspect }
- begin;
- Regexp.timeout = timeout
- assert_nil(/a+z/ =~ "a" * 1000000 + "xz")
- end;
- end
-
- def test_cache_opcodes_initialize
- str = 'test1-test2-test3-test4-test_5'
- re = '^([0-9a-zA-Z\-/]*){1,256}$'
- 100.times do
- assert !Regexp.new(re).match?(str)
- end
- end
-
- def test_bug_19273 # [Bug #19273]
- pattern = /(?:(?:-?b)|(?:-?(?:1_?(?:0_?)*)?0))(?::(?:(?:-?b)|(?:-?(?:1_?(?:0_?)*)?0))){0,3}/
- assert_equal("10:0:0".match(pattern)[0], "10:0:0")
- end
-
- def test_bug_19467 # [Bug #19467]
- assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
- timeout = #{ EnvUtil.apply_timeout_scale(10).inspect }
- begin;
- Regexp.timeout = timeout
-
- assert_nil(/\A.*a.*z\z/ =~ "a" * 1000000 + "y")
- end;
- end
-
- def test_bug_19476 # [Bug #19476]
- assert_equal("123456789".match(/(?:x?\dx?){2,10}/)[0], "123456789")
- assert_equal("123456789".match(/(?:x?\dx?){2,}/)[0], "123456789")
- end
-
- def test_encoding_flags_are_preserved_when_initialized_with_another_regexp
- re = Regexp.new("\u2018hello\u2019".encode("UTF-8"))
- str = "".encode("US-ASCII")
-
- assert_nothing_raised do
- str.match?(re)
- str.match?(Regexp.new(re))
- end
- end
-
- def test_bug_19537 # [Bug #19537]
- str = 'aac'
- re = '^([ab]{1,3})(a?)*$'
- 100.times do
- assert !Regexp.new(re).match?(str)
- end
- end
-
- def test_bug_20083 # [Bug #20083]
- re = /([\s]*ABC)$/i
- (1..100).each do |n|
- text = "#{"0" * n}ABC"
- assert text.match?(re)
- end
- end
-
- def test_bug_20098 # [Bug #20098]
- assert /a((.|.)|bc){,4}z/.match? 'abcbcbcbcz'
- assert /a(b+?c*){4,5}z/.match? 'abbbccbbbccbcbcz'
- assert /a(b+?(.|.)){2,3}z/.match? 'abbbcbbbcbbbcz'
- assert /a(b*?(.|.)[bc]){2,5}z/.match? 'abcbbbcbcccbcz'
- assert /^(?:.+){2,4}?b|b/.match? "aaaabaa"
- end
-
- def test_bug_20207 # [Bug #20207]
- assert(!'clan'.match?(/(?=.*a)(?!.*n)/))
- end
-
- def test_bug_20212 # [Bug #20212]
- regex = Regexp.new(
- /\A((?=.*?[a-z])(?!.*--)[a-z\d]+[a-z\d-]*[a-z\d]+).((?=.*?[a-z])(?!.*--)[a-z\d]+[a-z\d-]*[a-z\d]+).((?=.*?[a-z])(?!.*--)[a-zd]+[a-zd-]*[a-zd]+).((?=.*?[a-z])(?!.*--)[a-zd]+[a-zd-]*[a-zd]+)\Z/x
- )
- string = "www.google.com"
- 100.times.each { assert(regex.match?(string)) }
- end
-
- def test_bug_20246 # [Bug #20246]
- assert_equal '1.2.3', '1.2.3'[/(\d+)(\.\g<1>){2}/]
- assert_equal '1.2.3', '1.2.3'[/((?:\d|foo|bar)+)(\.\g<1>){2}/]
- end
-
- def test_linear_time_p
- assert_send [Regexp, :linear_time?, /a/]
- assert_send [Regexp, :linear_time?, 'a']
- assert_send [Regexp, :linear_time?, 'a', Regexp::IGNORECASE]
- assert_not_send [Regexp, :linear_time?, /(a)\1/]
- assert_not_send [Regexp, :linear_time?, "(a)\\1"]
-
- assert_not_send [Regexp, :linear_time?, /(?=(a))/]
- assert_not_send [Regexp, :linear_time?, /(?!(a))/]
-
- assert_raise(TypeError) {Regexp.linear_time?(nil)}
- assert_raise(TypeError) {Regexp.linear_time?(Regexp.allocate)}
- end
-
- def test_linear_performance
- pre = ->(n) {[Regexp.new("a?" * n + "a" * n), "a" * n]}
- assert_linear_performance([10, 29], pre: pre) do |re, s|
- re =~ s
- end
- end
end
diff --git a/test/ruby/test_require.rb b/test/ruby/test_require.rb
index fd5092aaf0..a71fe0932e 100644
--- a/test/ruby/test_require.rb
+++ b/test/ruby/test_require.rb
@@ -110,7 +110,7 @@ class TestRequire < Test::Unit::TestCase
begin
require_path = File.join(tmp, dir, 'foo.rb').encode(encoding)
rescue
- omit "cannot convert path encoding to #{encoding}"
+ skip "cannot convert path encoding to #{encoding}"
end
Dir.mkdir(File.dirname(require_path))
open(require_path, "wb") {|f| f.puts '$:.push __FILE__'}
@@ -192,7 +192,7 @@ class TestRequire < Test::Unit::TestCase
t.close
path = File.expand_path(t.path).sub(/\A(\w):/, '//127.0.0.1/\1$')
- omit "local drive #$1: is not shared" unless File.exist?(path)
+ skip "local drive #$1: is not shared" unless File.exist?(path)
args = ['--disable-gems', "-I#{File.dirname(path)}"]
assert_in_out_err(args, "#{<<~"END;"}", [path], [])
begin
@@ -209,7 +209,7 @@ class TestRequire < Test::Unit::TestCase
File.write(req, "p :ok\n")
assert_file.exist?(req)
req[/.rb$/i] = ""
- assert_in_out_err([], <<-INPUT, %w(:ok), [])
+ assert_in_out_err(['--disable-gems'], <<-INPUT, %w(:ok), [])
require "#{req}"
require "#{req}"
INPUT
@@ -227,7 +227,6 @@ class TestRequire < Test::Unit::TestCase
assert_not_nil(bt = e.backtrace, "no backtrace")
assert_not_empty(bt.find_all {|b| b.start_with? __FILE__}, proc {bt.inspect})
end
- ensure
$LOADED_FEATURES.replace loaded_features
end
@@ -478,7 +477,7 @@ class TestRequire < Test::Unit::TestCase
result = IO.popen([EnvUtil.rubybin, "b/tst.rb"], &:read)
assert_equal("a/lib.rb\n", result, "[ruby-dev:40040]")
rescue NotImplementedError, Errno::EACCES
- omit "File.symlink is not implemented"
+ skip "File.symlink is not implemented"
end
}
}
@@ -504,7 +503,7 @@ class TestRequire < Test::Unit::TestCase
result = IO.popen([EnvUtil.rubybin, "c.rb"], &:read)
assert_equal("1", result, "bug17885 [ruby-core:104010]")
rescue NotImplementedError, Errno::EACCES
- omit "File.symlink is not implemented"
+ skip "File.symlink is not implemented"
end
}
}
@@ -697,7 +696,7 @@ class TestRequire < Test::Unit::TestCase
Dir.mktmpdir {|tmp|
Dir.chdir(tmp) {
open("foo.rb", "w") {}
- assert_in_out_err([{"RUBYOPT"=>nil}], "#{<<~"begin;"}\n#{<<~"end;"}", %w(:ok), [], bug7158)
+ assert_in_out_err([{"RUBYOPT"=>nil}, '--disable-gems'], "#{<<~"begin;"}\n#{<<~"end;"}", %w(:ok), [], bug7158)
begin;
$:.replace([IO::NULL])
a = Object.new
@@ -725,7 +724,7 @@ class TestRequire < Test::Unit::TestCase
Dir.mktmpdir {|tmp|
Dir.chdir(tmp) {
open("foo.rb", "w") {}
- assert_in_out_err([{"RUBYOPT"=>nil}], "#{<<~"begin;"}\n#{<<~"end;"}", %w(:ok), [], bug7158)
+ assert_in_out_err([{"RUBYOPT"=>nil}, '--disable-gems'], "#{<<~"begin;"}\n#{<<~"end;"}", %w(:ok), [], bug7158)
begin;
$:.replace([IO::NULL])
a = Object.new
@@ -755,7 +754,7 @@ class TestRequire < Test::Unit::TestCase
open("foo.rb", "w") {}
Dir.mkdir("a")
open(File.join("a", "bar.rb"), "w") {}
- assert_in_out_err([], "#{<<~"begin;"}\n#{<<~"end;"}", %w(:ok), [], bug7383)
+ assert_in_out_err(['--disable-gems'], "#{<<~"begin;"}\n#{<<~"end;"}", %w(:ok), [], bug7383)
begin;
$:.replace([IO::NULL])
$:.#{add} "#{tmp}"
@@ -839,8 +838,6 @@ class TestRequire < Test::Unit::TestCase
end if File.respond_to?(:mkfifo)
def test_loading_fifo_threading_success
- omit "[Bug #18613]" if /freebsd/=~ RUBY_PLATFORM
-
Tempfile.create(%w'fifo .rb') {|f|
f.close
File.unlink(f.path)
@@ -867,7 +864,7 @@ class TestRequire < Test::Unit::TestCase
end if File.respond_to?(:mkfifo)
def test_loading_fifo_fd_leak
- omit if RUBY_PLATFORM =~ /android/ # https://rubyci.org/logs/rubyci.s3.amazonaws.com/android29-x86_64/ruby-master/log/20200419T124100Z.fail.html.gz
+ skip if RUBY_PLATFORM =~ /android/ # https://rubyci.org/logs/rubyci.s3.amazonaws.com/android29-x86_64/ruby-master/log/20200419T124100Z.fail.html.gz
Tempfile.create(%w'fifo .rb') {|f|
f.close
@@ -928,7 +925,7 @@ class TestRequire < Test::Unit::TestCase
begin
File.symlink "real", File.join(tmp, "symlink")
rescue NotImplementedError, Errno::EACCES
- omit "File.symlink is not implemented"
+ 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)
@@ -976,19 +973,4 @@ class TestRequire < Test::Unit::TestCase
assert_nil($LOAD_PATH.resolve_feature_path("superkalifragilisticoespialidoso"))
end
end
-
- def test_require_with_public_method_missing
- # [Bug #19793]
- assert_separately(["-W0", "-rtempfile"], __FILE__, __LINE__, <<~RUBY)
- GC.stress = true
-
- class Object
- public :method_missing
- end
-
- Tempfile.create(["empty", ".rb"]) do |file|
- require file.path
- end
- RUBY
- end
end
diff --git a/test/ruby/test_require_lib.rb b/test/ruby/test_require_lib.rb
index a88279727e..6b2846c8fd 100644
--- a/test/ruby/test_require_lib.rb
+++ b/test/ruby/test_require_lib.rb
@@ -1,26 +1,25 @@
-# frozen_string_literal: true
+# frozen_string_literal: false
require 'test/unit'
class TestRequireLib < Test::Unit::TestCase
- libdir = __dir__ + '/../../lib'
+ TEST_RATIO = ENV["TEST_REQUIRE_THREAD_RATIO"]&.tap {|s|break s.to_f} || 0.05 # testing all files needs too long time...
- # .rb files at lib
- scripts = Dir.glob('*.rb', base: libdir).map {|f| f.chomp('.rb')}
-
- # .rb files in subdirectories of lib without same name script
- dirs = Dir.glob('*/', base: libdir).map {|d| d.chomp('/')}
- dirs -= scripts
- scripts.concat(Dir.glob(dirs.map {|d| d + '/*.rb'}, base: libdir).map {|f| f.chomp('.rb')})
-
- # skip some problems
- scripts -= %w[bundler bundled_gems rubygems mkmf]
-
- scripts.each do |lib|
+ 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
+ next if %r!/lib/irb/ext/tracer\.rb\z! =~ 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(['-W0'], "#{<<~"begin;"}\n#{<<~"end;"}")
+ assert_separately(['--disable-gems', '-W0'], "#{<<~"begin;"}\n#{<<~"end;"}")
begin;
n = Thread.list.size
- require #{lib.dump}
+ begin
+ require #{lib.dump}
+ rescue Exception
+ skip $!
+ end
assert_equal n, Thread.list.size
end;
end
diff --git a/test/ruby/test_rubyoptions.rb b/test/ruby/test_rubyoptions.rb
index 38ca119a8f..aae2522fc6 100644
--- a/test/ruby/test_rubyoptions.rb
+++ b/test/ruby/test_rubyoptions.rb
@@ -7,14 +7,13 @@ require 'tempfile'
require_relative '../lib/jit_support'
class TestRubyOptions < Test::Unit::TestCase
- def self.rjit_enabled? = defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled?
def self.yjit_enabled? = defined?(RubyVM::YJIT.enabled?) && RubyVM::YJIT.enabled?
NO_JIT_DESCRIPTION =
- if rjit_enabled?
- RUBY_DESCRIPTION.sub(/\+RJIT /, '')
- elsif yjit_enabled?
- RUBY_DESCRIPTION.sub(/\+YJIT( (dev|dev_nodebug|stats))? /, '')
+ if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # checking -DMJIT_FORCE_ENABLE
+ RUBY_DESCRIPTION.sub(/\+MJIT /, '')
+ elsif yjit_enabled? # checking -DYJIT_FORCE_ENABLE
+ RUBY_DESCRIPTION.sub(/\+YJIT /, '')
else
RUBY_DESCRIPTION
end
@@ -74,7 +73,7 @@ class TestRubyOptions < Test::Unit::TestCase
def test_backtrace_limit
assert_in_out_err(%w(--backtrace-limit), "", [], /missing argument for --backtrace-limit/)
assert_in_out_err(%w(--backtrace-limit= 1), "", [], /missing argument for --backtrace-limit/)
- assert_in_out_err(%w(--backtrace-limit=-2), "", [], /wrong limit for backtrace length/)
+ assert_in_out_err(%w(--backtrace-limit=-1), "", [], /wrong limit for backtrace length/)
code = 'def f(n);n > 0 ? f(n-1) : raise;end;f(5)'
assert_in_out_err(%w(--backtrace-limit=1), code, [],
[/.*unhandled exception\n/, /^\tfrom .*\n/,
@@ -84,22 +83,11 @@ class TestRubyOptions < Test::Unit::TestCase
/^\t \.{3} \d+ levels\.{3}\n/])
assert_kind_of(Integer, Thread::Backtrace.limit)
assert_in_out_err(%w(--backtrace-limit=1), "p Thread::Backtrace.limit", ['1'], [])
- assert_in_out_err(%w(--backtrace-limit 1), "p Thread::Backtrace.limit", ['1'], [])
- env = {"RUBYOPT" => "--backtrace-limit=5"}
- assert_in_out_err([env], "p Thread::Backtrace.limit", ['5'], [])
- assert_in_out_err([env, "--backtrace-limit=1"], "p Thread::Backtrace.limit", ['1'], [])
- assert_in_out_err([env, "--backtrace-limit=-1"], "p Thread::Backtrace.limit", ['-1'], [])
- assert_in_out_err([env, "--backtrace-limit=3", "--backtrace-limit=1"],
- "p Thread::Backtrace.limit", ['1'], [])
- assert_in_out_err([{"RUBYOPT" => "--backtrace-limit=5 --backtrace-limit=3"}],
- "p Thread::Backtrace.limit", ['3'], [])
- long_max = RbConfig::LIMITS["LONG_MAX"]
- assert_in_out_err(%W(--backtrace-limit=#{long_max}), "p Thread::Backtrace.limit",
- ["#{long_max}"], [])
end
def test_warning
- save_rubyopt = ENV.delete('RUBYOPT')
+ save_rubyopt = ENV['RUBYOPT']
+ ENV['RUBYOPT'] = nil
assert_in_out_err(%w(-W0 -e) + ['p $-W'], "", %w(0), [])
assert_in_out_err(%w(-W1 -e) + ['p $-W'], "", %w(1), [])
assert_in_out_err(%w(-Wx -e) + ['p $-W'], "", %w(2), [])
@@ -110,36 +98,29 @@ class TestRubyOptions < Test::Unit::TestCase
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 -e) + ['p Warning[:performance]'], "", %w(false), [])
- assert_in_out_err(%w(-W:performance -e) + ['p Warning[:performance]'], "", %w(true), [])
assert_in_out_err(%w(-W:qux), "", [], /unknown warning category: `qux'/)
assert_in_out_err(%w(-w -e) + ['p Warning[:deprecated]'], "", %w(true), [])
assert_in_out_err(%w(-W -e) + ['p Warning[:deprecated]'], "", %w(true), [])
assert_in_out_err(%w(-We) + ['p Warning[:deprecated]'], "", %w(true), [])
assert_in_out_err(%w(-e) + ['p Warning[:deprecated]'], "", %w(false), [])
- assert_in_out_err(%w(-w -e) + ['p Warning[:performance]'], "", %w(false), [])
- assert_in_out_err(%w(-W -e) + ['p Warning[:performance]'], "", %w(false), [])
- code = 'puts "#{$VERBOSE}:#{Warning[:deprecated]}:#{Warning[:experimental]}:#{Warning[:performance]}"'
+ 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:false:true:false), [])
- assert_in_out_err(["-r#{t.path}", '-w', '-e', code], "", %w(true:true:true:false true:true:true:false), [])
- assert_in_out_err(["-r#{t.path}", '-W:deprecated', '-e', code], "", %w(false:true:true:false false:true:true:false), [])
- assert_in_out_err(["-r#{t.path}", '-W:no-experimental', '-e', code], "", %w(false:false:false:false false:false:false:false), [])
- assert_in_out_err(["-r#{t.path}", '-W:performance', '-e', code], "", %w(false:false:true:true false:false:true:true), [])
+ 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_debug
- assert_in_out_err(["-de", "p $DEBUG"], "", %w(true), [])
+ assert_in_out_err(["--disable-gems", "-de", "p $DEBUG"], "", %w(true), [])
- assert_in_out_err(["--debug", "-e", "p $DEBUG"],
+ assert_in_out_err(["--disable-gems", "--debug", "-e", "p $DEBUG"],
"", %w(true), [])
-
- assert_in_out_err(["--debug-", "-e", "p $DEBUG"], "", %w(), /invalid option --debug-/)
end
q = Regexp.method(:quote)
@@ -153,21 +134,21 @@ class TestRubyOptions < Test::Unit::TestCase
end
private_constant :VERSION_PATTERN
- VERSION_PATTERN_WITH_RJIT =
+ VERSION_PATTERN_WITH_JIT =
case RUBY_ENGINE
when 'ruby'
- /^ruby #{q[RUBY_VERSION]}(?:[p ]|dev|rc).*? \+RJIT (\+MN )?\[#{q[RUBY_PLATFORM]}\]$/
+ /^ruby #{q[RUBY_VERSION]}(?:[p ]|dev|rc).*? \+MJIT \[#{q[RUBY_PLATFORM]}\]$/
else
VERSION_PATTERN
end
- private_constant :VERSION_PATTERN_WITH_RJIT
+ private_constant :VERSION_PATTERN_WITH_JIT
def test_verbose
assert_in_out_err([{'RUBY_YJIT_ENABLE' => nil}, "-vve", ""]) do |r, e|
assert_match(VERSION_PATTERN, r[0])
- if self.class.rjit_enabled? && !JITSupport.rjit_force_enabled?
+ if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? && !mjit_force_enabled? # checking -DMJIT_FORCE_ENABLE
assert_equal(NO_JIT_DESCRIPTION, r[0])
- elsif self.class.yjit_enabled? && !JITSupport.yjit_force_enabled?
+ elsif self.class.yjit_enabled? && !yjit_force_enabled? # checking -DYJIT_FORCE_ENABLE
assert_equal(NO_JIT_DESCRIPTION, r[0])
else
assert_equal(RUBY_DESCRIPTION, r[0])
@@ -188,15 +169,10 @@ class TestRubyOptions < Test::Unit::TestCase
end
def test_enable
- if JITSupport.yjit_supported?
+ 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) + [""], "", [], [])
- elsif JITSupport.rjit_supported?
- # Avoid failing tests by RJIT warnings
- assert_in_out_err(%w(--enable all --disable rjit -e) + [""], "", [], [])
- assert_in_out_err(%w(--enable-all --disable-rjit -e) + [""], "", [], [])
- assert_in_out_err(%w(--enable=all --disable=rjit -e) + [""], "", [], [])
end
assert_in_out_err(%w(--enable foobarbazqux -e) + [""], "", [],
/unknown argument for --enable: `foobarbazqux'/)
@@ -210,9 +186,9 @@ class TestRubyOptions < Test::Unit::TestCase
assert_in_out_err(%w(--disable foobarbazqux -e) + [""], "", [],
/unknown argument for --disable: `foobarbazqux'/)
assert_in_out_err(%w(--disable), "", [], /missing argument for --disable/)
- assert_in_out_err(%w(-e) + ['p defined? Gem'], "", ["nil"], [])
+ 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(-e) + ['p defined? DidYouMean'], "", ["nil"], [])
+ assert_in_out_err(%w(--disable-gems -e) + ['p defined? DidYouMean'], "", ["nil"], [])
end
def test_kanji
@@ -233,29 +209,31 @@ class TestRubyOptions < Test::Unit::TestCase
end
def test_version
- env = { 'RUBY_YJIT_ENABLE' => nil } # unset in children
+ env = {'RUBY_YJIT_ENABLE' => nil} # unset in children
assert_in_out_err([env, '--version']) do |r, e|
assert_match(VERSION_PATTERN, r[0])
if ENV['RUBY_YJIT_ENABLE'] == '1'
assert_equal(NO_JIT_DESCRIPTION, r[0])
- elsif self.class.rjit_enabled? || self.class.yjit_enabled? # checking -D(M|Y)JIT_FORCE_ENABLE
+ elsif defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? || self.class.yjit_enabled? # checking -D(M|Y)JIT_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([], e)
end
- end
- def test_rjit_disabled_version
- return unless JITSupport.rjit_supported?
- return if JITSupport.yjit_force_enabled?
+ return if RbConfig::CONFIG["MJIT_SUPPORT"] == 'no'
+ return if yjit_force_enabled?
- env = { 'RUBY_YJIT_ENABLE' => nil } # unset in children
[
- %w(--version --rjit --disable=rjit),
- %w(--version --enable=rjit --disable=rjit),
- %w(--version --enable-rjit --disable-rjit),
+ %w(--version --mjit --disable=mjit),
+ %w(--version --enable=mjit --disable=mjit),
+ %w(--version --enable-mjit --disable-mjit),
+ *([
+ %w(--version --jit --disable=jit),
+ %w(--version --enable=jit --disable=jit),
+ %w(--version --enable-jit --disable-jit),
+ ] unless RUBY_PLATFORM.start_with?('x86_64-') && RUBY_PLATFORM !~ /mswin|mingw|msys/),
].each do |args|
assert_in_out_err([env] + args) do |r, e|
assert_match(VERSION_PATTERN, r[0])
@@ -263,43 +241,31 @@ class TestRubyOptions < Test::Unit::TestCase
assert_equal([], e)
end
end
- end
-
- def test_rjit_version
- return unless JITSupport.rjit_supported?
- return if JITSupport.yjit_force_enabled?
- env = { 'RUBY_YJIT_ENABLE' => nil } # unset in children
- [
- %w(--version --rjit),
- %w(--version --enable=rjit),
- %w(--version --enable-rjit),
- ].each do |args|
- assert_in_out_err([env] + args) do |r, e|
- assert_match(VERSION_PATTERN_WITH_RJIT, r[0])
- if JITSupport.rjit_force_enabled?
- assert_equal(RUBY_DESCRIPTION, r[0])
- else
- assert_equal(EnvUtil.invoke_ruby([env, '--rjit', '-e', 'print RUBY_DESCRIPTION'], '', true).first, r[0])
+ if JITSupport.supported?
+ [
+ %w(--version --mjit),
+ %w(--version --enable=mjit),
+ %w(--version --enable-mjit),
+ *([
+ %w(--version --jit),
+ %w(--version --enable=jit),
+ %w(--version --enable-jit),
+ ] unless RUBY_PLATFORM.start_with?('x86_64-') && RUBY_PLATFORM !~ /mswin|mingw|msys/),
+ ].each do |args|
+ assert_in_out_err([env] + args) do |r, e|
+ assert_match(VERSION_PATTERN_WITH_JIT, r[0])
+ if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # checking -DMJIT_FORCE_ENABLE
+ assert_equal(RUBY_DESCRIPTION, r[0])
+ else
+ assert_equal(EnvUtil.invoke_ruby([env, '--mjit', '-e', 'print RUBY_DESCRIPTION'], '', true).first, r[0])
+ end
+ assert_equal([], e)
end
- assert_equal([], e)
end
end
end
- def test_parser_flag
- warning = /compiler based on the Prism parser is currently experimental/
-
- assert_in_out_err(%w(--parser=prism -e) + ["puts :hi"], "", %w(hi), warning)
-
- assert_in_out_err(%w(--parser=parse.y -e) + ["puts :hi"], "", %w(hi), [])
- assert_norun_with_rflag('--parser=parse.y', '--version', "")
-
- assert_in_out_err(%w(--parser=notreal -e) + ["puts :hi"], "", [], /unknown parser notreal/)
-
- assert_in_out_err(%w(--parser=prism --version), "", /\+PRISM/, warning)
- end
-
def test_eval
assert_in_out_err(%w(-e), "", [], /no code specified for -e \(RuntimeError\)/)
end
@@ -381,25 +347,7 @@ class TestRubyOptions < Test::Unit::TestCase
end
def test_syntax_check
- assert_in_out_err(%w(-cw -e a=1+1 -e !a), "", ["Syntax OK"], [])
- assert_in_out_err(%w(-cw -e break), "", [], ["-e:1: Invalid break", :*])
- assert_in_out_err(%w(-cw -e next), "", [], ["-e:1: Invalid next", :*])
- assert_in_out_err(%w(-cw -e redo), "", [], ["-e:1: Invalid redo", :*])
- assert_in_out_err(%w(-cw -e retry), "", [], ["-e:1: Invalid retry", :*])
- assert_in_out_err(%w(-cw -e yield), "", [], ["-e:1: Invalid yield", :*])
- assert_in_out_err(%w(-cw -e begin -e break -e end), "", [], ["-e:2: Invalid break", :*])
- assert_in_out_err(%w(-cw -e begin -e next -e end), "", [], ["-e:2: Invalid next", :*])
- assert_in_out_err(%w(-cw -e begin -e redo -e end), "", [], ["-e:2: Invalid redo", :*])
- assert_in_out_err(%w(-cw -e begin -e retry -e end), "", [], ["-e:2: Invalid retry", :*])
- assert_in_out_err(%w(-cw -e begin -e yield -e end), "", [], ["-e:2: Invalid yield", :*])
- assert_in_out_err(%w(-cw -e !defined?(break)), "", ["Syntax OK"], [])
- assert_in_out_err(%w(-cw -e !defined?(next)), "", ["Syntax OK"], [])
- assert_in_out_err(%w(-cw -e !defined?(redo)), "", ["Syntax OK"], [])
- assert_in_out_err(%w(-cw -e !defined?(retry)), "", ["Syntax OK"], [])
- assert_in_out_err(%w(-cw -e !defined?(yield)), "", ["Syntax OK"], [])
- assert_in_out_err(%w(-n -cw -e break), "", ["Syntax OK"], [])
- assert_in_out_err(%w(-n -cw -e next), "", ["Syntax OK"], [])
- assert_in_out_err(%w(-n -cw -e redo), "", ["Syntax OK"], [])
+ assert_in_out_err(%w(-c -e a=1+1 -e !a), "", ["Syntax OK"], [])
end
def test_invalid_option
@@ -407,9 +355,9 @@ class TestRubyOptions < Test::Unit::TestCase
assert_in_out_err(%W(-\r -e) + [""], "", [], [])
- assert_in_out_err(%W(-\rx), "", [], /invalid option -[\r\n] \(-h will show valid options\) \(RuntimeError\)/)
+ assert_in_out_err(%W(-\rx), "", [], /invalid option -\\r \(-h will show valid options\) \(RuntimeError\)/)
- assert_in_out_err(%W(-\x01), "", [], /invalid option -\x01 \(-h will show valid options\) \(RuntimeError\)/)
+ assert_in_out_err(%W(-\x01), "", [], /invalid option -\\x01 \(-h will show valid options\) \(RuntimeError\)/)
assert_in_out_err(%w(-Z), "", [], /invalid option -Z \(-h will show valid options\) \(RuntimeError\)/)
end
@@ -447,11 +395,12 @@ class TestRubyOptions < Test::Unit::TestCase
assert_in_out_err(%w(), "p Warning[:experimental]", ["false"])
ENV['RUBYOPT'] = '-W:qux'
assert_in_out_err(%w(), "", [], /unknown warning category: `qux'/)
-
- ENV['RUBYOPT'] = 'w'
- assert_in_out_err(%w(), "p $VERBOSE", ["true"])
ensure
- ENV['RUBYOPT'] = rubyopt_orig
+ if rubyopt_orig
+ ENV['RUBYOPT'] = rubyopt_orig
+ else
+ ENV.delete('RUBYOPT')
+ end
end
def test_search
@@ -725,7 +674,7 @@ class TestRubyOptions < Test::Unit::TestCase
end
def test_set_program_name
- omit "platform dependent feature" unless defined?(PSCMD) and PSCMD
+ skip "platform dependent feature" unless defined?(PSCMD) and PSCMD
with_tmpchdir do
write_file("test-script", "$0 = 'hello world'; /test-script/ =~ Process.argv0 or $0 = 'Process.argv0 changed!'; sleep 60")
@@ -748,7 +697,7 @@ class TestRubyOptions < Test::Unit::TestCase
end
def test_setproctitle
- omit "platform dependent feature" unless defined?(PSCMD) and PSCMD
+ skip "platform dependent feature" unless defined?(PSCMD) and PSCMD
assert_separately([], "#{<<-"{#"}\n#{<<-'};'}")
{#
@@ -789,7 +738,7 @@ class TestRubyOptions < Test::Unit::TestCase
-e:(?:1:)?\s\[BUG\]\sSegmentation\sfault.*\n
)x,
%r(
- #{ Regexp.quote((TestRubyOptions.rjit_enabled? && !JITSupport.rjit_force_enabled?) ? NO_JIT_DESCRIPTION : RUBY_DESCRIPTION) }\n\n
+ #{ Regexp.quote(NO_JIT_DESCRIPTION) }\n\n
)x,
%r(
(?:--\s(?:.+\n)*\n)?
@@ -806,9 +755,6 @@ class TestRubyOptions < Test::Unit::TestCase
)?
)x,
%r(
- (?:--\sThreading(?:.+\n)*\n)?
- )x,
- %r(
(?:--\sMachine(?:.+\n)*\n)?
)x,
%r(
@@ -824,32 +770,26 @@ class TestRubyOptions < Test::Unit::TestCase
)?
)x,
]
-
- KILL_SELF = "Process.kill :SEGV, $$"
end
- def assert_segv(args, message=nil, list: SEGVTest::ExpectedStderrList, **opt)
- # We want YJIT to be enabled in the subprocess if it's enabled for us
- # so that the Ruby description matches.
- env = Hash === args.first ? args.shift : {}
- args.unshift("--yjit") if self.class.yjit_enabled?
- env.update({'RUBY_ON_BUG' => nil})
- args.unshift(env)
+ def assert_segv(args, message=nil)
+ skip if ENV['RUBY_ON_BUG']
test_stdin = ""
+ opt = SEGVTest::ExecOptions.dup
+ list = SEGVTest::ExpectedStderrList
- assert_in_out_err(args, test_stdin, //, list, encoding: "ASCII-8BIT",
- **SEGVTest::ExecOptions, **opt)
+ assert_in_out_err(args, test_stdin, //, list, encoding: "ASCII-8BIT", **opt)
end
def test_segv_test
- assert_segv(["--disable-gems", "-e", SEGVTest::KILL_SELF])
+ assert_segv(["--disable-gems", "-e", "Process.kill :SEGV, $$"])
end
def test_segv_loaded_features
bug7402 = '[ruby-core:49573]'
- status = assert_segv(['-e', "END {#{SEGVTest::KILL_SELF}}",
+ status = assert_segv(['-e', 'END {Process.kill :SEGV, $$}',
'-e', 'class Bogus; def to_str; exit true; end; end',
'-e', '$".clear',
'-e', '$".unshift Bogus.new',
@@ -863,70 +803,10 @@ class TestRubyOptions < Test::Unit::TestCase
Tempfile.create(["test_ruby_test_bug7597", ".rb"]) {|t|
t.write "f" * 100
t.flush
- assert_segv(["--disable-gems", "-e", "$0=ARGV[0]; #{SEGVTest::KILL_SELF}", t.path], bug7597)
+ assert_segv(["--disable-gems", "-e", "$0=ARGV[0]; Process.kill :SEGV, $$", t.path], bug7597)
}
end
- def assert_crash_report(path, cmd = nil)
- Dir.mktmpdir("ruby_crash_report") do |dir|
- list = SEGVTest::ExpectedStderrList
- if cmd
- FileUtils.mkpath(File.join(dir, File.dirname(cmd)))
- File.write(File.join(dir, cmd), SEGVTest::KILL_SELF+"\n")
- c = Regexp.quote(cmd)
- list = list.map {|re| Regexp.new(re.source.gsub(/^\s*(\(\?:)?\K-e(?=:)/) {c}, re.options)}
- else
- cmd = ['-e', SEGVTest::KILL_SELF]
- end
- status = assert_segv([{"RUBY_CRASH_REPORT"=>path}, *cmd], list: [], chdir: dir)
- reports = Dir.glob("*.log", File::FNM_DOTMATCH, base: dir)
- assert_equal(1, reports.size)
- assert_pattern_list(list, File.read(File.join(dir, reports.first)))
- break status, reports.first
- end
- end
-
- def test_crash_report
- assert_crash_report("%e.%f.%p.log") do |status, report|
- assert_equal("#{File.basename(EnvUtil.rubybin)}.-e.#{status.pid}.log", report)
- end
- end
-
- def test_crash_report_script
- assert_crash_report("%e.%f.%p.log", "bug.rb") do |status, report|
- assert_equal("#{File.basename(EnvUtil.rubybin)}.bug.rb.#{status.pid}.log", report)
- end
- end
-
- def test_crash_report_executable_path
- omit if EnvUtil.rubybin.size > 245
- assert_crash_report("%E.%p.log") do |status, report|
- assert_equal("#{EnvUtil.rubybin.tr('/', '!')}.#{status.pid}.log", report)
- end
- end
-
- def test_crash_report_script_path
- assert_crash_report("%F.%p.log", "test/bug.rb") do |status, report|
- assert_equal("test!bug.rb.#{status.pid}.log", report)
- end
- end
-
- def test_crash_report_pipe
- if File.executable?(echo = "/bin/echo")
- elsif /mswin|ming/ =~ RUBY_PLATFORM
- echo = "echo"
- else
- omit "/bin/echo not found"
- end
- env = {"RUBY_CRASH_REPORT"=>"| #{echo} %e:%f:%p", "RUBY_ON_BUG"=>nil}
- assert_in_out_err([env], SEGVTest::KILL_SELF,
- encoding: "ASCII-8BIT",
- **SEGVTest::ExecOptions) do |stdout, stderr, status|
- assert_empty(stderr)
- assert_equal(["#{File.basename(EnvUtil.rubybin)}:-:#{status.pid}"], stdout)
- end
- end
-
def test_DATA
Tempfile.create(["test_ruby_test_rubyoption", ".rb"]) {|t|
t.puts "puts DATA.read.inspect"
@@ -978,7 +858,7 @@ class TestRubyOptions < Test::Unit::TestCase
Process.wait pid
}
rescue RuntimeError
- omit $!
+ skip $!
end
}
assert_equal("", result, '[ruby-dev:37798]')
@@ -1028,7 +908,7 @@ class TestRubyOptions < Test::Unit::TestCase
name = c.chr(Encoding::UTF_8)
expected = name.encode("locale") rescue nil
}
- omit "can't make locale name"
+ skip "can't make locale name"
end
name << ".rb"
expected << ".rb"
@@ -1114,7 +994,8 @@ class TestRubyOptions < Test::Unit::TestCase
stderr = []
Tempfile.create(%w"bug10435- .rb") do |script|
dir, base = File.split(script.path)
- File.write(script, "abort ':run'\n")
+ script.puts "abort ':run'"
+ script.close
opts = ['-C', dir, '-r', "./#{base}", *opt]
_, e = assert_in_out_err([*opts, '-ep'], "", //)
stderr.concat(e) if e
@@ -1138,8 +1019,6 @@ class TestRubyOptions < Test::Unit::TestCase
def test_dump_parsetree_with_rflag
assert_norun_with_rflag('--dump=parsetree')
assert_norun_with_rflag('--dump=parsetree', '-e', '#frozen-string-literal: true')
- assert_norun_with_rflag('--dump=parsetree+error_tolerant')
- assert_norun_with_rflag('--dump=parse+error_tolerant')
end
def test_dump_insns_with_rflag
@@ -1237,13 +1116,25 @@ class TestRubyOptions < Test::Unit::TestCase
end
def test_null_script
- omit "#{IO::NULL} is not a character device" unless File.chardev?(IO::NULL)
+ skip "#{IO::NULL} is not a character device" unless File.chardev?(IO::NULL)
assert_in_out_err([IO::NULL], success: true)
end
- def test_free_at_exit_env_var
- env = {"RUBY_FREE_AT_EXIT"=>"1"}
- assert_ruby_status([env, "-e;"])
- assert_in_out_err([env, "-W"], "", [], /Free at exit is experimental and may be unstable/)
+ 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, "--disable-yjit", "--mjit-debug=-O0 -O1", "--mjit-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/)
+ end
+
+ def yjit_force_enabled?
+ "#{RbConfig::CONFIG['CFLAGS']} #{RbConfig::CONFIG['CPPFLAGS']}".match?(/(\A|\s)-D ?YJIT_FORCE_ENABLE\b/)
end
end
diff --git a/test/ruby/test_rubyvm.rb b/test/ruby/test_rubyvm.rb
index d729aa5af8..7d4588a165 100644
--- a/test/ruby/test_rubyvm.rb
+++ b/test/ruby/test_rubyvm.rb
@@ -4,9 +4,11 @@ require 'test/unit'
class TestRubyVM < Test::Unit::TestCase
def test_stat
assert_kind_of Hash, RubyVM.stat
+ assert_kind_of Integer, RubyVM.stat[:global_constant_state]
RubyVM.stat(stat = {})
assert_not_empty stat
+ assert_equal stat[:global_constant_state], RubyVM.stat(:global_constant_state)
end
def test_stat_unknown
@@ -32,8 +34,6 @@ class TestRubyVM < Test::Unit::TestCase
end
def test_keep_script_lines
- pend if ENV['RUBY_ISEQ_DUMP_DEBUG'] # TODO
-
prev_conf = RubyVM.keep_script_lines
# keep
diff --git a/test/ruby/test_rubyvm_jit.rb b/test/ruby/test_rubyvm_jit.rb
new file mode 100644
index 0000000000..a3558d791c
--- /dev/null
+++ b/test/ruby/test_rubyvm_jit.rb
@@ -0,0 +1,91 @@
+# frozen_string_literal: true
+require 'test/unit'
+require_relative '../lib/jit_support'
+
+return if RbConfig::CONFIG["MJIT_SUPPORT"] == 'no'
+
+class TestRubyVMJIT < 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 dbaf0aaf09..73d8aee6a2 100644
--- a/test/ruby/test_settracefunc.rb
+++ b/test/ruby/test_settracefunc.rb
@@ -50,26 +50,6 @@ class TestSetTraceFunc < Test::Unit::TestCase
assert_equal([], events)
end
- def test_c_return_no_binding
- binding = :none
- TracePoint.new(:c_return){|tp|
- binding = tp.binding
- }.enable{
- 1.object_id
- }
- assert_nil(binding)
- end
-
- def test_c_call_no_binding
- binding = :none
- TracePoint.new(:c_call){|tp|
- binding = tp.binding
- }.enable{
- 1.object_id
- }
- assert_nil(binding)
- end
-
def test_c_call_removed_method
# [Bug #19305]
klass = Class.new do
@@ -151,10 +131,6 @@ class TestSetTraceFunc < Test::Unit::TestCase
events.shift)
assert_equal(["line", 4, __method__, self.class],
events.shift)
- assert_equal(["c-call", 4, :const_added, Module],
- events.shift)
- assert_equal(["c-return", 4, :const_added, Module],
- events.shift)
assert_equal(["c-call", 4, :inherited, Class],
events.shift)
assert_equal(["c-return", 4, :inherited, Class],
@@ -358,18 +334,18 @@ class TestSetTraceFunc < Test::Unit::TestCase
def test_thread_trace
events = {:set => [], :add => []}
- name = "#{self.class}\##{__method__}"
prc = Proc.new { |event, file, lineno, mid, binding, klass|
- events[:set] << [event, lineno, mid, klass, :set] if file == name
+ events[:set] << [event, lineno, mid, klass, :set]
}
prc = prc # suppress warning
prc2 = Proc.new { |event, file, lineno, mid, binding, klass|
- events[:add] << [event, lineno, mid, klass, :add] if file == name
+ events[:add] << [event, lineno, mid, klass, :add]
}
prc2 = prc2 # suppress warning
th = Thread.new do
th = Thread.current
+ name = "#{self.class}\##{__method__}"
eval <<-EOF.gsub(/^.*?: /, ""), nil, name
1: th.set_trace_func(prc)
2: th.add_trace_func(prc2)
@@ -392,8 +368,6 @@ class TestSetTraceFunc < Test::Unit::TestCase
[["c-return", 2, :add_trace_func, Thread],
["line", 3, __method__, self.class],
- ["c-call", 3, :const_added, Module],
- ["c-return", 3, :const_added, Module],
["c-call", 3, :inherited, Class],
["c-return", 3, :inherited, Class],
["class", 3, nil, nil],
@@ -502,9 +476,9 @@ class TestSetTraceFunc < Test::Unit::TestCase
begin
eval <<-EOF.gsub(/^.*?: /, ""), nil, 'xyzzy'
1: trace = TracePoint.trace(*trace_events){|tp| next if !target_thread?
- 2: events << [tp.event, tp.lineno, tp.path, _defined_class.(tp), tp.method_id, tp.self, tp.binding&.eval("_local_var"), _get_data.(tp)] if tp.path == 'xyzzy'
+ 2: events << [tp.event, tp.lineno, tp.path, _defined_class.(tp), tp.method_id, tp.self, tp.binding.eval("_local_var"), _get_data.(tp)] if tp.path == 'xyzzy'
3: }
- 4: [1].each{|;_local_var| _local_var = :inner
+ 4: 1.times{|;_local_var| _local_var = :inner
5: tap{}
6: }
7: class XYZZY
@@ -531,29 +505,27 @@ class TestSetTraceFunc < Test::Unit::TestCase
answer_events = [
#
[:line, 4, 'xyzzy', self.class, method, self, :outer, :nothing],
- [:c_call, 4, 'xyzzy', Array, :each, [1], nil, :nothing],
+ [:c_call, 4, 'xyzzy', Integer, :times, 1, :outer, :nothing],
[:line, 4, 'xyzzy', self.class, method, self, nil, :nothing],
[:line, 5, 'xyzzy', self.class, method, self, :inner, :nothing],
- [:c_return, 4, "xyzzy", Array, :each, [1], nil, [1]],
+ [:c_return, 4, "xyzzy", Integer, :times, 1, :outer, 1],
[:line, 7, 'xyzzy', self.class, method, self, :outer, :nothing],
- [:c_call, 7, "xyzzy", Module, :const_added, TestSetTraceFunc, nil, :nothing],
- [:c_return, 7, "xyzzy", Module, :const_added, TestSetTraceFunc, nil, nil],
- [:c_call, 7, "xyzzy", Class, :inherited, Object, nil, :nothing],
- [:c_return, 7, "xyzzy", Class, :inherited, Object, nil, nil],
+ [: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, nil, :nothing],
- [:c_return, 9, "xyzzy", Module, :method_added, xyzzy.class, nil, nil],
+ [: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, nil, :nothing],
- [:c_return,13, "xyzzy", Module, :method_added, xyzzy.class, nil, nil],
+ [: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, nil, :nothing],
- [:c_call, 18, "xyzzy", BasicObject, :initialize, xyzzy, nil, :nothing],
- [:c_return,18, "xyzzy", BasicObject, :initialize, xyzzy, nil, nil],
- [:c_return,18, "xyzzy", Class, :new, xyzzy.class, nil, xyzzy],
+ [: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],
@@ -564,17 +536,17 @@ class TestSetTraceFunc < Test::Unit::TestCase
[: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, nil, :nothing],
- [:c_call, 20, "xyzzy", Exception, :exception, RuntimeError, nil, :nothing],
- [:c_call, 20, "xyzzy", Exception, :initialize, raised_exc, nil, :nothing],
- [:c_return,20, "xyzzy", Exception, :initialize, raised_exc, nil, raised_exc],
- [:c_return,20, "xyzzy", Exception, :exception, RuntimeError, nil, raised_exc],
- [:c_return,20, "xyzzy", Kernel, :raise, self, nil, nil],
- [:c_call, 20, "xyzzy", Exception, :backtrace, raised_exc, nil, :nothing],
- [:c_return,20, "xyzzy", Exception, :backtrace, raised_exc, nil, nil],
+ [: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, nil, :nothing],
- [:c_return,20, "xyzzy", Module, :===, RuntimeError, nil, true],
+ [:c_call, 20, "xyzzy", Module, :===, RuntimeError,:outer, :nothing],
+ [:c_return,20, "xyzzy", Module, :===, RuntimeError,:outer, true],
[:line, 21, "xyzzy", TestSetTraceFunc, method, self, :outer, :nothing],
]
@@ -625,19 +597,6 @@ PREP
CODE
end
- def test_tracepoint_bmethod_memory_leak
- assert_no_memory_leak([], '', "#{<<~"begin;"}\n#{<<~'end;'}", "[Bug #20194]", rss: true)
- obj = Object.new
- obj.define_singleton_method(:foo) {}
- bmethod = obj.method(:foo)
- tp = TracePoint.new(:return) {}
- begin;
- 1_000_000.times do
- tp.enable(target: bmethod) {}
- end
- end;
- end
-
def trace_by_set_trace_func
events = []
trace = nil
@@ -650,9 +609,9 @@ CODE
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'
+ 2: events << [event, line, file, klass, id, binding.eval('self'), binding.eval("_local_var")] if file == 'xyzzy'
3: })
- 4: [1].map{|;_local_var| _local_var = :inner
+ 4: 1.times{|;_local_var| _local_var = :inner
5: tap{}
6: }
7: class XYZZY
@@ -675,31 +634,29 @@ CODE
answer_events = [
#
- [:c_return, 1, "xyzzy", TracePoint, :trace, TracePoint, nil, nil],
+ [: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, nil, nil],
+ [:c_call, 4, 'xyzzy', Integer, :times, 1, :outer, :nothing],
[:line, 4, 'xyzzy', self.class, method, self, nil, :nothing],
[:line, 5, 'xyzzy', self.class, method, self, :inner, :nothing],
- [:c_return, 4, "xyzzy", Integer, :times, 1, nil, nil],
+ [: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, nil, nil],
- [:c_return, 7, "xyzzy", Class, :inherited, Object, nil, nil],
- [:c_call, 7, "xyzzy", Class, :const_added, Object, nil, nil],
- [:c_return, 7, "xyzzy", Class, :const_added, Object, nil, nil],
+ [: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, nil, nil],
- [:c_return, 9, "xyzzy", Module, :method_added, xyzzy.class, nil, nil],
+ [: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, nil, nil],
- [:c_return,13, "xyzzy", Module, :method_added, xyzzy.class, nil, nil],
+ [: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, nil, nil],
- [:c_call, 18, "xyzzy", BasicObject, :initialize, xyzzy, nil, nil],
- [:c_return,18, "xyzzy", BasicObject, :initialize, xyzzy, nil, nil],
- [:c_return,18, "xyzzy", Class, :new, xyzzy.class, nil, nil],
+ [: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],
@@ -710,29 +667,23 @@ CODE
[: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, nil, nil],
- [:c_call, 20, "xyzzy", Exception, :exception, RuntimeError, nil, nil],
- [:c_call, 20, "xyzzy", Exception, :initialize, raised_exc, nil, nil],
- [:c_return,20, "xyzzy", Exception, :initialize, raised_exc, nil, nil],
- [:c_return,20, "xyzzy", Exception, :exception, RuntimeError, nil, nil],
- [:c_return,20, "xyzzy", Kernel, :raise, self, nil, nil],
- [:c_call, 20, "xyzzy", Exception, :backtrace, raised_exc, nil, nil],
- [:c_return,20, "xyzzy", Exception, :backtrace, raised_exc, nil, nil],
+ [: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, nil, nil],
- [:c_return,20, "xyzzy", Module, :===, RuntimeError, nil, nil],
+ [: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, nil, nil],
+ [:c_call, 21, "xyzzy", TracePoint, :disable, trace, :outer, :nothing],
]
return events, answer_events
end
- def test_set_trace_func_curry_argument_error
- b = lambda {|x, y, z| (x||0) + (y||0) + (z||0) }.curry[1, 2]
- set_trace_func(proc {})
- assert_raise(ArgumentError) {b[3, 4]}
- end
-
def test_set_trace_func
actual_events, expected_events = trace_by_set_trace_func
expected_events.zip(actual_events){|e, a|
@@ -789,30 +740,25 @@ CODE
def test_tracepoint_enable
ary = []
args = nil
- begin
- trace = TracePoint.new(:call){|tp|
- next if !target_thread?
- ary << tp.method_id
- }
- foo
- trace.enable(target_thread: nil){|*a|
- args = a
- foo
- }
+ trace = TracePoint.new(:call){|tp|
+ next if !target_thread?
+ ary << tp.method_id
+ }
+ foo
+ trace.enable{|*a|
+ args = a
foo
- assert_equal([:foo], ary)
- assert_equal([], args)
- ensure
- trace&.disable
- end
+ }
+ foo
+ assert_equal([:foo], ary)
+ assert_equal([], args)
trace = TracePoint.new{}
begin
assert_equal(false, trace.enable)
assert_equal(true, trace.enable)
- trace.enable(target_thread: nil){}
- trace.disable
- assert_equal(false, trace.enable)
+ trace.enable{}
+ assert_equal(true, trace.enable)
ensure
trace.disable
end
@@ -968,55 +914,6 @@ CODE
assert_equal(expected*2, events)
end
- def test_tracepoint_struct
- c = Struct.new(:x) do
- alias y x
- alias y= x=
- end
- obj = c.new
-
- ar_meth = obj.method(:x)
- aw_meth = obj.method(:x=)
- aar_meth = obj.method(:y)
- aaw_meth = obj.method(:y=)
- events = []
- trace = TracePoint.new(:c_call, :c_return){|tp|
- next if !target_thread?
- next if tp.path != __FILE__
- next if tp.method_id == :call
- case tp.event
- when :c_call
- assert_raise(RuntimeError) {tp.return_value}
- events << [tp.event, tp.method_id, tp.callee_id]
- when :c_return
- events << [tp.event, tp.method_id, tp.callee_id, tp.return_value]
- end
- }
- test_proc = proc do
- obj.x = 1
- obj.x
- obj.y = 2
- obj.y
- aw_meth.call(1)
- ar_meth.call
- aaw_meth.call(2)
- aar_meth.call
- end
- test_proc.call # populate call caches
- trace.enable(&test_proc)
- expected = [
- [:c_call, :x=, :x=],
- [:c_return, :x=, :x=, 1],
- [:c_call, :x, :x],
- [:c_return, :x, :x, 1],
- [:c_call, :x=, :y=],
- [:c_return, :x=, :y=, 2],
- [:c_call, :x, :y],
- [:c_return, :x, :y, 2],
- ]
- assert_equal(expected*2, events)
- end
-
class XYZZYException < Exception; end
def method_test_tracepoint_raised_exception err
raise err
@@ -1056,7 +953,7 @@ CODE
/return/ =~ tp.event ? tp.return_value : nil
]
}.enable{
- [1].map{
+ 1.times{
3
}
method_for_test_tracepoint_block{
@@ -1066,10 +963,10 @@ CODE
# pp events
# expected_events =
[[:b_call, :test_tracepoint_block, TestSetTraceFunc, TestSetTraceFunc, nil],
- [:c_call, :map, Array, Array, nil],
+ [:c_call, :times, Integer, Integer, nil],
[:b_call, :test_tracepoint_block, TestSetTraceFunc, TestSetTraceFunc, nil],
[:b_return, :test_tracepoint_block, TestSetTraceFunc, TestSetTraceFunc, 3],
- [:c_return, :map, Array, Array, [3]],
+ [:c_return, :times, Integer, Integer, 1],
[:call, :method_for_test_tracepoint_block, TestSetTraceFunc, TestSetTraceFunc, nil],
[:b_call, :test_tracepoint_block, TestSetTraceFunc, TestSetTraceFunc, nil],
[:b_return, :test_tracepoint_block, TestSetTraceFunc, TestSetTraceFunc, 4],
@@ -1093,7 +990,7 @@ CODE
tp.defined_class, #=> nil,
tp.self.class # tp.self return creating/ending thread
]
- }.enable(target_thread: nil){
+ }.enable{
created_thread = Thread.new{thread_self = self}
created_thread.join
}
@@ -1372,7 +1269,7 @@ CODE
next if !target_thread?
events << tp.event
}.enable{
- [1].map{
+ 1.times{
3
}
method_for_test_tracepoint_block{
@@ -1394,7 +1291,7 @@ CODE
next if !target_thread?
events << tp.event
}.enable{
- [1].map{
+ 1.times{
3
}
method_for_test_tracepoint_block{
@@ -1753,7 +1650,7 @@ CODE
Bug10724.new
}
- assert_equal([:call, :call, :return, :return], evs)
+ assert_equal([:call, :return], evs)
end
require 'fiber'
@@ -1985,11 +1882,7 @@ CODE
def tp_return_value mid
ary = []
- TracePoint.new(:return, :b_return){|tp|
- next if !target_thread?
- next if tp.path != __FILE__
- ary << [tp.event, tp.method_id, tp.return_value]
- }.enable{
+ TracePoint.new(:return, :b_return){|tp| next if !target_thread?; ary << [tp.event, tp.method_id, tp.return_value]}.enable{
send mid
}
ary.pop # last b_return event is not required.
@@ -2198,7 +2091,7 @@ CODE
q = Thread::Queue.new
t = Thread.new{
Thread.current.add_trace_func proc{|ev, file, line, *args|
- events << [ev, line] if file == __FILE__
+ events << [ev, line]
} # do not stop trace. They will be stopped at Thread termination.
q.push 1
_x = 1
@@ -2234,9 +2127,9 @@ CODE
}
# it is dirty hack. usually we shouldn't use such technique
Thread.pass until t.status == 'sleep'
- # When RJIT thread exists, t.status becomes 'sleep' even if it does not reach m2t_q.pop.
+ # When MJIT thread exists, t.status becomes 'sleep' even if it does not reach m2t_q.pop.
# This sleep forces it to reach m2t_q.pop for --jit-wait.
- sleep 1 if defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled?
+ sleep 1 if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?
t.add_trace_func proc{|ev, file, line, *args|
if file == __FILE__
@@ -2249,16 +2142,17 @@ CODE
m2t_q.push 1
t.join
- assert_equal ["line", base_line + 32], events[0]
- assert_equal ["line", base_line + 33], events[1]
- assert_equal ["call", base_line + -6], events[2]
- assert_equal ["return", base_line + -4], events[3]
- assert_equal ["line", base_line + 34], events[4]
- assert_equal ["line", base_line + 35], events[5]
- assert_equal ["c-call", base_line + 35], events[6] # Thread.current
- assert_equal ["c-return", base_line + 35], events[7] # Thread.current
- assert_equal ["c-call", base_line + 35], events[8] # Thread#set_trace_func
- assert_equal nil, events[9]
+ assert_equal ["c-return", base_line + 31], events[0]
+ assert_equal ["line", base_line + 32], events[1]
+ assert_equal ["line", base_line + 33], events[2]
+ assert_equal ["call", base_line + -6], events[3]
+ assert_equal ["return", base_line + -4], events[4]
+ assert_equal ["line", base_line + 34], events[5]
+ assert_equal ["line", base_line + 35], events[6]
+ assert_equal ["c-call", base_line + 35], events[7] # Thread.current
+ assert_equal ["c-return", base_line + 35], events[8] # Thread.current
+ 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
@@ -2358,7 +2252,7 @@ CODE
# global TP and targeted TP
ex = assert_raise(ArgumentError) do
tp = TracePoint.new(:line){}
- tp.enable(target_thread: nil){
+ tp.enable{
tp.enable(target: code2){}
}
end
@@ -2472,40 +2366,6 @@ CODE
assert_equal [:tp1, 1, 2, :tp2, 3], events
end
- def test_multiple_enable
- ary = []
- trace = TracePoint.new(:call) do |tp|
- ary << tp.method_id
- end
- trace.enable
- trace.enable
- foo
- trace.disable
- assert_equal(1, ary.count(:foo), '[Bug #19114]')
- end
-
- def test_multiple_tracepoints_same_bmethod
- events = []
- tp1 = TracePoint.new(:return) do |tp|
- events << :tp1
- end
- tp2 = TracePoint.new(:return) do |tp|
- events << :tp2
- end
-
- obj = Object.new
- obj.define_singleton_method(:foo) {}
- bmethod = obj.method(:foo)
-
- tp1.enable(target: bmethod) do
- tp2.enable(target: bmethod) do
- obj.foo
- end
- end
-
- assert_equal([:tp2, :tp1], events, '[Bug #18031]')
- end
-
def test_script_compiled
events = []
tp = TracePoint.new(:script_compiled){|tp|
@@ -2534,7 +2394,7 @@ CODE
}
assert_equal [], events, 'script_compiled event should not be invoked on compile error'
- omit "TODO: test for requires"
+ skip "TODO: test for requires"
events.clear
tp.enable{
@@ -2703,20 +2563,6 @@ CODE
end
bar
EOS
-
- assert_normal_exit(<<-EOS, 'Bug #18730')
- def bar
- 42
- end
- tp_line = TracePoint.new(:line) do |tp0|
- tp_multi1 = TracePoint.new(:return, :b_return, :line) do |tp|
- tp0.disable
- end
- tp_multi1.enable
- end
- tp_line.enable(target: method(:bar))
- bar
- EOS
end
def test_stat_exists
@@ -2776,102 +2622,4 @@ CODE
TracePoint.allow_reentry{}
end
end
-
- def test_raising_from_b_return_tp_tracing_bmethod
- assert_normal_exit(<<~RUBY, '[Bug #18060]', timeout: 3)
- class Foo
- define_singleton_method(:foo) { return } # a bmethod
- end
-
- TracePoint.trace(:b_return) do |tp|
- raise
- end
-
- Foo.foo
- RUBY
-
- # Same thing but with a target
- assert_normal_exit(<<~RUBY, '[Bug #18060]', timeout: 3)
- class Foo
- define_singleton_method(:foo) { return } # a bmethod
- end
-
- TracePoint.new(:b_return) do |tp|
- raise
- end.enable(target: Foo.method(:foo))
-
- Foo.foo
- RUBY
- end
-
- def helper_cant_rescue
- begin
- raise SyntaxError
- rescue
- cant_rescue
- end
- end
-
- def test_tp_rescue
- lines = []
- TracePoint.new(:line){|tp|
- next unless target_thread?
- lines << tp.lineno
- }.enable{
- begin
- helper_cant_rescue
- rescue SyntaxError
- end
- }
- _call_line = lines.shift
- _raise_line = lines.shift
- assert_equal [], lines
- end
-
- def helper_can_rescue
- begin
- raise __LINE__.to_s
- rescue SyntaxError
- :ng
- rescue
- :ok
- end
- end
-
- def helper_can_rescue_empty_body
- begin
- raise __LINE__.to_s
- rescue SyntaxError
- :ng
- rescue
- end
- end
-
- def test_tp_rescue_event
- lines = []
- TracePoint.new(:rescue){|tp|
- next unless target_thread?
- lines << [tp.lineno, tp.raised_exception]
- }.enable{
- helper_can_rescue
- }
-
- line, err, = lines.pop
- assert_equal [], lines
- assert err.kind_of?(RuntimeError)
- assert_equal err.message.to_i + 4, line
-
- lines = []
- TracePoint.new(:rescue){|tp|
- next unless target_thread?
- lines << [tp.lineno, tp.raised_exception]
- }.enable{
- helper_can_rescue_empty_body
- }
-
- line, err, = lines.pop
- assert_equal [], lines
- assert err.kind_of?(RuntimeError)
- assert_equal err.message.to_i + 3, line
- end
end
diff --git a/test/ruby/test_shapes.rb b/test/ruby/test_shapes.rb
deleted file mode 100644
index ee99fbad6d..0000000000
--- a/test/ruby/test_shapes.rb
+++ /dev/null
@@ -1,1041 +0,0 @@
-# frozen_string_literal: false
-require 'test/unit'
-require 'objspace'
-require 'json'
-
-# These test the functionality of object shapes
-class TestShapes < Test::Unit::TestCase
- MANY_IVS = 80
-
- class IVOrder
- def expected_ivs
- %w{ @a @b @c @d @e @f @g @h @i @j @k }
- end
-
- def set_ivs
- expected_ivs.each { instance_variable_set(_1, 1) }
- self
- end
- end
-
- class ShapeOrder
- def initialize
- @b = :b # 5 => 6
- end
-
- def set_b
- @b = :b # 5 => 6
- end
-
- def set_c
- @c = :c # 5 => 7
- end
- end
-
- class OrderedAlloc
- def add_ivars
- 10.times do |i|
- instance_variable_set("@foo" + i.to_s, 0)
- end
- end
- end
-
- class Example
- def initialize
- @a = 1
- end
- end
-
- class RemoveAndAdd
- def add_foo
- @foo = 1
- end
-
- def remove_foo
- remove_instance_variable(:@foo)
- end
-
- def add_bar
- @bar = 1
- end
- end
-
- class TooComplex
- attr_reader :hopefully_unique_name, :b
-
- def initialize
- @hopefully_unique_name = "a"
- @b = "b"
- end
-
- # Make enough lazily defined accessors to allow us to force
- # polymorphism
- class_eval (RubyVM::Shape::SHAPE_MAX_VARIATIONS + 1).times.map {
- "def a#{_1}_m; @a#{_1} ||= #{_1}; end"
- }.join(" ; ")
-
- class_eval "attr_accessor " + (RubyVM::Shape::SHAPE_MAX_VARIATIONS + 1).times.map {
- ":a#{_1}"
- }.join(", ")
-
- def iv_not_defined; @not_defined; end
-
- def write_iv_method
- self.a3 = 12345
- end
-
- def write_iv
- @a3 = 12345
- end
- end
-
- # RubyVM::Shape.of returns new instances of shape objects for
- # each call. This helper method allows us to define equality for
- # shapes
- def assert_shape_equal(shape1, shape2)
- assert_equal(shape1.id, shape2.id)
- assert_equal(shape1.parent_id, shape2.parent_id)
- assert_equal(shape1.depth, shape2.depth)
- assert_equal(shape1.type, shape2.type)
- end
-
- def refute_shape_equal(shape1, shape2)
- refute_equal(shape1.id, shape2.id)
- end
-
- def test_iv_order_correct_on_complex_objects
- (RubyVM::Shape::SHAPE_MAX_VARIATIONS + 1).times {
- IVOrder.new.instance_variable_set("@a#{_1}", 1)
- }
-
- obj = IVOrder.new
- iv_list = obj.set_ivs.instance_variables
- assert_equal obj.expected_ivs, iv_list.map(&:to_s)
- end
-
- def test_too_complex
- ensure_complex
-
- tc = TooComplex.new
- tc.send("a#{RubyVM::Shape::SHAPE_MAX_VARIATIONS}_m")
- assert_predicate RubyVM::Shape.of(tc), :too_complex?
- end
-
- def test_ordered_alloc_is_not_complex
- 5.times { OrderedAlloc.new.add_ivars }
- obj = JSON.parse(ObjectSpace.dump(OrderedAlloc))
- assert_operator obj["variation_count"], :<, RubyVM::Shape::SHAPE_MAX_VARIATIONS
- end
-
- def test_too_many_ivs_on_obj
- assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- class Hi; end
-
- RubyVM::Shape.exhaust_shapes(2)
-
- obj = Hi.new
- obj.instance_variable_set(:@b, 1)
- obj.instance_variable_set(:@c, 1)
- obj.instance_variable_set(:@d, 1)
-
- assert_predicate RubyVM::Shape.of(obj), :too_complex?
- end;
- end
-
- def test_too_many_ivs_on_class
- obj = Class.new
-
- (MANY_IVS + 1).times do
- obj.instance_variable_set(:"@a#{_1}", 1)
- end
-
- assert_false RubyVM::Shape.of(obj).too_complex?
- end
-
- def test_removing_when_too_many_ivs_on_class
- obj = Class.new
-
- (MANY_IVS + 2).times do
- obj.instance_variable_set(:"@a#{_1}", 1)
- end
- (MANY_IVS + 2).times do
- obj.remove_instance_variable(:"@a#{_1}")
- end
-
- assert_empty obj.instance_variables
- end
-
- def test_removing_when_too_many_ivs_on_module
- obj = Module.new
-
- (MANY_IVS + 2).times do
- obj.instance_variable_set(:"@a#{_1}", 1)
- end
- (MANY_IVS + 2).times do
- obj.remove_instance_variable(:"@a#{_1}")
- end
-
- assert_empty obj.instance_variables
- end
-
- def test_too_complex_geniv
- assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- class TooComplex < Hash
- attr_reader :very_unique
- end
-
- RubyVM::Shape.exhaust_shapes
-
- (RubyVM::Shape::SHAPE_MAX_VARIATIONS * 2).times do
- TooComplex.new.instance_variable_set(:"@unique_#{_1}", 1)
- end
-
- tc = TooComplex.new
- tc.instance_variable_set(:@very_unique, 3)
- tc.instance_variable_set(:@very_unique2, 4)
- assert_equal 3, tc.instance_variable_get(:@very_unique)
- assert_equal 4, tc.instance_variable_get(:@very_unique2)
-
- assert_equal [:@very_unique, :@very_unique2], tc.instance_variables
- end;
- end
-
- def test_use_all_shapes_then_freeze
- assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- class Hi; end
- RubyVM::Shape.exhaust_shapes(3)
-
- obj = Hi.new
- i = 0
- while RubyVM::Shape.shapes_available > 0
- obj.instance_variable_set(:"@b#{i}", 1)
- i += 1
- end
- obj.freeze
-
- assert obj.frozen?
- end;
- end
-
- def test_run_out_of_shape_for_object
- assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- class A
- def initialize
- @a = 1
- end
- end
- RubyVM::Shape.exhaust_shapes
-
- A.new
- end;
- end
-
- def test_run_out_of_shape_for_class_ivar
- assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- RubyVM::Shape.exhaust_shapes
-
- c = Class.new
- c.instance_variable_set(:@a, 1)
- assert_equal(1, c.instance_variable_get(:@a))
-
- c.remove_instance_variable(:@a)
- assert_nil(c.instance_variable_get(:@a))
-
- assert_raise(NameError) do
- c.remove_instance_variable(:@a)
- end
- end;
- end
-
- def test_evacuate_class_ivar_and_compaction
- assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- count = 20
-
- c = Class.new
- count.times do |ivar|
- c.instance_variable_set("@i#{ivar}", "ivar-#{ivar}")
- end
-
- RubyVM::Shape.exhaust_shapes
-
- GC.auto_compact = true
- GC.stress = true
- # Cause evacuation
- c.instance_variable_set(:@a, o = Object.new)
- assert_equal(o, c.instance_variable_get(:@a))
- GC.stress = false
-
- count.times do |ivar|
- assert_equal "ivar-#{ivar}", c.instance_variable_get("@i#{ivar}")
- end
- end;
- end
-
- def test_evacuate_generic_ivar_and_compaction
- assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- count = 20
-
- c = Hash.new
- count.times do |ivar|
- c.instance_variable_set("@i#{ivar}", "ivar-#{ivar}")
- end
-
- RubyVM::Shape.exhaust_shapes
-
- GC.auto_compact = true
- GC.stress = true
-
- # Cause evacuation
- c.instance_variable_set(:@a, o = Object.new)
- assert_equal(o, c.instance_variable_get(:@a))
-
- GC.stress = false
-
- count.times do |ivar|
- assert_equal "ivar-#{ivar}", c.instance_variable_get("@i#{ivar}")
- end
- end;
- end
-
- def test_evacuate_object_ivar_and_compaction
- assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- count = 20
-
- c = Object.new
- count.times do |ivar|
- c.instance_variable_set("@i#{ivar}", "ivar-#{ivar}")
- end
-
- RubyVM::Shape.exhaust_shapes
-
- GC.auto_compact = true
- GC.stress = true
-
- # Cause evacuation
- c.instance_variable_set(:@a, o = Object.new)
- assert_equal(o, c.instance_variable_get(:@a))
-
- GC.stress = false
-
- count.times do |ivar|
- assert_equal "ivar-#{ivar}", c.instance_variable_get("@i#{ivar}")
- end
- end;
- end
-
- def test_gc_stress_during_evacuate_generic_ivar
- assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- [].instance_variable_set(:@a, 1)
-
- RubyVM::Shape.exhaust_shapes
-
- ary = 10.times.map { [] }
-
- GC.stress = true
- ary.each do |o|
- o.instance_variable_set(:@a, 1)
- o.instance_variable_set(:@b, 1)
- end
- end;
- end
-
- def test_run_out_of_shape_for_module_ivar
- assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- RubyVM::Shape.exhaust_shapes
-
- module Foo
- @a = 1
- @b = 2
- assert_equal 1, @a
- assert_equal 2, @b
- end
- end;
- end
-
- def test_run_out_of_shape_for_class_cvar
- assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- RubyVM::Shape.exhaust_shapes
-
- c = Class.new
-
- c.class_variable_set(:@@a, 1)
- assert_equal(1, c.class_variable_get(:@@a))
-
- c.class_eval { remove_class_variable(:@@a) }
- assert_false(c.class_variable_defined?(:@@a))
-
- assert_raise(NameError) do
- c.class_eval { remove_class_variable(:@@a) }
- end
- end;
- end
-
- def test_run_out_of_shape_generic_instance_variable_set
- assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- class TooComplex < Hash
- end
-
- RubyVM::Shape.exhaust_shapes
-
- tc = TooComplex.new
- tc.instance_variable_set(:@a, 1)
- tc.instance_variable_set(:@b, 2)
-
- tc.remove_instance_variable(:@a)
- assert_nil(tc.instance_variable_get(:@a))
-
- assert_raise(NameError) do
- tc.remove_instance_variable(:@a)
- end
- end;
- end
-
- def test_run_out_of_shape_generic_ivar_set
- assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- class Hi < String
- def initialize
- 8.times do |i|
- instance_variable_set("@ivar_#{i}", i)
- end
- end
-
- def transition
- @hi_transition ||= 1
- end
- end
-
- a = Hi.new
-
- # Try to run out of shapes
- RubyVM::Shape.exhaust_shapes
-
- assert_equal 1, a.transition
- assert_equal 1, a.transition
- end;
- end
-
- def test_run_out_of_shape_instance_variable_defined
- assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- class A
- attr_reader :a, :b, :c, :d
- def initialize
- @a = @b = @c = @d = 1
- end
- end
-
- RubyVM::Shape.exhaust_shapes
-
- a = A.new
- assert_equal true, a.instance_variable_defined?(:@a)
- end;
- end
-
- def test_run_out_of_shape_instance_variable_defined_on_module
- assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- RubyVM::Shape.exhaust_shapes
-
- module A
- @a = @b = @c = @d = 1
- end
-
- assert_equal true, A.instance_variable_defined?(:@a)
- end;
- end
-
- def test_run_out_of_shape_during_remove_instance_variable
- assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- o = Object.new
- 10.times { |i| o.instance_variable_set(:"@a#{i}", i) }
-
- RubyVM::Shape.exhaust_shapes
-
- o.remove_instance_variable(:@a0)
- (1...10).each do |i|
- assert_equal(i, o.instance_variable_get(:"@a#{i}"))
- end
- end;
- end
-
- def test_run_out_of_shape_remove_instance_variable
- assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- class A
- attr_reader :a, :b, :c, :d
- def initialize
- @a = @b = @c = @d = 1
- end
- end
-
- a = A.new
-
- RubyVM::Shape.exhaust_shapes
-
- a.remove_instance_variable(:@b)
- assert_nil a.b
-
- a.remove_instance_variable(:@a)
- assert_nil a.a
-
- a.remove_instance_variable(:@c)
- assert_nil a.c
-
- assert_equal 1, a.d
- end;
- end
-
- def test_run_out_of_shape_rb_obj_copy_ivar
- assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- class A
- def initialize
- init # Avoid right sizing
- end
-
- def init
- @a = @b = @c = @d = @e = @f = 1
- end
- end
-
- a = A.new
-
- RubyVM::Shape.exhaust_shapes
-
- a.dup
- end;
- end
-
- def test_evacuate_generic_ivar_memory_leak
- assert_no_memory_leak([], "#{<<~'begin;'}", "#{<<~'end;'}", rss: true)
- o = []
- o.instance_variable_set(:@a, 1)
-
- RubyVM::Shape.exhaust_shapes
-
- ary = 1_000_000.times.map { [] }
- begin;
- ary.each do |o|
- o.instance_variable_set(:@a, 1)
- o.instance_variable_set(:@b, 1)
- end
- ary.clear
- ary = nil
- GC.start
- end;
- end
-
- def test_use_all_shapes_module
- assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- class Hi; end
-
- RubyVM::Shape.exhaust_shapes(2)
-
- obj = Module.new
- 3.times do
- obj.instance_variable_set(:"@a#{_1}", _1)
- end
-
- ivs = 3.times.map do
- obj.instance_variable_get(:"@a#{_1}")
- end
-
- assert_equal [0, 1, 2], ivs
- end;
- end
-
- def test_complex_freeze_after_clone
- assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- class Hi; end
-
- RubyVM::Shape.exhaust_shapes(2)
-
- obj = Object.new
- i = 0
- while RubyVM::Shape.shapes_available > 0
- obj.instance_variable_set(:"@b#{i}", i)
- i += 1
- end
-
- v = obj.clone(freeze: true)
- assert_predicate v, :frozen?
- assert_equal 0, v.instance_variable_get(:@b0)
- end;
- end
-
- def test_too_complex_ractor
- assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- $VERBOSE = nil
- class TooComplex
- attr_reader :very_unique
- end
-
- RubyVM::Shape::SHAPE_MAX_VARIATIONS.times do
- TooComplex.new.instance_variable_set(:"@unique_#{_1}", Object.new)
- end
-
- tc = TooComplex.new
- tc.instance_variable_set(:"@very_unique", 3)
-
- assert_predicate RubyVM::Shape.of(tc), :too_complex?
- assert_equal 3, tc.very_unique
- assert_equal 3, Ractor.new(tc) { |x| Ractor.yield(x.very_unique) }.take
- assert_equal tc.instance_variables.sort, Ractor.new(tc) { |x| Ractor.yield(x.instance_variables) }.take.sort
- end;
- end
-
- def test_too_complex_ractor_shareable
- assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- $VERBOSE = nil
- class TooComplex
- attr_reader :very_unique
- end
-
- RubyVM::Shape::SHAPE_MAX_VARIATIONS.times do
- TooComplex.new.instance_variable_set(:"@unique_#{_1}", Object.new)
- end
-
- tc = TooComplex.new
- tc.instance_variable_set(:"@very_unique", 3)
-
- assert_predicate RubyVM::Shape.of(tc), :too_complex?
- assert_equal 3, tc.very_unique
- assert_equal 3, Ractor.make_shareable(tc).very_unique
- end;
- end
-
- def test_too_complex_obj_ivar_ractor_share
- assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- $VERBOSE = nil
-
- RubyVM::Shape.exhaust_shapes
-
- r = Ractor.new do
- o = Object.new
- o.instance_variable_set(:@a, "hello")
- Ractor.yield(o)
- end
-
- o = r.take
- assert_equal "hello", o.instance_variable_get(:@a)
- end;
- end
-
- def test_too_complex_generic_ivar_ractor_share
- assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- $VERBOSE = nil
-
- RubyVM::Shape.exhaust_shapes
-
- r = Ractor.new do
- o = []
- o.instance_variable_set(:@a, "hello")
- Ractor.yield(o)
- end
-
- o = r.take
- assert_equal "hello", o.instance_variable_get(:@a)
- end;
- end
-
- def test_read_iv_after_complex
- ensure_complex
-
- tc = TooComplex.new
- tc.send("a#{RubyVM::Shape::SHAPE_MAX_VARIATIONS}_m")
- assert_predicate RubyVM::Shape.of(tc), :too_complex?
- assert_equal 3, tc.a3_m
- end
-
- def test_read_method_after_complex
- ensure_complex
-
- tc = TooComplex.new
- tc.send("a#{RubyVM::Shape::SHAPE_MAX_VARIATIONS}_m")
- assert_predicate RubyVM::Shape.of(tc), :too_complex?
- assert_equal 3, tc.a3_m
- assert_equal 3, tc.a3
- end
-
- def test_write_method_after_complex
- ensure_complex
-
- tc = TooComplex.new
- tc.send("a#{RubyVM::Shape::SHAPE_MAX_VARIATIONS}_m")
- assert_predicate RubyVM::Shape.of(tc), :too_complex?
- tc.write_iv_method
- tc.write_iv_method
- assert_equal 12345, tc.a3_m
- assert_equal 12345, tc.a3
- end
-
- def test_write_iv_after_complex
- ensure_complex
-
- tc = TooComplex.new
- tc.send("a#{RubyVM::Shape::SHAPE_MAX_VARIATIONS}_m")
- assert_predicate RubyVM::Shape.of(tc), :too_complex?
- tc.write_iv
- tc.write_iv
- assert_equal 12345, tc.a3_m
- assert_equal 12345, tc.a3
- end
-
- def test_iv_read_via_method_after_complex
- ensure_complex
-
- tc = TooComplex.new
- tc.send("a#{RubyVM::Shape::SHAPE_MAX_VARIATIONS}_m")
- assert_predicate RubyVM::Shape.of(tc), :too_complex?
- assert_equal 3, tc.a3_m
- assert_equal 3, tc.instance_variable_get(:@a3)
- end
-
- def test_delete_iv_after_complex
- ensure_complex
-
- tc = TooComplex.new
- tc.send("a#{RubyVM::Shape::SHAPE_MAX_VARIATIONS}_m")
- assert_predicate RubyVM::Shape.of(tc), :too_complex?
-
- assert_equal 3, tc.a3_m # make sure IV is initialized
- assert tc.instance_variable_defined?(:@a3)
- tc.remove_instance_variable(:@a3)
- assert_nil tc.a3
- end
-
- def test_delete_undefined_after_complex
- ensure_complex
-
- tc = TooComplex.new
- tc.send("a#{RubyVM::Shape::SHAPE_MAX_VARIATIONS}_m")
- assert_predicate RubyVM::Shape.of(tc), :too_complex?
-
- refute tc.instance_variable_defined?(:@a3)
- assert_raise(NameError) do
- tc.remove_instance_variable(:@a3)
- end
- assert_nil tc.a3
- end
-
- def test_remove_instance_variable
- ivars_count = 5
- object = Object.new
- ivars_count.times do |i|
- object.instance_variable_set("@ivar_#{i}", i)
- end
-
- ivars = ivars_count.times.map do |i|
- object.instance_variable_get("@ivar_#{i}")
- end
- assert_equal [0, 1, 2, 3, 4], ivars
-
- object.remove_instance_variable(:@ivar_2)
-
- ivars = ivars_count.times.map do |i|
- object.instance_variable_get("@ivar_#{i}")
- end
- assert_equal [0, 1, nil, 3, 4], ivars
- end
-
- def test_remove_instance_variable_when_out_of_shapes
- assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- ivars_count = 5
- object = Object.new
- ivars_count.times do |i|
- object.instance_variable_set("@ivar_#{i}", i)
- end
-
- ivars = ivars_count.times.map do |i|
- object.instance_variable_get("@ivar_#{i}")
- end
- assert_equal [0, 1, 2, 3, 4], ivars
-
- RubyVM::Shape.exhaust_shapes
-
- object.remove_instance_variable(:@ivar_2)
-
- ivars = ivars_count.times.map do |i|
- object.instance_variable_get("@ivar_#{i}")
- end
- assert_equal [0, 1, nil, 3, 4], ivars
- end;
- end
-
- def test_remove_instance_variable_capacity_transition
- assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- t_object_shape = RubyVM::Shape.find_by_id(GC::INTERNAL_CONSTANTS[:SIZE_POOL_COUNT])
- assert_equal(RubyVM::Shape::SHAPE_T_OBJECT, t_object_shape.type)
-
- initial_capacity = t_object_shape.capacity
-
- # a does not transition in capacity
- a = Class.new.new
- initial_capacity.times do |i|
- a.instance_variable_set(:"@ivar#{i + 1}", i)
- end
-
- # b transitions in capacity
- b = Class.new.new
- (initial_capacity + 1).times do |i|
- b.instance_variable_set(:"@ivar#{i}", i)
- end
-
- assert_operator(RubyVM::Shape.of(a).capacity, :<, RubyVM::Shape.of(b).capacity)
-
- # b will now have the same tree as a
- b.remove_instance_variable(:@ivar0)
-
- a.instance_variable_set(:@foo, 1)
- a.instance_variable_set(:@bar, 1)
-
- # Check that there is no heap corruption
- GC.verify_internal_consistency
- end;
- end
-
- def test_freeze_after_complex
- ensure_complex
-
- tc = TooComplex.new
- tc.send("a#{RubyVM::Shape::SHAPE_MAX_VARIATIONS}_m")
- assert_predicate RubyVM::Shape.of(tc), :too_complex?
- tc.freeze
- assert_raise(FrozenError) { tc.a3_m }
- # doesn't transition to frozen shape in this case
- assert_predicate RubyVM::Shape.of(tc), :too_complex?
- end
-
- def test_read_undefined_iv_after_complex
- ensure_complex
-
- tc = TooComplex.new
- tc.send("a#{RubyVM::Shape::SHAPE_MAX_VARIATIONS}_m")
- assert_predicate RubyVM::Shape.of(tc), :too_complex?
- assert_equal nil, tc.iv_not_defined
- assert_predicate RubyVM::Shape.of(tc), :too_complex?
- end
-
- def test_shape_order
- bar = ShapeOrder.new # 0 => 1
- bar.set_c # 1 => 2
- bar.set_b # 2 => 2
-
- foo = ShapeOrder.new # 0 => 1
- shape_id = RubyVM::Shape.of(foo).id
- foo.set_b # should not transition
- assert_equal shape_id, RubyVM::Shape.of(foo).id
- end
-
- def test_iv_index
- example = RemoveAndAdd.new
- initial_shape = RubyVM::Shape.of(example)
- assert_equal 0, initial_shape.next_iv_index
-
- example.add_foo # makes a transition
- add_foo_shape = RubyVM::Shape.of(example)
- assert_equal([:@foo], example.instance_variables)
- assert_equal(initial_shape.id, add_foo_shape.parent.id)
- assert_equal(1, add_foo_shape.next_iv_index)
-
- example.remove_foo # makes a transition
- remove_foo_shape = RubyVM::Shape.of(example)
- assert_equal([], example.instance_variables)
- assert_shape_equal(initial_shape, remove_foo_shape)
-
- example.add_bar # makes a transition
- bar_shape = RubyVM::Shape.of(example)
- assert_equal([:@bar], example.instance_variables)
- assert_equal(initial_shape.id, bar_shape.parent_id)
- assert_equal(1, bar_shape.next_iv_index)
- end
-
- def test_remove_then_add_again
- example = RemoveAndAdd.new
- _initial_shape = RubyVM::Shape.of(example)
-
- example.add_foo # makes a transition
- add_foo_shape = RubyVM::Shape.of(example)
- example.remove_foo # makes a transition
- example.add_foo # makes a transition
- assert_shape_equal(add_foo_shape, RubyVM::Shape.of(example))
- end
-
- class TestObject; end
-
- def test_new_obj_has_t_object_shape
- obj = TestObject.new
- shape = RubyVM::Shape.of(obj)
- assert_equal RubyVM::Shape::SHAPE_T_OBJECT, shape.type
- assert_shape_equal(RubyVM::Shape.root_shape, shape.parent)
- end
-
- def test_str_has_root_shape
- assert_shape_equal(RubyVM::Shape.root_shape, RubyVM::Shape.of(""))
- end
-
- def test_array_has_root_shape
- assert_shape_equal(RubyVM::Shape.root_shape, RubyVM::Shape.of([]))
- end
-
- def test_true_has_special_const_shape_id
- assert_equal(RubyVM::Shape::SPECIAL_CONST_SHAPE_ID, RubyVM::Shape.of(true).id)
- end
-
- def test_nil_has_special_const_shape_id
- assert_equal(RubyVM::Shape::SPECIAL_CONST_SHAPE_ID, RubyVM::Shape.of(nil).id)
- end
-
- def test_root_shape_transition_to_special_const_on_frozen
- assert_equal(RubyVM::Shape::SPECIAL_CONST_SHAPE_ID, RubyVM::Shape.of([].freeze).id)
- end
-
- def test_basic_shape_transition
- omit "Failing with RJIT for some reason" if defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled?
- obj = Example.new
- shape = RubyVM::Shape.of(obj)
- refute_equal(RubyVM::Shape.root_shape, shape)
- assert_equal :@a, shape.edge_name
- assert_equal RubyVM::Shape::SHAPE_IVAR, shape.type
-
- shape = shape.parent
- assert_equal RubyVM::Shape::SHAPE_T_OBJECT, shape.type
-
- shape = shape.parent
- assert_equal(RubyVM::Shape.root_shape.id, shape.id)
- assert_equal(1, obj.instance_variable_get(:@a))
- end
-
- def test_different_objects_make_same_transition
- obj = []
- obj2 = ""
- obj.instance_variable_set(:@a, 1)
- obj2.instance_variable_set(:@a, 1)
- assert_shape_equal(RubyVM::Shape.of(obj), RubyVM::Shape.of(obj2))
- end
-
- def test_duplicating_objects
- obj = Example.new
- obj2 = obj.dup
- assert_shape_equal(RubyVM::Shape.of(obj), RubyVM::Shape.of(obj2))
- end
-
- def test_duplicating_too_complex_objects_memory_leak
- assert_no_memory_leak([], "#{<<~'begin;'}", "#{<<~'end;'}", "[Bug #20162]", rss: true)
- RubyVM::Shape.exhaust_shapes
-
- o = Object.new
- o.instance_variable_set(:@a, 0)
- begin;
- 1_000_000.times do
- o.dup
- end
- end;
- end
-
- def test_freezing_and_duplicating_object
- obj = Object.new.freeze
- obj2 = obj.dup
- refute_predicate(obj2, :frozen?)
- # dup'd objects shouldn't be frozen, and the shape should be the
- # parent shape of the copied object
- assert_equal(RubyVM::Shape.of(obj).parent.id, RubyVM::Shape.of(obj2).id)
- end
-
- def test_freezing_and_duplicating_object_with_ivars
- obj = Example.new.freeze
- obj2 = obj.dup
- refute_predicate(obj2, :frozen?)
- refute_shape_equal(RubyVM::Shape.of(obj), RubyVM::Shape.of(obj2))
- assert_equal(obj2.instance_variable_get(:@a), 1)
- end
-
- def test_freezing_and_duplicating_string_with_ivars
- str = "str"
- str.instance_variable_set(:@a, 1)
- str.freeze
- str2 = str.dup
- refute_predicate(str2, :frozen?)
- refute_equal(RubyVM::Shape.of(str).id, RubyVM::Shape.of(str2).id)
- assert_equal(str2.instance_variable_get(:@a), 1)
- end
-
- def test_freezing_and_cloning_objects
- obj = Object.new.freeze
- obj2 = obj.clone(freeze: true)
- assert_predicate(obj2, :frozen?)
- assert_shape_equal(RubyVM::Shape.of(obj), RubyVM::Shape.of(obj2))
- end
-
- def test_cloning_with_freeze_option
- obj = Object.new
- obj2 = obj.clone(freeze: true)
- assert_predicate(obj2, :frozen?)
- refute_shape_equal(RubyVM::Shape.of(obj), RubyVM::Shape.of(obj2))
- assert_equal(RubyVM::Shape::SHAPE_FROZEN, RubyVM::Shape.of(obj2).type)
- assert_shape_equal(RubyVM::Shape.of(obj), RubyVM::Shape.of(obj2).parent)
- end
-
- def test_freezing_and_cloning_object_with_ivars
- obj = Example.new.freeze
- obj2 = obj.clone(freeze: true)
- assert_predicate(obj2, :frozen?)
- assert_shape_equal(RubyVM::Shape.of(obj), RubyVM::Shape.of(obj2))
- assert_equal(obj2.instance_variable_get(:@a), 1)
- end
-
- def test_freezing_and_cloning_string
- str = "str".freeze
- str2 = str.clone(freeze: true)
- assert_predicate(str2, :frozen?)
- assert_shape_equal(RubyVM::Shape.of(str), RubyVM::Shape.of(str2))
- end
-
- def test_freezing_and_cloning_string_with_ivars
- str = "str"
- str.instance_variable_set(:@a, 1)
- str.freeze
- str2 = str.clone(freeze: true)
- assert_predicate(str2, :frozen?)
- assert_shape_equal(RubyVM::Shape.of(str), RubyVM::Shape.of(str2))
- assert_equal(str2.instance_variable_get(:@a), 1)
- end
-
- def test_out_of_bounds_shape
- assert_raise ArgumentError do
- RubyVM::Shape.find_by_id(RubyVM.stat[:next_shape_id])
- end
- assert_raise ArgumentError do
- RubyVM::Shape.find_by_id(-1)
- end
- end
-
- def ensure_complex
- RubyVM::Shape::SHAPE_MAX_VARIATIONS.times do
- tc = TooComplex.new
- tc.send("a#{_1}_m")
- end
- end
-end if defined?(RubyVM::Shape)
diff --git a/test/ruby/test_signal.rb b/test/ruby/test_signal.rb
index 7877a35129..a62537d59d 100644
--- a/test/ruby/test_signal.rb
+++ b/test/ruby/test_signal.rb
@@ -291,8 +291,7 @@ class TestSignal < Test::Unit::TestCase
if trap = Signal.list['TRAP']
bug9820 = '[ruby-dev:48592] [Bug #9820]'
- no_core = "Process.setrlimit(Process::RLIMIT_CORE, 0); " if defined?(Process.setrlimit) && defined?(Process::RLIMIT_CORE)
- status = assert_in_out_err(['-e', "#{no_core}Process.kill(:TRAP, $$)"])
+ status = assert_in_out_err(['-e', 'Process.kill(:TRAP, $$)'])
assert_predicate(status, :signaled?, bug9820)
assert_equal(trap, status.termsig, bug9820)
end
@@ -323,6 +322,49 @@ class TestSignal < Test::Unit::TestCase
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)
diff --git a/test/ruby/test_sprintf.rb b/test/ruby/test_sprintf.rb
index c453ecd350..f2e73eb58d 100644
--- a/test/ruby/test_sprintf.rb
+++ b/test/ruby/test_sprintf.rb
@@ -362,16 +362,11 @@ class TestSprintf < Test::Unit::TestCase
def test_char
assert_equal("a", sprintf("%c", 97))
assert_equal("a", sprintf("%c", ?a))
- assert_equal("a", sprintf("%c", "a"))
- assert_equal("a", sprintf("%c", sprintf("%c%c", ?a, ?a)))
+ assert_raise(ArgumentError) { sprintf("%c", sprintf("%c%c", ?a, ?a)) }
assert_equal(" " * (BSIZ - 1) + "a", sprintf(" " * (BSIZ - 1) + "%c", ?a))
assert_equal(" " * (BSIZ - 1) + "a", sprintf(" " * (BSIZ - 1) + "%-1c", ?a))
assert_equal(" " * BSIZ + "a", sprintf("%#{ BSIZ + 1 }c", ?a))
assert_equal("a" + " " * BSIZ, sprintf("%-#{ BSIZ + 1 }c", ?a))
- assert_raise(ArgumentError) { sprintf("%c", -1) }
- s = sprintf("%c".encode(Encoding::US_ASCII), 0x80)
- assert_equal("\x80".b, s)
- assert_predicate(s, :valid_encoding?)
end
def test_string
@@ -512,16 +507,6 @@ class TestSprintf < Test::Unit::TestCase
end
end
- def test_coderange
- format_str = "wrong constant name %s"
- interpolated_str = "\u3042"
- assert_predicate format_str, :ascii_only?
- refute_predicate interpolated_str, :ascii_only?
-
- str = format_str % interpolated_str
- refute_predicate str, :ascii_only?
- end
-
def test_named_default
h = Hash.new('world')
assert_equal("hello world", "hello %{location}" % h)
diff --git a/test/ruby/test_stack.rb b/test/ruby/test_stack.rb
index 8a78848322..763aeb6bc2 100644
--- a/test/ruby/test_stack.rb
+++ b/test/ruby/test_stack.rb
@@ -18,6 +18,7 @@ class TestStack < 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
+ env['ASAN_OPTIONS'] = ENV['ASAN_OPTIONS'] if ENV['ASAN_OPTIONS']
stdout, stderr, status = EnvUtil.invoke_ruby([env, '-e', script], '', true, true, timeout: 30)
assert(!status.signaled?, FailDesc[status, nil, stderr])
diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb
index 42f2544b5a..6c00aa15f9 100644
--- a/test/ruby/test_string.rb
+++ b/test/ruby/test_string.rb
@@ -83,7 +83,7 @@ class TestString < Test::Unit::TestCase
end
def test_initialize_shared
- S(str = "mystring" * 10).__send__(:initialize, capacity: str.bytesize)
+ String.new(str = "mystring" * 10).__send__(:initialize, capacity: str.bytesize)
assert_equal("mystring", str[0, 8])
end
@@ -97,10 +97,8 @@ class TestString < Test::Unit::TestCase
end
def test_initialize_memory_leak
- return unless @cls == String
-
assert_no_memory_leak([], <<-PREP, <<-CODE, rss: true)
-code = proc {('x'*100_000).__send__(:initialize, '')}
+code = proc {('x'*100000).__send__(:initialize, '')}
1_000.times(&code)
PREP
100_000.times(&code)
@@ -109,10 +107,8 @@ CODE
# Bug #18154
def test_initialize_nofree_memory_leak
- return unless @cls == String
-
assert_no_memory_leak([], <<-PREP, <<-CODE, rss: true)
-code = proc {0.to_s.__send__(:initialize, capacity: 100_000)}
+code = proc {0.to_s.__send__(:initialize, capacity: 10000)}
1_000.times(&code)
PREP
100_000.times(&code)
@@ -244,23 +240,23 @@ CODE
assert_equal(-1, S("ABCDEF") <=> S("abcdef"))
- assert_nil(S("foo") <=> Object.new)
+ assert_nil("foo" <=> Object.new)
o = Object.new
def o.to_str; "bar"; end
- assert_equal(1, S("foo") <=> o)
+ assert_equal(1, "foo" <=> o)
class << o;remove_method :to_str;end
def o.<=>(x); nil; end
- assert_nil(S("foo") <=> o)
+ assert_nil("foo" <=> o)
class << o;remove_method :<=>;end
def o.<=>(x); 1; end
- assert_equal(-1, S("foo") <=> o)
+ assert_equal(-1, "foo" <=> o)
class << o;remove_method :<=>;end
def o.<=>(x); 2**100; end
- assert_equal(-1, S("foo") <=> o)
+ assert_equal(-1, "foo" <=> o)
end
def test_EQUAL # '=='
@@ -274,10 +270,10 @@ CODE
o = Object.new
def o.to_str; end
def o.==(x); false; end
- assert_equal(false, S("foo") == o)
+ assert_equal(false, "foo" == o)
class << o;remove_method :==;end
def o.==(x); true; end
- assert_equal(true, S("foo") == o)
+ assert_equal(true, "foo" == o)
end
def test_LSHIFT # '<<'
@@ -301,9 +297,6 @@ CODE
assert_raise(RangeError, bug) {S("a".force_encoding(Encoding::UTF_8)) << -1}
assert_raise(RangeError, bug) {S("a".force_encoding(Encoding::UTF_8)) << 0x81308130}
assert_nothing_raised {S("a".force_encoding(Encoding::GB18030)) << 0x81308130}
-
- s = "\x95".force_encoding(Encoding::SJIS).tap(&:valid_encoding?)
- assert_predicate(s << 0x5c, :valid_encoding?)
end
def test_MATCH # '=~'
@@ -590,8 +583,6 @@ CODE
assert_equal("foo", s.chomp!("\n"))
s = "foo\r"
assert_equal("foo", s.chomp!("\n"))
-
- assert_raise(ArgumentError) {String.new.chomp!("", "")}
ensure
$/ = save
$VERBOSE = verbose
@@ -657,36 +648,15 @@ CODE
result << 0x0300
expected = S("\u0300".encode(Encoding::UTF_16LE))
assert_equal(expected, result, bug7090)
- assert_raise(TypeError) { S('foo') << :foo }
- assert_raise(FrozenError) { S('foo').freeze.concat('bar') }
+ assert_raise(TypeError) { 'foo' << :foo }
+ assert_raise(FrozenError) { 'foo'.freeze.concat('bar') }
end
def test_concat_literals
- s=S("." * 50)
+ s="." * 50
assert_equal(Encoding::UTF_8, "#{s}x".encoding)
end
- def test_string_interpolations_across_size_pools_get_embedded
- omit if GC::INTERNAL_CONSTANTS[:SIZE_POOL_COUNT] == 1
-
- require 'objspace'
- base_slot_size = GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE]
- small_obj_size = (base_slot_size / 2)
- large_obj_size = base_slot_size * 2
-
- a = "a" * small_obj_size
- b = "a" * large_obj_size
-
- res = "#{a}, #{b}"
- dump_res = ObjectSpace.dump(res)
- dump_orig = ObjectSpace.dump(a)
- new_slot_size = Integer(dump_res.match(/"slot_size":(\d+)/)[1])
- orig_slot_size = Integer(dump_orig.match(/"slot_size":(\d+)/)[1])
-
- assert_match(/"embedded":true/, dump_res)
- assert_operator(new_slot_size, :>, orig_slot_size)
- end
-
def test_count
a = S("hello world")
assert_equal(5, a.count(S("lo")))
@@ -694,18 +664,18 @@ CODE
assert_equal(4, a.count(S("hello"), S("^l")))
assert_equal(4, a.count(S("ej-m")))
assert_equal(0, S("y").count(S("a\\-z")))
- assert_equal(5, S("abc\u{3042 3044 3046}").count("^a"))
- assert_equal(1, S("abc\u{3042 3044 3046}").count("\u3042"))
- assert_equal(5, S("abc\u{3042 3044 3046}").count("^\u3042"))
- assert_equal(2, S("abc\u{3042 3044 3046}").count("a-z", "^a"))
- assert_equal(0, S("abc\u{3042 3044 3046}").count("a", "\u3042"))
- assert_equal(0, S("abc\u{3042 3044 3046}").count("\u3042", "a"))
- assert_equal(0, S("abc\u{3042 3044 3046}").count("\u3042", "\u3044"))
- assert_equal(4, S("abc\u{3042 3044 3046}").count("^a", "^\u3044"))
- assert_equal(4, S("abc\u{3042 3044 3046}").count("^\u3044", "^a"))
- assert_equal(4, S("abc\u{3042 3044 3046}").count("^\u3042", "^\u3044"))
+ assert_equal(5, "abc\u{3042 3044 3046}".count("^a"))
+ assert_equal(1, "abc\u{3042 3044 3046}".count("\u3042"))
+ assert_equal(5, "abc\u{3042 3044 3046}".count("^\u3042"))
+ assert_equal(2, "abc\u{3042 3044 3046}".count("a-z", "^a"))
+ assert_equal(0, "abc\u{3042 3044 3046}".count("a", "\u3042"))
+ assert_equal(0, "abc\u{3042 3044 3046}".count("\u3042", "a"))
+ assert_equal(0, "abc\u{3042 3044 3046}".count("\u3042", "\u3044"))
+ assert_equal(4, "abc\u{3042 3044 3046}".count("^a", "^\u3044"))
+ assert_equal(4, "abc\u{3042 3044 3046}".count("^\u3044", "^a"))
+ assert_equal(4, "abc\u{3042 3044 3046}".count("^\u3042", "^\u3044"))
- assert_raise(ArgumentError) { S("foo").count }
+ assert_raise(ArgumentError) { "foo".count }
end
def crypt_supports_des_crypt?
@@ -747,17 +717,17 @@ CODE
assert_equal(S("hell"), S("hello").delete(S("aeiou"), S("^e")))
assert_equal(S("ho"), S("hello").delete(S("ej-m")))
- assert_equal(S("a").hash, S("a\u0101").delete("\u0101").hash, '[ruby-talk:329267]')
- assert_equal(true, S("a\u0101").delete("\u0101").ascii_only?)
- assert_equal(true, S("a\u3041").delete("\u3041").ascii_only?)
- assert_equal(false, S("a\u3041\u3042").delete("\u3041").ascii_only?)
+ assert_equal("a".hash, "a\u0101".delete("\u0101").hash, '[ruby-talk:329267]')
+ assert_equal(true, "a\u0101".delete("\u0101").ascii_only?)
+ assert_equal(true, "a\u3041".delete("\u3041").ascii_only?)
+ assert_equal(false, "a\u3041\u3042".delete("\u3041").ascii_only?)
- assert_equal("a", S("abc\u{3042 3044 3046}").delete("^a"))
- assert_equal("bc\u{3042 3044 3046}", S("abc\u{3042 3044 3046}").delete("a"))
- assert_equal("\u3042", S("abc\u{3042 3044 3046}").delete("^\u3042"))
+ assert_equal("a", "abc\u{3042 3044 3046}".delete("^a"))
+ assert_equal("bc\u{3042 3044 3046}", "abc\u{3042 3044 3046}".delete("a"))
+ assert_equal("\u3042", "abc\u{3042 3044 3046}".delete("^\u3042"))
bug6160 = '[ruby-dev:45374]'
- assert_equal("", S('\\').delete('\\'), bug6160)
+ assert_equal("", '\\'.delete('\\'), bug6160)
end
def test_delete!
@@ -862,10 +832,10 @@ CODE
assert_equal(Encoding::UTF_8, S('"\\u3042"').encode(Encoding::EUC_JP).undump.encoding)
assert_equal("abc".encode(Encoding::UTF_16LE),
- S('"a\x00b\x00c\x00".force_encoding("UTF-16LE")').undump)
+ '"a\x00b\x00c\x00".force_encoding("UTF-16LE")'.undump)
- assert_equal('\#', S('"\\\\#"').undump)
- assert_equal('\#{', S('"\\\\\#{"').undump)
+ assert_equal('\#', '"\\\\#"'.undump)
+ assert_equal('\#{', '"\\\\\#{"'.undump)
assert_raise(RuntimeError) { S('\u3042').undump }
assert_raise(RuntimeError) { S('"\x82\xA0\u3042"'.force_encoding("SJIS")).undump }
@@ -897,21 +867,10 @@ CODE
assert_raise(RuntimeError) { S('"\\"').undump }
assert_raise(RuntimeError) { S(%("\0")).undump }
assert_raise_with_message(RuntimeError, /invalid/) {
- S('"\\u{007F}".xxxxxx').undump
+ '"\\u{007F}".xxxxxx'.undump
}
end
- def test_undump_gc_compact_stress
- a = S("Test") << 1 << 2 << 3 << 9 << 13 << 10
- EnvUtil.under_gc_compact_stress do
- assert_equal(a, S('"Test\\x01\\x02\\x03\\t\\r\\n"').undump)
- end
-
- EnvUtil.under_gc_compact_stress do
- assert_equal(S("\u{ABCDE 10ABCD}"), S('"\\u{ABCDE 10ABCD}"').undump)
- end
- end
-
def test_dup
for frozen in [ false, true ]
a = S("hello")
@@ -924,18 +883,6 @@ CODE
end
end
- class StringWithIVSet < String
- def set_iv
- @foo = 1
- end
- end
-
- def test_ivar_set_after_frozen_dup
- str = StringWithIVSet.new.freeze
- str.dup.set_iv
- assert_raise(FrozenError) { str.set_iv }
- end
-
def test_each
verbose, $VERBOSE = $VERBOSE, nil
@@ -1100,9 +1047,9 @@ CODE
g = g.encode(enc)
assert_equal g.chars, g.grapheme_clusters
end
- assert_equal ["a", "b", "c"], S("abc").b.grapheme_clusters
+ assert_equal ["a", "b", "c"], "abc".b.grapheme_clusters
- s = S("ABC").b
+ s = "ABC".b
res = []
assert_same s, s.grapheme_clusters {|x| res << x }
assert_equal(3, res.size)
@@ -1111,17 +1058,6 @@ CODE
assert_equal("C", res[2])
end
- def test_grapheme_clusters_memory_leak
- assert_no_memory_leak([], "", "#{<<~"begin;"}\n#{<<~'end;'}", "[Bug #todo]", rss: true)
- begin;
- str = "hello world".encode(Encoding::UTF_32LE)
-
- 10_000.times do
- str.grapheme_clusters
- end
- end;
- end
-
def test_each_line
verbose, $VERBOSE = $VERBOSE, nil
@@ -1159,7 +1095,7 @@ CODE
$/ = save
s = nil
- S("foo\nbar").each_line(nil) {|s2| s = s2 }
+ "foo\nbar".each_line(nil) {|s2| s = s2 }
assert_equal("foo\nbar", s)
assert_equal "hello\n", S("hello\nworld").each_line.next
@@ -1167,7 +1103,7 @@ CODE
bug7646 = "[ruby-dev:46827]"
assert_nothing_raised(bug7646) do
- S("\n\u0100").each_line("\n") {}
+ "\n\u0100".each_line("\n") {}
end
ensure
$/ = save
@@ -1181,19 +1117,14 @@ CODE
assert_equal(S("world"), res[1])
res = []
- S("hello\n\n\nworld\n").each_line(S(''), chomp: true) {|x| res << x}
- assert_equal(S("hello"), res[0])
- assert_equal(S("world\n"), res[1])
-
- res = []
- S("hello\r\n\r\nworld\r\n").each_line(S(''), chomp: true) {|x| res << x}
- assert_equal(S("hello"), res[0])
- assert_equal(S("world\r\n"), res[1])
+ S("hello\n\n\nworld").each_line(S(''), chomp: true) {|x| res << x}
+ assert_equal(S("hello\n"), res[0])
+ assert_equal(S("world"), res[1])
res = []
- S("hello\r\n\n\nworld").each_line(S(''), chomp: true) {|x| res << x}
- assert_equal(S("hello"), res[0])
- assert_equal(S("world"), res[1])
+ S("hello\r\n\r\nworld").each_line(S(''), chomp: true) {|x| res << x}
+ assert_equal(S("hello\r\n"), res[0])
+ assert_equal(S("world"), res[1])
res = []
S("hello!world").each_line(S('!'), chomp: true) {|x| res << x}
@@ -1206,7 +1137,7 @@ CODE
assert_equal(S("a"), res[0])
s = nil
- S("foo\nbar").each_line(nil, chomp: true) {|s2| s = s2 }
+ "foo\nbar".each_line(nil, chomp: true) {|s2| s = s2 }
assert_equal("foo\nbar", s)
assert_equal "hello", S("hello\nworld").each_line(chomp: true).next
@@ -1271,13 +1202,9 @@ CODE
S("hello").gsub(/(hell)(.)/) { |s| $1.upcase + S('-') + $2 })
assert_equal(S("<>h<>e<>l<>l<>o<>"), S("hello").gsub(S(''), S('<\0>')))
- assert_equal("z", S("abc").gsub(/./, "a" => "z"), "moved from btest/knownbug")
+ assert_equal("z", "abc".gsub(/./, "a" => "z"), "moved from btest/knownbug")
- assert_raise(ArgumentError) { S("foo").gsub }
- end
-
- def test_gsub_gc_compact_stress
- EnvUtil.under_gc_compact_stress { assert_equal(S("h<e>ll<o>"), S("hello").gsub(/([aeiou])/, S('<\1>'))) }
+ assert_raise(ArgumentError) { "foo".gsub }
end
def test_gsub_encoding
@@ -1323,32 +1250,24 @@ CODE
assert_nil(a.sub!(S('X'), S('Y')))
end
- def test_gsub_bang_gc_compact_stress
- EnvUtil.under_gc_compact_stress do
- a = S("hello")
- a.gsub!(/([aeiou])/, S('<\1>'))
- assert_equal(S("h<e>ll<o>"), a)
- end
- end
-
def test_sub_hash
- assert_equal('azc', S('abc').sub(/b/, "b" => "z"))
- assert_equal('ac', S('abc').sub(/b/, {}))
- assert_equal('a1c', S('abc').sub(/b/, "b" => 1))
- assert_equal('aBc', S('abc').sub(/b/, Hash.new {|h, k| k.upcase }))
- assert_equal('a[\&]c', S('abc').sub(/b/, "b" => '[\&]'))
- assert_equal('aBcabc', S('abcabc').sub(/b/, Hash.new {|h, k| h[k] = k.upcase }))
- assert_equal('aBcdef', S('abcdef').sub(/de|b/, "b" => "B", "de" => "DE"))
+ assert_equal('azc', 'abc'.sub(/b/, "b" => "z"))
+ assert_equal('ac', 'abc'.sub(/b/, {}))
+ assert_equal('a1c', 'abc'.sub(/b/, "b" => 1))
+ assert_equal('aBc', 'abc'.sub(/b/, Hash.new {|h, k| k.upcase }))
+ assert_equal('a[\&]c', 'abc'.sub(/b/, "b" => '[\&]'))
+ assert_equal('aBcabc', 'abcabc'.sub(/b/, Hash.new {|h, k| h[k] = k.upcase }))
+ assert_equal('aBcdef', 'abcdef'.sub(/de|b/, "b" => "B", "de" => "DE"))
end
def test_gsub_hash
- assert_equal('azc', S('abc').gsub(/b/, "b" => "z"))
- assert_equal('ac', S('abc').gsub(/b/, {}))
- assert_equal('a1c', S('abc').gsub(/b/, "b" => 1))
- assert_equal('aBc', S('abc').gsub(/b/, Hash.new {|h, k| k.upcase }))
- assert_equal('a[\&]c', S('abc').gsub(/b/, "b" => '[\&]'))
- assert_equal('aBcaBc', S('abcabc').gsub(/b/, Hash.new {|h, k| h[k] = k.upcase }))
- assert_equal('aBcDEf', S('abcdef').gsub(/de|b/, "b" => "B", "de" => "DE"))
+ assert_equal('azc', 'abc'.gsub(/b/, "b" => "z"))
+ assert_equal('ac', 'abc'.gsub(/b/, {}))
+ assert_equal('a1c', 'abc'.gsub(/b/, "b" => 1))
+ assert_equal('aBc', 'abc'.gsub(/b/, Hash.new {|h, k| k.upcase }))
+ assert_equal('a[\&]c', 'abc'.gsub(/b/, "b" => '[\&]'))
+ assert_equal('aBcaBc', 'abcabc'.gsub(/b/, Hash.new {|h, k| h[k] = k.upcase }))
+ assert_equal('aBcDEf', 'abcdef'.gsub(/de|b/, "b" => "B", "de" => "DE"))
end
def test_hash
@@ -1358,9 +1277,6 @@ CODE
assert_not_equal(S("a").hash, S("a\0").hash, bug4104)
bug9172 = '[ruby-core:58658] [Bug #9172]'
assert_not_equal(S("sub-setter").hash, S("discover").hash, bug9172)
- assert_equal(S("").hash, S("".encode(Encoding::UTF_32BE)).hash)
- h1, h2 = ["\x80", "\x81"].map {|c| c.b.hash ^ c.hash}
- assert_not_equal(h1, h2)
end
def test_hex
@@ -1381,54 +1297,45 @@ CODE
end
def test_index
- assert_index(0, S("hello"), ?h)
- assert_index(1, S("hello"), S("ell"))
- assert_index(2, S("hello"), /ll./)
+ assert_equal(0, S("hello").index(?h))
+ assert_equal(1, S("hello").index(S("ell")))
+ assert_equal(2, S("hello").index(/ll./))
- assert_index(3, S("hello"), ?l, 3)
- assert_index(3, S("hello"), S("l"), 3)
- assert_index(3, S("hello"), /l./, 3)
+ assert_equal(3, S("hello").index(?l, 3))
+ assert_equal(3, S("hello").index(S("l"), 3))
+ assert_equal(3, S("hello").index(/l./, 3))
- assert_index(nil, S("hello"), ?z, 3)
- assert_index(nil, S("hello"), S("z"), 3)
- assert_index(nil, S("hello"), /z./, 3)
+ assert_nil(S("hello").index(?z, 3))
+ assert_nil(S("hello").index(S("z"), 3))
+ assert_nil(S("hello").index(/z./, 3))
- assert_index(nil, S("hello"), ?z)
- assert_index(nil, S("hello"), S("z"))
- assert_index(nil, S("hello"), /z./)
+ assert_nil(S("hello").index(?z))
+ assert_nil(S("hello").index(S("z")))
+ assert_nil(S("hello").index(/z./))
- assert_index(0, S(""), S(""))
- assert_index(0, S(""), //)
- assert_index(nil, S(""), S("hello"))
- assert_index(nil, S(""), /hello/)
- assert_index(0, S("hello"), S(""))
- assert_index(0, S("hello"), //)
+ assert_equal(0, S("").index(S("")))
+ assert_equal(0, S("").index(//))
+ assert_nil(S("").index(S("hello")))
+ assert_nil(S("").index(/hello/))
+ assert_equal(0, S("hello").index(S("")))
+ assert_equal(0, S("hello").index(//))
s = S("long") * 1000 << "x"
- assert_index(nil, s, S("y"))
- assert_index(4 * 1000, s, S("x"))
+ assert_nil(s.index(S("y")))
+ assert_equal(4 * 1000, s.index(S("x")))
s << "yx"
- assert_index(4 * 1000, s, S("x"))
- assert_index(4 * 1000, s, S("xyx"))
+ assert_equal(4 * 1000, s.index(S("x")))
+ assert_equal(4 * 1000, s.index(S("xyx")))
o = Object.new
def o.to_str; "bar"; end
- assert_index(3, S("foobarbarbaz"), o)
- assert_raise(TypeError) { S("foo").index(Object.new) }
-
- assert_index(nil, S("foo"), //, -100)
- assert_index(nil, S("foo"), //, 4)
-
- assert_index(2, S("abcdbce"), /b\Kc/)
+ assert_equal(3, "foobarbarbaz".index(o))
+ assert_raise(TypeError) { "foo".index(Object.new) }
- assert_index(0, S("こんにちは"), ?こ)
- assert_index(1, S("こんにちは"), S("んにち"))
- assert_index(2, S("こんにちは"), /にち./)
+ assert_nil("foo".index(//, -100))
+ assert_nil($~)
- assert_index(0, S("にんにちは"), ?に, 0)
- assert_index(2, S("にんにちは"), ?に, 1)
- assert_index(2, S("にんにちは"), ?に, 2)
- assert_index(nil, S("にんにちは"), ?に, 3)
+ assert_equal(2, S("abcdbce").index(/b\Kc/))
end
def test_insert
@@ -1535,16 +1442,16 @@ CODE
b = a.replace(S("xyz"))
assert_equal(S("xyz"), b)
- s = S("foo") * 100
+ s = "foo" * 100
s2 = ("bar" * 100).dup
s.replace(s2)
assert_equal(s2, s)
- s2 = [S("foo")].pack("p")
+ s2 = ["foo"].pack("p")
s.replace(s2)
assert_equal(s2, s)
- fs = S("").freeze
+ fs = "".freeze
assert_raise(FrozenError) { fs.replace("a") }
assert_raise(FrozenError) { fs.replace(fs) }
assert_raise(ArgumentError) { fs.replace() }
@@ -1575,57 +1482,34 @@ CODE
end
def test_rindex
- assert_rindex(3, S("hello"), ?l)
- assert_rindex(6, S("ell, hello"), S("ell"))
- assert_rindex(7, S("ell, hello"), /ll./)
-
- assert_rindex(3, S("hello,lo"), ?l, 3)
- assert_rindex(3, S("hello,lo"), S("l"), 3)
- assert_rindex(3, S("hello,lo"), /l./, 3)
+ assert_equal(3, S("hello").rindex(?l))
+ assert_equal(6, S("ell, hello").rindex(S("ell")))
+ assert_equal(7, S("ell, hello").rindex(/ll./))
- assert_rindex(nil, S("hello"), ?z, 3)
- assert_rindex(nil, S("hello"), S("z"), 3)
- assert_rindex(nil, S("hello"), /z./, 3)
+ assert_equal(3, S("hello,lo").rindex(?l, 3))
+ assert_equal(3, S("hello,lo").rindex(S("l"), 3))
+ assert_equal(3, S("hello,lo").rindex(/l./, 3))
- assert_rindex(nil, S("hello"), ?z)
- assert_rindex(nil, S("hello"), S("z"))
- assert_rindex(nil, S("hello"), /z./)
+ assert_nil(S("hello").rindex(?z, 3))
+ assert_nil(S("hello").rindex(S("z"), 3))
+ assert_nil(S("hello").rindex(/z./, 3))
- assert_rindex(5, S("hello"), S(""))
- assert_rindex(5, S("hello"), S(""), 5)
- assert_rindex(4, S("hello"), S(""), 4)
- assert_rindex(0, S("hello"), S(""), 0)
+ assert_nil(S("hello").rindex(?z))
+ assert_nil(S("hello").rindex(S("z")))
+ assert_nil(S("hello").rindex(/z./))
o = Object.new
def o.to_str; "bar"; end
- assert_rindex(6, S("foobarbarbaz"), o)
- assert_raise(TypeError) { S("foo").rindex(Object.new) }
-
- assert_rindex(nil, S("foo"), //, -100)
-
- m = assert_rindex(3, S("foo"), //)
- assert_equal([3, 3], m.offset(0))
- assert_rindex(3, S("foo"), //, 4)
+ assert_equal(6, "foobarbarbaz".rindex(o))
+ assert_raise(TypeError) { "foo".rindex(Object.new) }
- assert_rindex(5, S("abcdbce"), /b\Kc/)
-
- assert_rindex(2, S("こんにちは"), ?に)
- assert_rindex(6, S("にちは、こんにちは"), S("にちは"))
- assert_rindex(6, S("にちは、こんにちは"), /にち./)
+ assert_nil("foo".rindex(//, -100))
+ assert_nil($~)
- assert_rindex(6, S("にちは、こんにちは"), S("にちは"), 7)
- assert_rindex(6, S("にちは、こんにちは"), S("にちは"), -2)
- assert_rindex(6, S("にちは、こんにちは"), S("にちは"), 6)
- assert_rindex(6, S("にちは、こんにちは"), S("にちは"), -3)
- assert_rindex(0, S("にちは、こんにちは"), S("にちは"), 5)
- assert_rindex(0, S("にちは、こんにちは"), S("にちは"), -4)
- assert_rindex(0, S("にちは、こんにちは"), S("にちは"), 1)
- assert_rindex(0, S("にちは、こんにちは"), S("にちは"), 0)
+ assert_equal(3, "foo".rindex(//))
+ assert_equal([3, 3], $~.offset(0))
- assert_rindex(0, S("こんにちは"), S("こんにちは"))
- assert_rindex(nil, S("こんにち"), S("こんにちは"))
- assert_rindex(nil, S("こ"), S("こんにちは"))
- assert_rindex(nil, S(""), S("こんにちは"))
+ assert_equal(5, S("abcdbce").rindex(/b\Kc/))
end
def test_rjust
@@ -1664,19 +1548,6 @@ CODE
assert_equal(%w[1 2 3], S("a1 a2 a3").scan(/a\K./))
end
- def test_scan_gc_compact_stress
- EnvUtil.under_gc_compact_stress { assert_equal([["1a"], ["2b"], ["3c"]], S("1a2b3c").scan(/(\d.)/)) }
- end
-
- def test_scan_segv
- bug19159 = '[Bug #19159]'
- assert_nothing_raised(Exception, bug19159) do
- ObjectSpace.each_object(MatchData).to_a
- "".scan(//)
- ObjectSpace.each_object(MatchData).to_a.inspect
- end
- end
-
def test_size
assert_equal(0, S("").size)
assert_equal(4, S("1234").size)
@@ -1818,8 +1689,7 @@ CODE
assert_equal(S("Bar"), a.slice!(S("Bar")))
assert_equal(S("Foo"), a)
- a = S("foo")
- assert_raise(ArgumentError) { a.slice! }
+ assert_raise(ArgumentError) { "foo".slice! }
end
def test_split
@@ -1844,7 +1714,7 @@ CODE
assert_equal([S("a"), S(""), S("b"), S("c")], S("a||b|c|").split(S('|')))
assert_equal([S("a"), S(""), S("b"), S("c"), S("")], S("a||b|c|").split(S('|'), -1))
- assert_equal([], S("").split(//, 1))
+ assert_equal([], "".split(//, 1))
ensure
EnvUtil.suppress_warning {$; = fs}
end
@@ -1883,18 +1753,16 @@ CODE
result = []; S("a||b|c|").split(S('|'), -1) {|s| result << s}
assert_equal([S("a"), S(""), S("b"), S("c"), S("")], result)
- result = []; S("").split(//, 1) {|s| result << s}
+ result = []; "".split(//, 1) {|s| result << s}
assert_equal([], result)
- result = []; S("aaa,bbb,ccc,ddd").split(/,/) {|s| result << s.gsub(/./, "A")}
+ result = []; "aaa,bbb,ccc,ddd".split(/,/) {|s| result << s.gsub(/./, "A")}
assert_equal(["AAA"]*4, result)
ensure
EnvUtil.suppress_warning {$; = fs}
end
def test_fs
- return unless @cls == String
-
assert_raise_with_message(TypeError, /\$;/) {
$; = []
}
@@ -1984,18 +1852,13 @@ CODE
assert_send([S("hello"), :start_with?, S("hel")])
assert_not_send([S("hello"), :start_with?, S("el")])
assert_send([S("hello"), :start_with?, S("el"), S("he")])
- assert_send([S("\xFF\xFE"), :start_with?, S("\xFF")])
- assert_send([S("hello\xBE"), :start_with?, S("hello")])
- assert_not_send([S("\u{c4}"), :start_with?, S("\xC3")])
bug5536 = '[ruby-core:40623]'
assert_raise(TypeError, bug5536) {S("str").start_with? :not_convertible_to_string}
- end
- def test_start_with_regexp
- assert_equal(true, S("hello").start_with?(/hel/))
+ assert_equal(true, "hello".start_with?(/hel/))
assert_equal("hel", $&)
- assert_equal(false, S("hello").start_with?(/el/))
+ assert_equal(false, "hello".start_with?(/el/))
assert_nil($&)
end
@@ -2005,9 +1868,9 @@ CODE
assert_equal(S("x"), S("\x00x\x00").strip)
assert_equal("0b0 ".force_encoding("UTF-16BE"),
- S("\x00 0b0 ").force_encoding("UTF-16BE").strip)
+ "\x00 0b0 ".force_encoding("UTF-16BE").strip)
assert_equal("0\x000b0 ".force_encoding("UTF-16BE"),
- S("0\x000b0 ").force_encoding("UTF-16BE").strip)
+ "0\x000b0 ".force_encoding("UTF-16BE").strip)
end
def test_strip!
@@ -2072,17 +1935,17 @@ CODE
o = Object.new
def o.to_str; "bar"; end
- assert_equal("fooBARbaz", S("foobarbaz").sub(o, "BAR"))
+ assert_equal("fooBARbaz", "foobarbaz".sub(o, "BAR"))
- assert_raise(TypeError) { S("foo").sub(Object.new, "") }
+ assert_raise(TypeError) { "foo".sub(Object.new, "") }
- assert_raise(ArgumentError) { S("foo").sub }
+ assert_raise(ArgumentError) { "foo".sub }
assert_raise(IndexError) { "foo"[/(?:(o$)|(x))/, 2] = 'bar' }
o = Object.new
def o.to_s; self; end
- assert_match(/^foo#<Object:0x.*>baz$/, S("foobarbaz").sub("bar") { o })
+ assert_match(/^foo#<Object:0x.*>baz$/, "foobarbaz".sub("bar") { o })
assert_equal(S("Abc"), S("abc").sub("a", "A"))
m = nil
@@ -2091,19 +1954,10 @@ CODE
assert_equal(/a/, m.regexp)
bug = '[ruby-core:78686] [Bug #13042] other than regexp has no name references'
assert_raise_with_message(IndexError, /oops/, bug) {
- S('hello').gsub('hello', '\k<oops>')
+ 'hello'.gsub('hello', '\k<oops>')
}
end
- def test_sub_gc_compact_stress
- EnvUtil.under_gc_compact_stress do
- m = /&(?<foo>.*?);/.match(S("aaa &amp; yyy"))
- assert_equal("amp", m["foo"])
-
- assert_equal("aaa [amp] yyy", S("aaa &amp; yyy").sub(/&(?<foo>.*?);/, S('[\k<foo>]')))
- end
- end
-
def test_sub!
a = S("hello")
b = a.dup
@@ -2147,18 +2001,18 @@ CODE
assert_equal(S("AAAAA000"), S("ZZZZ999").succ)
assert_equal(S("*+"), S("**").succ)
- assert_equal("abce", S("abcd").succ)
- assert_equal("THX1139", S("THX1138").succ)
- assert_equal("<\<koalb>>", S("<\<koala>>").succ)
- assert_equal("2000aaa", S("1999zzz").succ)
- assert_equal("AAAA0000", S("ZZZ9999").succ)
- assert_equal("**+", S("***").succ)
+ assert_equal("abce", "abcd".succ)
+ assert_equal("THX1139", "THX1138".succ)
+ assert_equal("<\<koalb>>", "<\<koala>>".succ)
+ assert_equal("2000aaa", "1999zzz".succ)
+ assert_equal("AAAA0000", "ZZZ9999".succ)
+ assert_equal("**+", "***".succ)
- assert_equal("!", S(" ").succ)
- assert_equal("", S("").succ)
+ assert_equal("!", " ".succ)
+ assert_equal("", "".succ)
bug = '[ruby-core:83062] [Bug #13952]'
- s = S("\xff").b
+ s = "\xff".b
assert_not_predicate(s, :ascii_only?)
assert_predicate(s.succ, :ascii_only?, bug)
end
@@ -2210,8 +2064,8 @@ CODE
assert_equal(S(""), a.succ!)
assert_equal(S(""), a)
- assert_equal("aaaaaaaaaaaa", S("zzzzzzzzzzz").succ!)
- assert_equal("aaaaaaaaaaaaaaaaaaaaaaaa", S("zzzzzzzzzzzzzzzzzzzzzzz").succ!)
+ assert_equal("aaaaaaaaaaaa", "zzzzzzzzzzz".succ!)
+ assert_equal("aaaaaaaaaaaaaaaaaaaaaaaa", "zzzzzzzzzzzzzzzzzzzzzzz".succ!)
end
def test_sum
@@ -2233,8 +2087,8 @@ CODE
end
def test_sum_2
- assert_equal(0, S("").sum)
- assert_equal(294, S("abc").sum)
+ assert_equal(0, "".sum)
+ assert_equal(294, "abc".sum)
check_sum("abc")
check_sum("\x80")
-3.upto(70) {|bits|
@@ -2281,39 +2135,39 @@ CODE
def test_to_i
assert_equal(1480, S("1480ft/sec").to_i)
assert_equal(0, S("speed of sound in water @20C = 1480ft/sec)").to_i)
- assert_equal(0, S(" 0").to_i)
- assert_equal(0, S("+0").to_i)
- assert_equal(0, S("-0").to_i)
- assert_equal(0, S("--0").to_i)
- assert_equal(16, S("0x10").to_i(0))
- assert_equal(16, S("0X10").to_i(0))
- assert_equal(2, S("0b10").to_i(0))
- assert_equal(2, S("0B10").to_i(0))
- assert_equal(8, S("0o10").to_i(0))
- assert_equal(8, S("0O10").to_i(0))
- assert_equal(10, S("0d10").to_i(0))
- assert_equal(10, S("0D10").to_i(0))
- assert_equal(8, S("010").to_i(0))
- assert_raise(ArgumentError) { S("010").to_i(-10) }
+ assert_equal(0, " 0".to_i)
+ assert_equal(0, "+0".to_i)
+ assert_equal(0, "-0".to_i)
+ assert_equal(0, "--0".to_i)
+ assert_equal(16, "0x10".to_i(0))
+ assert_equal(16, "0X10".to_i(0))
+ assert_equal(2, "0b10".to_i(0))
+ assert_equal(2, "0B10".to_i(0))
+ assert_equal(8, "0o10".to_i(0))
+ assert_equal(8, "0O10".to_i(0))
+ assert_equal(10, "0d10".to_i(0))
+ assert_equal(10, "0D10".to_i(0))
+ assert_equal(8, "010".to_i(0))
+ assert_raise(ArgumentError) { "010".to_i(-10) }
2.upto(36) {|radix|
- assert_equal(radix, S("10").to_i(radix))
- assert_equal(radix**2, S("100").to_i(radix))
+ assert_equal(radix, "10".to_i(radix))
+ assert_equal(radix**2, "100".to_i(radix))
}
- assert_raise(ArgumentError) { S("0").to_i(1) }
- assert_raise(ArgumentError) { S("0").to_i(37) }
- assert_equal(0, S("z").to_i(10))
- assert_equal(12, S("1_2").to_i(10))
- assert_equal(0x40000000, S("1073741824").to_i(10))
- assert_equal(0x4000000000000000, S("4611686018427387904").to_i(10))
- assert_equal(1, S("1__2").to_i(10))
- assert_equal(1, S("1_z").to_i(10))
+ assert_raise(ArgumentError) { "0".to_i(1) }
+ assert_raise(ArgumentError) { "0".to_i(37) }
+ assert_equal(0, "z".to_i(10))
+ assert_equal(12, "1_2".to_i(10))
+ assert_equal(0x40000000, "1073741824".to_i(10))
+ assert_equal(0x4000000000000000, "4611686018427387904".to_i(10))
+ assert_equal(1, "1__2".to_i(10))
+ assert_equal(1, "1_z".to_i(10))
bug6192 = '[ruby-core:43566]'
- assert_raise(Encoding::CompatibilityError, bug6192) {S("0".encode("utf-16be")).to_i}
- assert_raise(Encoding::CompatibilityError, bug6192) {S("0".encode("utf-16le")).to_i}
- assert_raise(Encoding::CompatibilityError, bug6192) {S("0".encode("utf-32be")).to_i}
- assert_raise(Encoding::CompatibilityError, bug6192) {S("0".encode("utf-32le")).to_i}
- assert_raise(Encoding::CompatibilityError, bug6192) {S("0".encode("iso-2022-jp")).to_i}
+ assert_raise(Encoding::CompatibilityError, bug6192) {"0".encode("utf-16be").to_i}
+ assert_raise(Encoding::CompatibilityError, bug6192) {"0".encode("utf-16le").to_i}
+ assert_raise(Encoding::CompatibilityError, bug6192) {"0".encode("utf-32be").to_i}
+ assert_raise(Encoding::CompatibilityError, bug6192) {"0".encode("utf-32le").to_i}
+ assert_raise(Encoding::CompatibilityError, bug6192) {"0".encode("iso-2022-jp").to_i}
end
def test_to_s
@@ -2345,13 +2199,13 @@ CODE
assert_equal(S("*e**o"), S("hello").tr(S("^aeiou"), S("*")))
assert_equal(S("hal"), S("ibm").tr(S("b-z"), S("a-z")))
- a = S("abc".force_encoding(Encoding::US_ASCII))
+ a = "abc".force_encoding(Encoding::US_ASCII)
assert_equal(Encoding::US_ASCII, a.tr(S("z"), S("\u0101")).encoding, '[ruby-core:22326]')
- assert_equal("a".hash, S("a").tr("a", "\u0101").tr("\u0101", "a").hash, '[ruby-core:22328]')
- assert_equal(true, S("\u0101").tr("\u0101", "a").ascii_only?)
- assert_equal(true, S("\u3041").tr("\u3041", "a").ascii_only?)
- assert_equal(false, S("\u3041\u3042").tr("\u3041", "a").ascii_only?)
+ assert_equal("a".hash, "a".tr("a", "\u0101").tr("\u0101", "a").hash, '[ruby-core:22328]')
+ assert_equal(true, "\u0101".tr("\u0101", "a").ascii_only?)
+ assert_equal(true, "\u3041".tr("\u3041", "a").ascii_only?)
+ assert_equal(false, "\u3041\u3042".tr("\u3041", "a").ascii_only?)
bug6156 = '[ruby-core:43335]'
bug13950 = '[ruby-core:83056] [Bug #13950]'
@@ -2361,8 +2215,6 @@ CODE
assert_not_predicate(str, :ascii_only?)
assert_not_predicate(star, :ascii_only?)
assert_not_predicate(result, :ascii_only?, bug13950)
-
- assert_equal(S("XYC"), S("ABC").tr("A-AB", "XY"))
end
def test_tr!
@@ -2384,20 +2236,16 @@ CODE
assert_nil(a.tr!(S("B-Z"), S("A-Z")))
assert_equal(S("ibm"), a)
- a = S("abc".force_encoding(Encoding::US_ASCII))
+ a = "abc".force_encoding(Encoding::US_ASCII)
assert_nil(a.tr!(S("z"), S("\u0101")), '[ruby-core:22326]')
assert_equal(Encoding::US_ASCII, a.encoding, '[ruby-core:22326]')
-
- assert_equal(S("XYC"), S("ABC").tr!("A-AB", "XY"))
end
def test_tr_s
assert_equal(S("hypo"), S("hello").tr_s(S("el"), S("yp")))
assert_equal(S("h*o"), S("hello").tr_s(S("el"), S("*")))
- assert_equal("a".hash, S("\u0101\u0101").tr_s("\u0101", "a").hash)
- assert_equal(true, S("\u3041\u3041").tr("\u3041", "a").ascii_only?)
-
- assert_equal(S("XYC"), S("ABC").tr_s("A-AB", "XY"))
+ assert_equal("a".hash, "\u0101\u0101".tr_s("\u0101", "a").hash)
+ assert_equal(true, "\u3041\u3041".tr("\u3041", "a").ascii_only?)
end
def test_tr_s!
@@ -2410,8 +2258,6 @@ CODE
a = S("hello")
assert_equal(S("h*o"), a.tr_s!(S("el"), S("*")))
assert_equal(S("h*o"), a)
-
- assert_equal(S("XYC"), S("ABC").tr_s!("A-AB", "XY"))
end
def test_unpack
@@ -2499,7 +2345,6 @@ CODE
assert_equal(S("HELLO"), S("HELLO").upcase)
assert_equal(S("ABC HELLO 123"), S("abc HELLO 123").upcase)
assert_equal(S("H\0""ELLO"), S("H\0""ello").upcase)
- assert_equal(S("\u{10574}"), S("\u{1059B}").upcase)
end
def test_upcase!
@@ -2573,8 +2418,6 @@ CODE
class S2 < String
end
def test_str_new4
- return unless @cls == String
-
s = (0..54).to_a.join # length = 100
s2 = S2.new(s[10,90])
s3 = s2[10,80]
@@ -2583,7 +2426,7 @@ CODE
end
def test_rb_str_new4
- s = S("a" * 100)
+ s = "a" * 100
s2 = s[10,90]
assert_equal("a" * 90, s2)
s3 = s2[10,80]
@@ -2601,11 +2444,11 @@ CODE
end
def test_rb_str_to_str
- assert_equal("ab", S("a") + StringLike.new("b"))
+ assert_equal("ab", "a" + StringLike.new("b"))
end
def test_rb_str_shared_replace
- s = S("a" * 100)
+ s = "a" * 100
s.succ!
assert_equal("a" * 99 + "b", s)
s = ""
@@ -2629,12 +2472,12 @@ CODE
def test_times2
s1 = ''
100.times {|n|
- s2 = S("a") * n
+ s2 = "a" * n
assert_equal(s1, s2)
s1 << 'a'
}
- assert_raise(ArgumentError) { S("foo") * (-1) }
+ assert_raise(ArgumentError) { "foo" * (-1) }
end
def test_respond_to
@@ -2642,41 +2485,41 @@ CODE
def o.respond_to?(arg) [:to_str].include?(arg) ? nil : super end
def o.to_str() "" end
def o.==(other) "" == other end
- assert_equal(false, S("") == o)
+ assert_equal(false, "" == o)
end
def test_match_method
- assert_equal("bar", S("foobarbaz").match(/bar/).to_s)
+ assert_equal("bar", "foobarbaz".match(/bar/).to_s)
o = Regexp.new('foo')
def o.match(x, y, z); x + y + z; end
- assert_equal("foobarbaz", S("foo").match(o, "bar", "baz"))
+ assert_equal("foobarbaz", "foo".match(o, "bar", "baz"))
x = nil
- S("foo").match(o, "bar", "baz") {|y| x = y }
+ "foo".match(o, "bar", "baz") {|y| x = y }
assert_equal("foobarbaz", x)
- assert_raise(ArgumentError) { S("foo").match }
+ assert_raise(ArgumentError) { "foo".match }
end
def test_match_p_regexp
/backref/ =~ 'backref'
# must match here, but not in a separate method, e.g., assert_send,
# to check if $~ is affected or not.
- assert_equal(true, S("").match?(//))
+ assert_equal(true, "".match?(//))
assert_equal(true, :abc.match?(/.../))
- assert_equal(true, S('abc').match?(/b/))
- assert_equal(true, S('abc').match?(/b/, 1))
- assert_equal(true, S('abc').match?(/../, 1))
- assert_equal(true, S('abc').match?(/../, -2))
- assert_equal(false, S('abc').match?(/../, -4))
- assert_equal(false, S('abc').match?(/../, 4))
- assert_equal(true, S("\u3042xx").match?(/../, 1))
- assert_equal(false, S("\u3042x").match?(/../, 1))
- assert_equal(true, S('').match?(/\z/))
- assert_equal(true, S('abc').match?(/\z/))
- assert_equal(true, S('Ruby').match?(/R.../))
- assert_equal(false, S('Ruby').match?(/R.../, 1))
- assert_equal(false, S('Ruby').match?(/P.../))
+ assert_equal(true, 'abc'.match?(/b/))
+ assert_equal(true, 'abc'.match?(/b/, 1))
+ assert_equal(true, 'abc'.match?(/../, 1))
+ assert_equal(true, 'abc'.match?(/../, -2))
+ assert_equal(false, 'abc'.match?(/../, -4))
+ assert_equal(false, 'abc'.match?(/../, 4))
+ assert_equal(true, "\u3042xx".match?(/../, 1))
+ assert_equal(false, "\u3042x".match?(/../, 1))
+ assert_equal(true, ''.match?(/\z/))
+ assert_equal(true, 'abc'.match?(/\z/))
+ assert_equal(true, 'Ruby'.match?(/R.../))
+ assert_equal(false, 'Ruby'.match?(/R.../, 1))
+ assert_equal(false, 'Ruby'.match?(/P.../))
assert_equal('backref', $&)
end
@@ -2684,21 +2527,21 @@ CODE
/backref/ =~ 'backref'
# must match here, but not in a separate method, e.g., assert_send,
# to check if $~ is affected or not.
- assert_equal(true, S("").match?(''))
+ assert_equal(true, "".match?(''))
assert_equal(true, :abc.match?('...'))
- assert_equal(true, S('abc').match?('b'))
- assert_equal(true, S('abc').match?('b', 1))
- assert_equal(true, S('abc').match?('..', 1))
- assert_equal(true, S('abc').match?('..', -2))
- assert_equal(false, S('abc').match?('..', -4))
- assert_equal(false, S('abc').match?('..', 4))
- assert_equal(true, S("\u3042xx").match?('..', 1))
- assert_equal(false, S("\u3042x").match?('..', 1))
- assert_equal(true, S('').match?('\z'))
- assert_equal(true, S('abc').match?('\z'))
- assert_equal(true, S('Ruby').match?('R...'))
- assert_equal(false, S('Ruby').match?('R...', 1))
- assert_equal(false, S('Ruby').match?('P...'))
+ assert_equal(true, 'abc'.match?('b'))
+ assert_equal(true, 'abc'.match?('b', 1))
+ assert_equal(true, 'abc'.match?('..', 1))
+ assert_equal(true, 'abc'.match?('..', -2))
+ assert_equal(false, 'abc'.match?('..', -4))
+ assert_equal(false, 'abc'.match?('..', 4))
+ assert_equal(true, "\u3042xx".match?('..', 1))
+ assert_equal(false, "\u3042x".match?('..', 1))
+ assert_equal(true, ''.match?('\z'))
+ assert_equal(true, 'abc'.match?('\z'))
+ assert_equal(true, 'Ruby'.match?('R...'))
+ assert_equal(false, 'Ruby'.match?('R...', 1))
+ assert_equal(false, 'Ruby'.match?('P...'))
assert_equal('backref', $&)
end
@@ -2718,23 +2561,18 @@ CODE
def test_inspect_nul
bug8290 = '[ruby-core:54458]'
- s = S("\0") + "12"
+ s = "\0" + "12"
assert_equal '"\u000012"', s.inspect, bug8290
- s = S("\0".b) + "12"
+ s = "\0".b + "12"
assert_equal '"\x0012"', s.inspect, bug8290
end
- def test_inspect_next_line
- bug16842 = '[ruby-core:98231]'
- assert_equal '"\\u0085"', 0x85.chr(Encoding::UTF_8).inspect, bug16842
- end
-
def test_partition
- assert_equal(%w(he l lo), S("hello").partition(/l/))
- assert_equal(%w(he l lo), S("hello").partition("l"))
- assert_raise(TypeError) { S("hello").partition(1) }
+ assert_equal(%w(he l lo), "hello".partition(/l/))
+ assert_equal(%w(he l lo), "hello".partition("l"))
+ assert_raise(TypeError) { "hello".partition(1) }
def (hyphen = Object.new).to_str; "-"; end
- assert_equal(%w(foo - bar), S("foo-bar").partition(hyphen), '[ruby-core:23540]')
+ assert_equal(%w(foo - bar), "foo-bar".partition(hyphen), '[ruby-core:23540]')
bug6206 = '[ruby-dev:45441]'
Encoding.list.each do |enc|
@@ -2744,24 +2582,24 @@ CODE
end
assert_equal(["\u30E6\u30FC\u30B6", "@", "\u30C9\u30E1.\u30A4\u30F3"],
- S("\u30E6\u30FC\u30B6@\u30C9\u30E1.\u30A4\u30F3").partition(/[@.]/))
+ "\u30E6\u30FC\u30B6@\u30C9\u30E1.\u30A4\u30F3".partition(/[@.]/))
bug = '[ruby-core:82911]'
- hello = S("hello")
+ hello = "hello"
hello.partition("hi").map(&:upcase!)
assert_equal("hello", hello, bug)
- assert_equal(["", "", "foo"], S("foo").partition(/^=*/))
+ assert_equal(["", "", "foo"], "foo".partition(/^=*/))
assert_equal([S("ab"), S("c"), S("dbce")], S("abcdbce").partition(/b\Kc/))
end
def test_rpartition
- assert_equal(%w(hel l o), S("hello").rpartition(/l/))
- assert_equal(%w(hel l o), S("hello").rpartition("l"))
- assert_raise(TypeError) { S("hello").rpartition(1) }
+ assert_equal(%w(hel l o), "hello".rpartition(/l/))
+ assert_equal(%w(hel l o), "hello".rpartition("l"))
+ assert_raise(TypeError) { "hello".rpartition(1) }
def (hyphen = Object.new).to_str; "-"; end
- assert_equal(%w(foo - bar), S("foo-bar").rpartition(hyphen), '[ruby-core:23540]')
+ assert_equal(%w(foo - bar), "foo-bar".rpartition(hyphen), '[ruby-core:23540]')
bug6206 = '[ruby-dev:45441]'
Encoding.list.each do |enc|
@@ -2772,7 +2610,7 @@ CODE
bug8138 = '[ruby-dev:47183]'
assert_equal(["\u30E6\u30FC\u30B6@\u30C9\u30E1", ".", "\u30A4\u30F3"],
- S("\u30E6\u30FC\u30B6@\u30C9\u30E1.\u30A4\u30F3").rpartition(/[@.]/), bug8138)
+ "\u30E6\u30FC\u30B6@\u30C9\u30E1.\u30A4\u30F3".rpartition(/[@.]/), bug8138)
bug = '[ruby-core:82911]'
hello = "hello"
@@ -2782,13 +2620,10 @@ CODE
assert_equal([S("abcdb"), S("c"), S("e")], S("abcdbce").rpartition(/b\Kc/))
end
- def test_fs_setter
- return unless @cls == String
-
+ def test_setter
assert_raise(TypeError) { $/ = 1 }
name = "\u{5206 884c}"
- assert_separately([], "#{<<~"do;"}\n#{<<~"end;"}")
- do;
+ assert_separately([], <<-"end;") # do
alias $#{name} $/
assert_raise_with_message(TypeError, /\\$#{name}/) { $#{name} = 1 }
end;
@@ -2821,19 +2656,16 @@ CODE
end
def test_gsub_enumerator
- e = S("abc").gsub(/./)
- assert_equal("a", e.next, "[ruby-dev:34828]")
- assert_equal("b", e.next)
- assert_equal("c", e.next)
+ assert_normal_exit %q{"abc".gsub(/./).next}, "[ruby-dev:34828]"
end
def test_clear_nonasciicompat
- assert_equal("", S("\u3042".encode("ISO-2022-JP")).clear)
+ assert_equal("", "\u3042".encode("ISO-2022-JP").clear)
end
def test_try_convert
- assert_equal(nil, @cls.try_convert(1))
- assert_equal("foo", @cls.try_convert("foo"))
+ assert_equal(nil, String.try_convert(1))
+ assert_equal("foo", String.try_convert("foo"))
end
def test_substr_negative_begin
@@ -2842,55 +2674,55 @@ CODE
=begin
def test_compare_different_encoding_string
- s1 = S("\xff".force_encoding("UTF-8"))
- s2 = S("\xff".force_encoding("ISO-2022-JP"))
+ s1 = "\xff".force_encoding("UTF-8")
+ s2 = "\xff".force_encoding("ISO-2022-JP")
assert_equal([-1, 1], [s1 <=> s2, s2 <=> s1].sort)
end
=end
def test_casecmp
- assert_equal(0, S("FoO").casecmp("fOO"))
- assert_equal(1, S("FoO").casecmp("BaR"))
- assert_equal(-1, S("baR").casecmp("FoO"))
- assert_equal(1, S("\u3042B").casecmp("\u3042a"))
- assert_equal(-1, S("foo").casecmp("foo\0"))
+ assert_equal(0, "FoO".casecmp("fOO"))
+ assert_equal(1, "FoO".casecmp("BaR"))
+ assert_equal(-1, "baR".casecmp("FoO"))
+ assert_equal(1, "\u3042B".casecmp("\u3042a"))
+ assert_equal(-1, "foo".casecmp("foo\0"))
- assert_nil(S("foo").casecmp(:foo))
- assert_nil(S("foo").casecmp(Object.new))
+ assert_nil("foo".casecmp(:foo))
+ assert_nil("foo".casecmp(Object.new))
o = Object.new
def o.to_str; "fOO"; end
- assert_equal(0, S("FoO").casecmp(o))
+ assert_equal(0, "FoO".casecmp(o))
end
def test_casecmp?
- assert_equal(true, S('FoO').casecmp?('fOO'))
- assert_equal(false, S('FoO').casecmp?('BaR'))
- assert_equal(false, S('baR').casecmp?('FoO'))
- assert_equal(true, S('äöü').casecmp?('ÄÖÜ'))
- assert_equal(false, S("foo").casecmp?("foo\0"))
+ assert_equal(true, 'FoO'.casecmp?('fOO'))
+ assert_equal(false, 'FoO'.casecmp?('BaR'))
+ assert_equal(false, 'baR'.casecmp?('FoO'))
+ assert_equal(true, 'äöü'.casecmp?('ÄÖÜ'))
+ assert_equal(false, "foo".casecmp?("foo\0"))
- assert_nil(S("foo").casecmp?(:foo))
- assert_nil(S("foo").casecmp?(Object.new))
+ assert_nil("foo".casecmp?(:foo))
+ assert_nil("foo".casecmp?(Object.new))
o = Object.new
def o.to_str; "fOO"; end
- assert_equal(true, S("FoO").casecmp?(o))
+ assert_equal(true, "FoO".casecmp?(o))
end
def test_upcase2
- assert_equal("\u3042AB", S("\u3042aB").upcase)
+ assert_equal("\u3042AB", "\u3042aB".upcase)
end
def test_downcase2
- assert_equal("\u3042ab", S("\u3042aB").downcase)
+ assert_equal("\u3042ab", "\u3042aB".downcase)
end
def test_rstrip
- assert_equal(" hello", S(" hello ").rstrip)
- assert_equal("\u3042", S("\u3042 ").rstrip)
- assert_equal("\u3042", S("\u3042\u0000").rstrip)
- assert_raise(Encoding::CompatibilityError) { S("\u3042".encode("ISO-2022-JP")).rstrip }
+ assert_equal(" hello", " hello ".rstrip)
+ assert_equal("\u3042", "\u3042 ".rstrip)
+ assert_equal("\u3042", "\u3042\u0000".rstrip)
+ assert_raise(Encoding::CompatibilityError) { "\u3042".encode("ISO-2022-JP").rstrip }
end
def test_rstrip_bang
@@ -2914,18 +2746,13 @@ CODE
assert_equal("\u3042", s5.rstrip!)
assert_equal("\u3042", s5)
- assert_raise(Encoding::CompatibilityError) { S("\u3042".encode("ISO-2022-JP")).rstrip! }
- assert_raise(Encoding::CompatibilityError) { S("abc \x80 ".force_encoding('UTF-8')).rstrip! }
- assert_raise(Encoding::CompatibilityError) { S("abc\x80 ".force_encoding('UTF-8')).rstrip! }
- assert_raise(Encoding::CompatibilityError) { S("abc \x80".force_encoding('UTF-8')).rstrip! }
- assert_raise(Encoding::CompatibilityError) { S("\x80".force_encoding('UTF-8')).rstrip! }
- assert_raise(Encoding::CompatibilityError) { S(" \x80 ".force_encoding('UTF-8')).rstrip! }
+ assert_raise(Encoding::CompatibilityError) { "\u3042".encode("ISO-2022-JP").rstrip! }
end
def test_lstrip
- assert_equal("hello ", S(" hello ").lstrip)
- assert_equal("\u3042", S(" \u3042").lstrip)
- assert_equal("hello ", S("\x00hello ").lstrip)
+ assert_equal("hello ", " hello ".lstrip)
+ assert_equal("\u3042", " \u3042".lstrip)
+ assert_equal("hello ", "\x00hello ".lstrip)
end
def test_lstrip_bang
@@ -2951,13 +2778,11 @@ CODE
end
- def test_delete_prefix_type_error
- assert_raise(TypeError) { S('hello').delete_prefix(nil) }
- assert_raise(TypeError) { S('hello').delete_prefix(1) }
- assert_raise(TypeError) { S('hello').delete_prefix(/hel/) }
- end
-
def test_delete_prefix
+ assert_raise(TypeError) { 'hello'.delete_prefix(nil) }
+ assert_raise(TypeError) { 'hello'.delete_prefix(1) }
+ assert_raise(TypeError) { 'hello'.delete_prefix(/hel/) }
+
s = S("hello")
assert_equal("lo", s.delete_prefix('hel'))
assert_equal("hello", s)
@@ -2977,9 +2802,8 @@ CODE
s = S("hello")
assert_equal("hello", s.delete_prefix("\u{3053 3093}"))
assert_equal("hello", s)
- end
- def test_delete_prefix_broken_encoding
+ # skip if argument is a broken string
s = S("\xe3\x81\x82")
assert_equal("\xe3\x81\x82", s.delete_prefix("\xe3"))
assert_equal("\xe3\x81\x82", s)
@@ -2988,31 +2812,23 @@ CODE
assert_equal("\x95\x5c".force_encoding("Shift_JIS"), s.delete_prefix("\x95"))
assert_equal("\x95\x5c".force_encoding("Shift_JIS"), s)
- assert_equal("\xFE", S("\xFF\xFE").delete_prefix("\xFF"))
- assert_equal("\xBE", S("hello\xBE").delete_prefix("hello"))
- assert_equal("\xBE", S("\xFFhello\xBE").delete_prefix("\xFFhello"))
- end
-
- def test_delete_prefix_clear_coderange
+ # clear coderange
s = S("\u{3053 3093}hello")
assert_not_predicate(s, :ascii_only?)
assert_predicate(s.delete_prefix("\u{3053 3093}"), :ascii_only?)
- end
- def test_delete_prefix_argument_conversion
+ # argument should be converted to String
klass = Class.new { def to_str; 'a'; end }
s = S("abba")
assert_equal("bba", s.delete_prefix(klass.new))
assert_equal("abba", s)
end
- def test_delete_prefix_bang_type_error
- assert_raise(TypeError) { S('hello').delete_prefix!(nil) }
- assert_raise(TypeError) { S('hello').delete_prefix!(1) }
- assert_raise(TypeError) { S('hello').delete_prefix!(/hel/) }
- end
-
def test_delete_prefix_bang
+ assert_raise(TypeError) { 'hello'.delete_prefix!(nil) }
+ assert_raise(TypeError) { 'hello'.delete_prefix!(1) }
+ assert_raise(TypeError) { 'hello'.delete_prefix!(/hel/) }
+
s = S("hello")
assert_equal("lo", s.delete_prefix!('hel'))
assert_equal("lo", s)
@@ -3032,32 +2848,23 @@ CODE
s = S("hello")
assert_equal(nil, s.delete_prefix!("\u{3053 3093}"))
assert_equal("hello", s)
- end
- def test_delete_prefix_bang_broken_encoding
+ # skip if argument is a broken string
s = S("\xe3\x81\x82")
assert_equal(nil, s.delete_prefix!("\xe3"))
assert_equal("\xe3\x81\x82", s)
- s = S("\xFF\xFE")
- assert_equal("\xFE", s.delete_prefix!("\xFF"))
- assert_equal("\xFE", s)
- end
-
- def test_delete_prefix_bang_clear_coderange
+ # clear coderange
s = S("\u{3053 3093}hello")
assert_not_predicate(s, :ascii_only?)
assert_predicate(s.delete_prefix!("\u{3053 3093}"), :ascii_only?)
- end
- def test_delete_prefix_bang_argument_conversion
+ # argument should be converted to String
klass = Class.new { def to_str; 'a'; end }
s = S("abba")
assert_equal("bba", s.delete_prefix!(klass.new))
assert_equal("bba", s)
- end
- def test_delete_prefix_bang_frozen_error
s = S("ax").freeze
assert_raise_with_message(FrozenError, /frozen/) {s.delete_prefix!("a")}
@@ -3070,13 +2877,11 @@ CODE
assert_raise_with_message(FrozenError, /frozen/) {s.delete_prefix!(o)}
end
- def test_delete_suffix_type_error
- assert_raise(TypeError) { S('hello').delete_suffix(nil) }
- assert_raise(TypeError) { S('hello').delete_suffix(1) }
- assert_raise(TypeError) { S('hello').delete_suffix(/hel/) }
- end
-
def test_delete_suffix
+ assert_raise(TypeError) { 'hello'.delete_suffix(nil) }
+ assert_raise(TypeError) { 'hello'.delete_suffix(1) }
+ assert_raise(TypeError) { 'hello'.delete_suffix(/hel/) }
+
s = S("hello")
assert_equal("hel", s.delete_suffix('lo'))
assert_equal("hello", s)
@@ -3096,28 +2901,23 @@ CODE
s = S("hello")
assert_equal("hello", s.delete_suffix("\u{3061 306f}"))
assert_equal("hello", s)
- end
- def test_delete_suffix_broken_encoding
+ # skip if argument is a broken string
s = S("\xe3\x81\x82")
assert_equal("\xe3\x81\x82", s.delete_suffix("\x82"))
assert_equal("\xe3\x81\x82", s)
- end
- def test_delete_suffix_clear_coderange
+ # clear coderange
s = S("hello\u{3053 3093}")
assert_not_predicate(s, :ascii_only?)
assert_predicate(s.delete_suffix("\u{3053 3093}"), :ascii_only?)
- end
- def test_delete_suffix_argument_conversion
+ # argument should be converted to String
klass = Class.new { def to_str; 'a'; end }
s = S("abba")
assert_equal("abb", s.delete_suffix(klass.new))
assert_equal("abba", s)
- end
- def test_delete_suffix_newline
# chomp removes any of "\n", "\r\n", "\r" when "\n" is specified,
# but delete_suffix does not
s = "foo\n"
@@ -3128,13 +2928,11 @@ CODE
assert_equal("foo\r", s.delete_suffix("\n"))
end
- def test_delete_suffix_bang_type_error
- assert_raise(TypeError) { S('hello').delete_suffix!(nil) }
- assert_raise(TypeError) { S('hello').delete_suffix!(1) }
- assert_raise(TypeError) { S('hello').delete_suffix!(/hel/) }
- end
+ def test_delete_suffix_bang
+ assert_raise(TypeError) { 'hello'.delete_suffix!(nil) }
+ assert_raise(TypeError) { 'hello'.delete_suffix!(1) }
+ assert_raise(TypeError) { 'hello'.delete_suffix!(/hel/) }
- def test_delete_suffix_bang_frozen_error
s = S("hello").freeze
assert_raise_with_message(FrozenError, /frozen/) {s.delete_suffix!('lo')}
@@ -3145,9 +2943,7 @@ CODE
"x"
end
assert_raise_with_message(FrozenError, /frozen/) {s.delete_suffix!(o)}
- end
- def test_delete_suffix_bang
s = S("hello")
assert_equal("hel", s.delete_suffix!('lo'))
assert_equal("hel", s)
@@ -3167,9 +2963,8 @@ CODE
s = S("hello")
assert_equal(nil, s.delete_suffix!("\u{3061 306f}"))
assert_equal("hello", s)
- end
- def test_delete_suffix_bang_broken_encoding
+ # skip if argument is a broken string
s = S("\xe3\x81\x82")
assert_equal(nil, s.delete_suffix!("\x82"))
assert_equal("\xe3\x81\x82", s)
@@ -3177,22 +2972,18 @@ CODE
s = S("\x95\x5c").force_encoding("Shift_JIS")
assert_equal(nil, s.delete_suffix!("\x5c"))
assert_equal("\x95\x5c".force_encoding("Shift_JIS"), s)
- end
- def test_delete_suffix_bang_clear_coderange
+ # clear coderange
s = S("hello\u{3053 3093}")
assert_not_predicate(s, :ascii_only?)
assert_predicate(s.delete_suffix!("\u{3053 3093}"), :ascii_only?)
- end
- def test_delete_suffix_bang_argument_conversion
+ # argument should be converted to String
klass = Class.new { def to_str; 'a'; end }
s = S("abba")
assert_equal("abb", s.delete_suffix!(klass.new))
assert_equal("abb", s)
- end
- def test_delete_suffix_bang_newline
# chomp removes any of "\n", "\r\n", "\r" when "\n" is specified,
# but delete_suffix does not
s = "foo\n"
@@ -3229,7 +3020,7 @@ CODE
end
def test_shared_force_encoding
- s = S("\u{3066}\u{3059}\u{3068}").gsub(//, '')
+ s = "\u{3066}\u{3059}\u{3068}".gsub(//, '')
h = {}
h[s] = nil
k = h.keys[0]
@@ -3244,16 +3035,16 @@ CODE
def test_ascii_incomat_inspect
bug4081 = '[ruby-core:33283]'
WIDE_ENCODINGS.each do |e|
- assert_equal('"abc"', S("abc".encode(e)).inspect)
- assert_equal('"\\u3042\\u3044\\u3046"', S("\u3042\u3044\u3046".encode(e)).inspect)
- assert_equal('"ab\\"c"', S("ab\"c".encode(e)).inspect, bug4081)
+ 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)
end
begin
verbose, $VERBOSE = $VERBOSE, nil
ext = Encoding.default_external
Encoding.default_external = "us-ascii"
$VERBOSE = verbose
- i = S("abc\"\\".force_encoding("utf-8")).inspect
+ i = "abc\"\\".force_encoding("utf-8").inspect
ensure
$VERBOSE = nil
Encoding.default_external = ext
@@ -3264,11 +3055,11 @@ CODE
def test_dummy_inspect
assert_equal('"\e\x24\x42\x22\x4C\x22\x68\e\x28\x42"',
- S("\u{ffe2}\u{2235}".encode("cp50220")).inspect)
+ "\u{ffe2}\u{2235}".encode("cp50220").inspect)
end
def test_prepend
- assert_equal(S("hello world!"), S("!").prepend("hello ", "world"))
+ assert_equal(S("hello world!"), "!".prepend("hello ", "world"))
b = S("ue")
assert_equal(S("ueueue"), b.prepend(b, b))
@@ -3276,7 +3067,7 @@ CODE
def foo.to_str
"b"
end
- assert_equal(S("ba"), S("a").prepend(foo))
+ assert_equal(S("ba"), "a".prepend(foo))
a = S("world")
b = S("hello ")
@@ -3290,34 +3081,34 @@ CODE
end
def test_byteslice
- assert_equal("h", S("hello").byteslice(0))
- assert_equal(nil, S("hello").byteslice(5))
- assert_equal("o", S("hello").byteslice(-1))
- assert_equal(nil, S("hello").byteslice(-6))
-
- assert_equal("", S("hello").byteslice(0, 0))
- assert_equal("hello", S("hello").byteslice(0, 6))
- assert_equal("hello", S("hello").byteslice(0, 6))
- assert_equal("", S("hello").byteslice(5, 1))
- assert_equal("o", S("hello").byteslice(-1, 6))
- assert_equal(nil, S("hello").byteslice(-6, 1))
- assert_equal(nil, S("hello").byteslice(0, -1))
-
- assert_equal("h", S("hello").byteslice(0..0))
- assert_equal("", S("hello").byteslice(5..0))
- assert_equal("o", S("hello").byteslice(4..5))
- assert_equal(nil, S("hello").byteslice(6..0))
- assert_equal("", S("hello").byteslice(-1..0))
- assert_equal("llo", S("hello").byteslice(-3..5))
-
- assert_equal(u("\x81"), S("\u3042").byteslice(1))
- assert_equal(u("\x81\x82"), S("\u3042").byteslice(1, 2))
- assert_equal(u("\x81\x82"), S("\u3042").byteslice(1..2))
-
- assert_equal(u("\x82")+("\u3042"*9), S("\u3042"*10).byteslice(2, 28))
+ assert_equal("h", "hello".byteslice(0))
+ assert_equal(nil, "hello".byteslice(5))
+ assert_equal("o", "hello".byteslice(-1))
+ assert_equal(nil, "hello".byteslice(-6))
+
+ assert_equal("", "hello".byteslice(0, 0))
+ assert_equal("hello", "hello".byteslice(0, 6))
+ assert_equal("hello", "hello".byteslice(0, 6))
+ assert_equal("", "hello".byteslice(5, 1))
+ assert_equal("o", "hello".byteslice(-1, 6))
+ assert_equal(nil, "hello".byteslice(-6, 1))
+ assert_equal(nil, "hello".byteslice(0, -1))
+
+ assert_equal("h", "hello".byteslice(0..0))
+ assert_equal("", "hello".byteslice(5..0))
+ assert_equal("o", "hello".byteslice(4..5))
+ assert_equal(nil, "hello".byteslice(6..0))
+ assert_equal("", "hello".byteslice(-1..0))
+ assert_equal("llo", "hello".byteslice(-3..5))
+
+ assert_equal(u("\x81"), "\u3042".byteslice(1))
+ assert_equal(u("\x81\x82"), "\u3042".byteslice(1, 2))
+ assert_equal(u("\x81\x82"), "\u3042".byteslice(1..2))
+
+ assert_equal(u("\x82")+("\u3042"*9), ("\u3042"*10).byteslice(2, 28))
bug7954 = '[ruby-dev:47108]'
- assert_equal(false, S("\u3042").byteslice(0, 2).valid_encoding?, bug7954)
+ assert_equal(false, "\u3042".byteslice(0, 2).valid_encoding?, bug7954)
assert_equal(false, ("\u3042"*10).byteslice(0, 20).valid_encoding?, bug7954)
end
@@ -3332,8 +3123,6 @@ CODE
end
def test_eq_tilde_can_be_overridden
- return unless @cls == String
-
assert_separately([], <<-RUBY)
class String
undef =~
@@ -3351,7 +3140,7 @@ CODE
end
def test_regexp_match_subclass
- s = Bug9581.new(S("abc"))
+ s = Bug9581.new("abc")
r = /abc/
assert_equal(:foo, s =~ r)
assert_equal(:foo, s.send(:=~, r))
@@ -3361,7 +3150,6 @@ CODE
def test_LSHIFT_neary_long_max
return unless @cls == String
-
assert_ruby_status([], <<-'end;', '[ruby-core:61886] [Bug #9709]', timeout: 20)
begin
a = "a" * 0x4000_0000
@@ -3373,8 +3161,6 @@ CODE
# enable only when string size range is smaller than memory space
def test_uplus_minus
- return unless @cls == String
-
str = "foo"
assert_not_predicate(str, :frozen?)
assert_not_predicate(+str, :frozen?)
@@ -3396,8 +3182,6 @@ CODE
end
def test_uminus_frozen
- return unless @cls == String
-
# embedded
str1 = ("foobar" * 3).freeze
str2 = ("foobar" * 3).freeze
@@ -3414,274 +3198,45 @@ CODE
end
def test_uminus_no_freeze_not_bare
- str = S("foo")
+ str = @cls.new("foo")
assert_instance_of(@cls, -str)
assert_equal(false, str.frozen?)
- str = S("foo")
+ 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 = S("foo")
+ str = @cls.new("foo")
assert_instance_of(@cls, -str)
assert_equal(false, str.frozen?)
end
def test_ord
- assert_equal(97, S("a").ord)
- assert_equal(97, S("abc").ord)
- assert_equal(0x3042, S("\u3042\u3043").ord)
- assert_raise(ArgumentError) { S("").ord }
+ assert_equal(97, "a".ord)
+ assert_equal(97, "abc".ord)
+ assert_equal(0x3042, "\u3042\u3043".ord)
+ assert_raise(ArgumentError) { "".ord }
end
def test_chr
- assert_equal("a", S("abcde").chr)
- assert_equal("a", S("a").chr)
- assert_equal("\u3042", S("\u3042\u3043").chr)
- assert_equal('', S('').chr)
+ assert_equal("a", "abcde".chr)
+ assert_equal("a", "a".chr)
+ assert_equal("\u3042", "\u3042\u3043".chr)
+ assert_equal('', ''.chr)
end
def test_substr_code_range
- data = S("\xff" + "a"*200)
+ data = "\xff" + "a"*200
assert_not_predicate(data, :valid_encoding?)
assert_predicate(data[100..-1], :valid_encoding?)
end
- def test_byteindex
- assert_byteindex(0, S("hello"), ?h)
- assert_byteindex(1, S("hello"), S("ell"))
- assert_byteindex(2, S("hello"), /ll./)
-
- assert_byteindex(3, S("hello"), ?l, 3)
- assert_byteindex(3, S("hello"), S("l"), 3)
- assert_byteindex(3, S("hello"), /l./, 3)
-
- assert_byteindex(nil, S("hello"), ?z, 3)
- assert_byteindex(nil, S("hello"), S("z"), 3)
- assert_byteindex(nil, S("hello"), /z./, 3)
-
- assert_byteindex(nil, S("hello"), ?z)
- assert_byteindex(nil, S("hello"), S("z"))
- assert_byteindex(nil, S("hello"), /z./)
-
- assert_byteindex(0, S(""), S(""))
- assert_byteindex(0, S(""), //)
- assert_byteindex(nil, S(""), S("hello"))
- assert_byteindex(nil, S(""), /hello/)
- assert_byteindex(0, S("hello"), S(""))
- assert_byteindex(0, S("hello"), //)
-
- s = S("long") * 1000 << "x"
- assert_byteindex(nil, s, S("y"))
- assert_byteindex(4 * 1000, s, S("x"))
- s << "yx"
- assert_byteindex(4 * 1000, s, S("x"))
- assert_byteindex(4 * 1000, s, S("xyx"))
-
- o = Object.new
- def o.to_str; "bar"; end
- assert_byteindex(3, S("foobarbarbaz"), o)
- assert_raise(TypeError) { S("foo").byteindex(Object.new) }
-
- assert_byteindex(nil, S("foo"), //, -100)
- assert_byteindex(nil, S("foo"), //, -4)
-
- assert_byteindex(2, S("abcdbce"), /b\Kc/)
-
- assert_byteindex(0, S("こんにちは"), ?こ)
- assert_byteindex(3, S("こんにちは"), S("んにち"))
- assert_byteindex(6, S("こんにちは"), /にち./)
-
- assert_byteindex(0, S("にんにちは"), ?に, 0)
- assert_raise(IndexError) { S("にんにちは").byteindex(?に, 1) }
- assert_raise(IndexError) { S("にんにちは").byteindex(?に, 5) }
- assert_byteindex(6, S("にんにちは"), ?に, 6)
- assert_byteindex(6, S("にんにちは"), S("に"), 6)
- assert_byteindex(6, S("にんにちは"), /に./, 6)
- assert_raise(IndexError) { S("にんにちは").byteindex(?に, 7) }
-
- s = S("foobarbarbaz")
- assert !1000.times.any? {s.byteindex("", 100_000_000)}
- end
-
- def test_byterindex
- assert_byterindex(3, S("hello"), ?l)
- assert_byterindex(6, S("ell, hello"), S("ell"))
- assert_byterindex(7, S("ell, hello"), /ll./)
-
- assert_byterindex(3, S("hello,lo"), ?l, 3)
- assert_byterindex(3, S("hello,lo"), S("l"), 3)
- assert_byterindex(3, S("hello,lo"), /l./, 3)
-
- assert_byterindex(nil, S("hello"), ?z, 3)
- assert_byterindex(nil, S("hello"), S("z"), 3)
- assert_byterindex(nil, S("hello"), /z./, 3)
-
- assert_byterindex(nil, S("hello"), ?z)
- assert_byterindex(nil, S("hello"), S("z"))
- assert_byterindex(nil, S("hello"), /z./)
-
- assert_byterindex(5, S("hello"), S(""))
- assert_byterindex(5, S("hello"), S(""), 5)
- assert_byterindex(4, S("hello"), S(""), 4)
- assert_byterindex(0, S("hello"), S(""), 0)
-
- o = Object.new
- def o.to_str; "bar"; end
- assert_byterindex(6, S("foobarbarbaz"), o)
- assert_raise(TypeError) { S("foo").byterindex(Object.new) }
-
- assert_byterindex(nil, S("foo"), //, -100)
-
- m = assert_byterindex(3, S("foo"), //)
- assert_equal([3, 3], m.offset(0))
- assert_byterindex(3, S("foo"), //, 4)
-
- assert_byterindex(5, S("abcdbce"), /b\Kc/)
-
- assert_byterindex(6, S("こんにちは"), ?に)
- assert_byterindex(18, S("にちは、こんにちは"), S("にちは"))
- assert_byterindex(18, S("にちは、こんにちは"), /にち./)
-
- assert_raise(IndexError) { S("にちは、こんにちは").byterindex(S("にちは"), 19) }
- assert_raise(IndexError) { S("にちは、こんにちは").byterindex(S("にちは"), -2) }
- assert_byterindex(18, S("にちは、こんにちは"), S("にちは"), 18)
- assert_byterindex(18, S("にちは、こんにちは"), S("にちは"), -3)
- assert_raise(IndexError) { S("にちは、こんにちは").byterindex(S("にちは"), 17) }
- assert_raise(IndexError) { S("にちは、こんにちは").byterindex(S("にちは"), -4) }
- assert_raise(IndexError) { S("にちは、こんにちは").byterindex(S("にちは"), 1) }
- assert_byterindex(0, S("にちは、こんにちは"), S("にちは"), 0)
-
- assert_byterindex(0, S("こんにちは"), S("こんにちは"))
- assert_byterindex(nil, S("こんにち"), S("こんにちは"))
- assert_byterindex(nil, S("こ"), S("こんにちは"))
- assert_byterindex(nil, S(""), S("こんにちは"))
- end
-
- def test_bytesplice
- assert_bytesplice_raise(IndexError, S("hello"), -6, 0, "bye")
- assert_bytesplice_result("byehello", S("hello"), -5, 0, "bye")
- assert_bytesplice_result("byehello", S("hello"), 0, 0, "bye")
- assert_bytesplice_result("byeello", S("hello"), 0, 1, "bye")
- assert_bytesplice_result("bye", S("hello"), 0, 5, "bye")
- assert_bytesplice_result("bye", S("hello"), 0, 6, "bye")
-
- assert_bytesplice_raise(IndexError, S("hello"), -5, 0, "bye", -4, 0)
- assert_bytesplice_result("byehello", S("hello"), 0, 0, "bye", 0, 3)
- assert_bytesplice_result("yehello", S("hello"), 0, 0, "bye", 1, 3)
- assert_bytesplice_result("yehello", S("hello"), 0, 0, "bye", 1, 2)
- assert_bytesplice_result("ehello", S("hello"), 0, 0, "bye", 2, 1)
- assert_bytesplice_result("hello", S("hello"), 0, 0, "bye", 3, 0)
- assert_bytesplice_result("hello", s = S("hello"), 0, 5, s, 0, 5)
- assert_bytesplice_result("elloo", s = S("hello"), 0, 4, s, 1, 4)
- assert_bytesplice_result("llolo", s = S("hello"), 0, 3, s, 2, 3)
- assert_bytesplice_result("lollo", s = S("hello"), 0, 2, s, 3, 2)
- assert_bytesplice_result("oello", s = S("hello"), 0, 1, s, 4, 1)
- assert_bytesplice_result("hhell", s = S("hello"), 1, 4, s, 0, 4)
- assert_bytesplice_result("hehel", s = S("hello"), 2, 3, s, 0, 3)
- assert_bytesplice_result("helhe", s = S("hello"), 3, 2, s, 0, 2)
- assert_bytesplice_result("hellh", s = S("hello"), 4, 1, s, 0, 1)
-
- assert_bytesplice_raise(RangeError, S("hello"), -6...-6, "bye")
- assert_bytesplice_result("byehello", S("hello"), -5...-5, "bye")
- assert_bytesplice_result("byehello", S("hello"), 0...0, "bye")
- assert_bytesplice_result("byeello", S("hello"), 0..0, "bye")
- assert_bytesplice_result("byeello", S("hello"), 0...1, "bye")
- assert_bytesplice_result("byello", S("hello"), 0..1, "bye")
- assert_bytesplice_result("bye", S("hello"), 0..-1, "bye")
- assert_bytesplice_result("bye", S("hello"), 0...5, "bye")
- assert_bytesplice_result("bye", S("hello"), 0...6, "bye")
- assert_bytesplice_result("llolo", s = S("hello"), 0..2, s, 2..4)
-
- assert_bytesplice_raise(RangeError, S("hello"), -5...-5, "bye", -6...-6)
- assert_bytesplice_result("byehello", S("hello"), -5...-5, "bye", 0..-1)
- assert_bytesplice_result("byehello", S("hello"), 0...0, "bye", 0..-1)
- assert_bytesplice_result("bhello", S("hello"), 0...0, "bye", 0..0)
- assert_bytesplice_result("byhello", S("hello"), 0...0, "bye", 0..1)
- assert_bytesplice_result("byehello", S("hello"), 0...0, "bye", 0..2)
- assert_bytesplice_result("yehello", S("hello"), 0...0, "bye", 1..2)
-
- assert_bytesplice_raise(TypeError, S("hello"), 0, "bye")
-
- assert_bytesplice_raise(IndexError, S("こんにちは"), -16, 0, "bye")
- assert_bytesplice_result("byeこんにちは", S("こんにちは"), -15, 0, "bye")
- assert_bytesplice_result("byeこんにちは", S("こんにちは"), 0, 0, "bye")
- assert_bytesplice_raise(IndexError, S("こんにちは"), 1, 0, "bye")
- assert_bytesplice_raise(IndexError, S("こんにちは"), 0, 1, "bye")
- assert_bytesplice_raise(IndexError, S("こんにちは"), 0, 2, "bye")
- assert_bytesplice_result("byeんにちは", S("こんにちは"), 0, 3, "bye")
- assert_bytesplice_result("こんにちはbye", S("こんにちは"), 15, 0, "bye")
-
- assert_bytesplice_raise(IndexError, S("こんにちは"), 0, 0, "さようなら", -16, 0)
- assert_bytesplice_result("こんにちはさようなら", S("こんにちは"), 15, 0, "さようなら", 0, 15)
- assert_bytesplice_result("さようなら", S("こんにちは"), 0, 15, "さようなら", 0, 15)
- assert_bytesplice_result("さんにちは", S("こんにちは"), 0, 3, "さようなら", 0, 3)
- assert_bytesplice_result("さようちは", S("こんにちは"), 0, 9, "さようなら", 0, 9)
- assert_bytesplice_result("ようなちは", S("こんにちは"), 0, 9, "さようなら", 3, 9)
- assert_bytesplice_result("ようちは", S("こんにちは"), 0, 9, "さようなら", 3, 6)
- assert_bytesplice_result("ようならちは", S("こんにちは"), 0, 9, "さようなら", 3, 12)
- assert_bytesplice_raise(IndexError, S("こんにちは"), 0, 15, "さようなら", -16, 0)
- assert_bytesplice_raise(IndexError, S("こんにちは"), 0, 15, "さようなら", 1, 0)
- assert_bytesplice_raise(IndexError, S("こんにちは"), 0, 15, "さようなら", 2, 0)
- assert_bytesplice_raise(IndexError, S("こんにちは"), 0, 15, "さようなら", 0, 1)
- assert_bytesplice_raise(IndexError, S("こんにちは"), 0, 15, "さようなら", 0, 2)
- assert_bytesplice_result("にちはちは", s = S("こんにちは"), 0, 9, s, 6, 9)
-
- assert_bytesplice_result("", S(""), 0, 0, "")
- assert_bytesplice_result("xxx", S(""), 0, 0, "xxx")
-
- assert_bytesplice_raise(ArgumentError, S("hello"), 0, 5, "bye", 0)
- assert_bytesplice_raise(ArgumentError, S("hello"), 0, 5, "bye", 0..-1)
- assert_bytesplice_raise(ArgumentError, S("hello"), 0..-1, "bye", 0, 3)
- end
-
- private
-
- def assert_bytesplice_result(expected, s, *args)
- assert_equal(expected, s.send(:bytesplice, *args))
- assert_equal(expected, s)
- end
-
- def assert_bytesplice_raise(e, s, *args)
- assert_raise(e) { s.send(:bytesplice, *args) }
- end
-
- def assert_index_like(method, expected, string, match, *rest)
- message = "#{method} with string does not affect $~"
- /.*/ =~ message
- md_before = $~
- assert_equal(expected, string.__send__(method, match, *rest))
- md_after = $~
- case match
- when Regexp
- if expected
- assert_not_nil(md_after)
- assert_not_same(md_before, md_after)
- else
- assert_nil(md_after)
- end
- else
- assert_same(md_before, md_after)
- end
- md_after
- end
-
- def assert_index(expected, string, match, *rest)
- assert_index_like(:index, expected, string, match, *rest)
- end
-
- def assert_rindex(expected, string, match, *rest)
- assert_index_like(:rindex, expected, string, match, *rest)
- end
-
- def assert_byteindex(expected, string, match, *rest)
- assert_index_like(:byteindex, expected, string, match, *rest)
- end
-
- def assert_byterindex(expected, string, match, *rest)
- assert_index_like(:byterindex, expected, string, match, *rest)
+ def test_slice_bang_code_range
+ str = "[Bug #19739] ABC OÜ"
+ str.slice!(/ oü$/i)
+ assert_predicate str, :ascii_only?
end
end
diff --git a/test/ruby/test_string_memory.rb b/test/ruby/test_string_memory.rb
deleted file mode 100644
index 3b4694f36f..0000000000
--- a/test/ruby/test_string_memory.rb
+++ /dev/null
@@ -1,55 +0,0 @@
-# frozen_string_literal: false
-require 'test/unit'
-require 'objspace'
-
-class TestStringMemory < Test::Unit::TestCase
- def capture_allocations(klass)
- allocations = []
-
- GC.start
- GC.disable
- generation = GC.count
-
- ObjectSpace.trace_object_allocations do
- yield
-
- ObjectSpace.each_object(klass) do |instance|
- allocations << instance if ObjectSpace.allocation_generation(instance) == generation
- end
- end
-
- return allocations
- ensure
- GC.enable
- end
-
- def test_byteslice_prefix
- string = ("a" * 100_000).freeze
-
- allocations = capture_allocations(String) do
- string.byteslice(0, 50_000)
- end
-
- assert_equal 1, allocations.size
- end
-
- def test_byteslice_postfix
- string = ("a" * 100_000).freeze
-
- allocations = capture_allocations(String) do
- string.byteslice(50_000, 100_000)
- end
-
- assert_equal 1, allocations.size
- end
-
- def test_byteslice_postfix_twice
- string = ("a" * 100_000).freeze
-
- allocations = capture_allocations(String) do
- string.byteslice(50_000, 100_000).byteslice(25_000, 50_000)
- end
-
- assert_equal 2, allocations.size
- end
-end
diff --git a/test/ruby/test_struct.rb b/test/ruby/test_struct.rb
index 3d727adf04..176e2ac5de 100644
--- a/test/ruby/test_struct.rb
+++ b/test/ruby/test_struct.rb
@@ -41,14 +41,6 @@ module TestStruct
end
end
- def test_larger_than_largest_pool
- count = (GC::INTERNAL_CONSTANTS[:RVARGC_MAX_ALLOCATE_SIZE] / RbConfig::SIZEOF["void*"]) + 1
- list = Array(0..count)
- klass = @Struct.new(*list.map { |i| :"a_#{i}"})
- struct = klass.new(*list)
- assert_equal 0, struct.a_0
- end
-
def test_small_structs
names = [:a, :b, :c, :d]
1.upto(4) {|n|
@@ -108,9 +100,8 @@ module TestStruct
assert_equal([:utime, :stime, :cutime, :cstime], Process.times.members)
end
- def test_struct_new_with_hash
- assert_raise_with_message(TypeError, /not a symbol/) {Struct.new(:a, {})}
- assert_raise_with_message(TypeError, /not a symbol/) {Struct.new(:a, {name: "b"})}
+ def test_struct_new_with_empty_hash
+ assert_equal({:a=>1}, Struct.new(:a, {}).new({:a=>1}).a)
end
def test_struct_new_with_keyword_init
@@ -371,8 +362,9 @@ module TestStruct
end
def test_keyword_args_warning
- assert_warn('') { assert_equal(1, @Struct.new(:a).new(a: 1).a) }
- assert_warn('') { assert_equal(1, @Struct.new(:a, keyword_init: nil).new(a: 1).a) }
+ warning = /warning: Passing only keyword arguments to Struct#initialize will behave differently from Ruby 3\.2\./
+ assert_warn(warning) { assert_equal({a: 1}, @Struct.new(:a).new(a: 1).a) }
+ assert_warn(warning) { assert_equal({a: 1}, @Struct.new(:a, keyword_init: nil).new(a: 1).a) }
assert_warn('') { assert_equal({a: 1}, @Struct.new(:a).new({a: 1}).a) }
assert_warn('') { assert_equal({a: 1}, @Struct.new(:a, :b).new(1, a: 1).b) }
assert_warn('') { assert_equal(1, @Struct.new(:a, keyword_init: true).new(a: 1).a) }
@@ -534,20 +526,6 @@ module TestStruct
assert_equal [[:req, :_]], klass.instance_method(:c=).parameters
end
- def test_named_structs_are_not_rooted
- # [Bug #20311]
- assert_no_memory_leak([], <<~PREP, <<~CODE, rss: true)
- code = proc do
- Struct.new("A")
- Struct.send(:remove_const, :A)
- end
-
- 1_000.times(&code)
- PREP
- 50_000.times(&code)
- CODE
- end
-
class TopStruct < Test::Unit::TestCase
include TestStruct
diff --git a/test/ruby/test_super.rb b/test/ruby/test_super.rb
index ce78e66c52..6a575b88c5 100644
--- a/test/ruby/test_super.rb
+++ b/test/ruby/test_super.rb
@@ -558,18 +558,6 @@ class TestSuper < Test::Unit::TestCase
end
end
- def test_zsuper_kw_splat_not_mutable
- extend(Module.new{def a(**k) k[:a] = 1 end})
- extend(Module.new do
- def a(**k)
- before = k.dup
- super
- [before, k]
- end
- end)
- assert_equal(*a)
- end
-
def test_from_eval
bug10263 = '[ruby-core:65122] [Bug #10263a]'
a = Class.new do
diff --git a/test/ruby/test_symbol.rb b/test/ruby/test_symbol.rb
index 7f75ecd90e..f7f17b8d67 100644
--- a/test/ruby/test_symbol.rb
+++ b/test/ruby/test_symbol.rb
@@ -36,19 +36,6 @@ class TestSymbol < Test::Unit::TestCase
assert_eval_inspected(:"@@1", false)
assert_eval_inspected(:"@", false)
assert_eval_inspected(:"@@", false)
- assert_eval_inspected(:"[]=")
- assert_eval_inspected(:"[][]", false)
- assert_eval_inspected(:"[][]=", false)
- assert_eval_inspected(:"@=", false)
- assert_eval_inspected(:"@@=", false)
- assert_eval_inspected(:"@x=", false)
- assert_eval_inspected(:"@@x=", false)
- assert_eval_inspected(:"$$=", false)
- assert_eval_inspected(:"$==", false)
- assert_eval_inspected(:"$x=", false)
- assert_eval_inspected(:"$$$=", false)
- assert_eval_inspected(:"foo?=", false)
- assert_eval_inspected(:"foo!=", false)
end
def assert_inspect_evaled(n)
@@ -118,12 +105,6 @@ class TestSymbol < Test::Unit::TestCase
end
end
- def test_inspect_under_gc_compact_stress
- EnvUtil.under_gc_compact_stress do
- assert_inspect_evaled(':testing')
- end
- end
-
def test_name
assert_equal("foo", :foo.name)
assert_same(:foo.name, :foo.name)
diff --git a/test/ruby/test_syntax.rb b/test/ruby/test_syntax.rb
index 2d4ce59b39..53036cab3b 100644
--- a/test/ruby/test_syntax.rb
+++ b/test/ruby/test_syntax.rb
@@ -13,7 +13,8 @@ class TestSyntax < Test::Unit::TestCase
def assert_syntax_files(test)
srcdir = File.expand_path("../../..", __FILE__)
srcdir = File.join(srcdir, test)
- assert_separately(%W[- #{srcdir}], __FILE__, __LINE__, <<-'eom', timeout: Float::INFINITY)
+ assert_separately(%W[--disable-gem - #{srcdir}],
+ __FILE__, __LINE__, <<-'eom', timeout: Float::INFINITY)
dir = ARGV.shift
for script in Dir["#{dir}/**/*.rb"].sort
assert_valid_syntax(IO::read(script), script)
@@ -76,122 +77,70 @@ class TestSyntax < Test::Unit::TestCase
def test_anonymous_block_forwarding
assert_syntax_error("def b; c(&); end", /no anonymous block parameter/)
- assert_syntax_error("def b(&) ->(&) {c(&)} end", /anonymous block parameter is also used/)
- assert_valid_syntax("def b(&) ->() {c(&)} end")
assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
begin;
- def b(&); c(&) end
- def c(&); yield 1 end
- a = nil
- b{|c| a = c}
- assert_equal(1, a)
-
- def inner
- yield
- end
-
- def block_only(&)
- inner(&)
- end
- assert_equal(1, block_only{1})
-
- def pos(arg1, &)
- inner(&)
- end
- assert_equal(2, pos(nil){2})
+ def b(&); c(&) end
+ def c(&); yield 1 end
+ a = nil
+ b{|c| a = c}
+ assert_equal(1, a)
+
+ def inner
+ yield
+ end
- def pos_kwrest(arg1, **kw, &)
- inner(&)
- end
- assert_equal(3, pos_kwrest(nil){3})
+ def block_only(&)
+ inner(&)
+ end
+ assert_equal(1, block_only{1})
- def no_kw(arg1, **nil, &)
- inner(&)
- end
- assert_equal(4, no_kw(nil){4})
+ def pos(arg1, &)
+ inner(&)
+ end
+ assert_equal(2, pos(nil){2})
- def rest_kw(*a, kwarg: 1, &)
- inner(&)
- end
- assert_equal(5, rest_kw{5})
+ def pos_kwrest(arg1, **kw, &)
+ inner(&)
+ end
+ assert_equal(3, pos_kwrest(nil){3})
- def kw(kwarg:1, &)
- inner(&)
- end
- assert_equal(6, kw{6})
+ def no_kw(arg1, **nil, &)
+ inner(&)
+ end
+ assert_equal(4, no_kw(nil){4})
- def pos_kw_kwrest(arg1, kwarg:1, **kw, &)
- inner(&)
- end
- assert_equal(7, pos_kw_kwrest(nil){7})
+ def rest_kw(*a, kwarg: 1, &)
+ inner(&)
+ end
+ assert_equal(5, rest_kw{5})
- def pos_rkw(arg1, kwarg1:, &)
- inner(&)
- end
- assert_equal(8, pos_rkw(nil, kwarg1: nil){8})
+ def kw(kwarg:1, &)
+ inner(&)
+ end
+ assert_equal(6, kw{6})
- def all(arg1, arg2, *rest, post1, post2, kw1: 1, kw2: 2, okw1:, okw2:, &)
- inner(&)
- end
- assert_equal(9, all(nil, nil, nil, nil, okw1: nil, okw2: nil){9})
+ def pos_kw_kwrest(arg1, kwarg:1, **kw, &)
+ inner(&)
+ end
+ assert_equal(7, pos_kw_kwrest(nil){7})
- def all_kwrest(arg1, arg2, *rest, post1, post2, kw1: 1, kw2: 2, okw1:, okw2:, **kw, &)
- inner(&)
- end
- assert_equal(10, all_kwrest(nil, nil, nil, nil, okw1: nil, okw2: nil){10})
- end;
- end
+ def pos_rkw(arg1, kwarg1:, &)
+ inner(&)
+ end
+ assert_equal(8, pos_rkw(nil, kwarg1: nil){8})
- def test_anonymous_rest_forwarding
- assert_syntax_error("def b; c(*); end", /no anonymous rest parameter/)
- assert_syntax_error("def b; c(1, *); end", /no anonymous rest parameter/)
- assert_syntax_error("def b(*) ->(*) {c(*)} end", /anonymous rest parameter is also used/)
- assert_syntax_error("def b(a, *) ->(*) {c(1, *)} end", /anonymous rest parameter is also used/)
- assert_syntax_error("def b(*) ->(a, *) {c(*)} end", /anonymous rest parameter is also used/)
- assert_valid_syntax("def b(*) ->() {c(*)} end")
- assert_valid_syntax("def b(a, *) ->() {c(1, *)} end")
- assert_valid_syntax("def b(*) ->(a) {c(*)} end")
- assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
- begin;
- def b(*); c(*) end
- def c(*a); a end
- def d(*); b(*, *) end
- assert_equal([1, 2], b(1, 2))
- assert_equal([1, 2, 1, 2], d(1, 2))
- end;
- end
+ def all(arg1, arg2, *rest, post1, post2, kw1: 1, kw2: 2, okw1:, okw2:, &)
+ inner(&)
+ end
+ assert_equal(9, all(nil, nil, nil, nil, okw1: nil, okw2: nil){9})
- def test_anonymous_keyword_rest_forwarding
- assert_syntax_error("def b; c(**); end", /no anonymous keyword rest parameter/)
- assert_syntax_error("def b; c(k: 1, **); end", /no anonymous keyword rest parameter/)
- assert_syntax_error("def b(**) ->(**) {c(**)} end", /anonymous keyword rest parameter is also used/)
- assert_syntax_error("def b(k:, **) ->(**) {c(k: 1, **)} end", /anonymous keyword rest parameter is also used/)
- assert_syntax_error("def b(**) ->(k:, **) {c(**)} end", /anonymous keyword rest parameter is also used/)
- assert_valid_syntax("def b(**) ->() {c(**)} end")
- assert_valid_syntax("def b(k:, **) ->() {c(k: 1, **)} end")
- assert_valid_syntax("def b(**) ->(k:) {c(**)} end")
- assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
- begin;
- def b(**); c(**) end
- def c(**kw); kw end
- def d(**); b(k: 1, **) end
- def e(**); b(**, k: 1) end
- def f(a: nil, **); b(**) end
- assert_equal({a: 1, k: 3}, b(a: 1, k: 3))
- assert_equal({a: 1, k: 3}, d(a: 1, k: 3))
- assert_equal({a: 1, k: 1}, e(a: 1, k: 3))
- assert_equal({k: 3}, f(a: 1, k: 3))
+ def all_kwrest(arg1, arg2, *rest, post1, post2, kw1: 1, kw2: 2, okw1:, okw2:, **kw, &)
+ inner(&)
+ end
+ assert_equal(10, all_kwrest(nil, nil, nil, nil, okw1: nil, okw2: nil){10})
end;
end
- def test_argument_forwarding_with_anon_rest_kwrest_and_block
- assert_syntax_error("def f(*, **, &); g(...); end", /unexpected \.\.\./)
- assert_syntax_error("def f(...); g(*); end", /no anonymous rest parameter/)
- assert_syntax_error("def f(...); g(0, *); end", /no anonymous rest parameter/)
- assert_syntax_error("def f(...); g(**); end", /no anonymous keyword rest parameter/)
- assert_syntax_error("def f(...); g(x: 1, **); end", /no anonymous keyword rest parameter/)
- end
-
def test_newline_in_block_parameters
bug = '[ruby-dev:45292]'
["", "a", "a, b"].product(["", ";x", [";", "x"]]) do |params|
@@ -349,12 +298,6 @@ class TestSyntax < Test::Unit::TestCase
assert_warn(/duplicated/) {r = eval("a.f(**{k: a.add(1), j: a.add(2), k: a.add(3), k: a.add(4)})")}
assert_equal(4, r)
assert_equal([1, 2, 3, 4], a)
- a.clear
- r = nil
- _z = {}
- assert_warn(/duplicated/) {r = eval("a.f(k: a.add(1), **_z, k: a.add(2))")}
- assert_equal(2, r)
- assert_equal([1, 2], a)
end
def test_keyword_empty_splat
@@ -656,8 +599,6 @@ WARN
assert_equal(42, obj.foo(42))
assert_equal(42, obj.foo(2, _: 0))
assert_equal(2, obj.foo(x: 2, _: 0))
- ensure
- self.class.remove_method(:foo)
end
def test_duplicated_opt_kw
@@ -1011,7 +952,7 @@ eom
["p ", ""], # no-pop
["", "p Foo::Bar"], # pop
].each do |p1, p2|
- src = <<~EOM
+ src = <<-EOM.gsub(/^\s*\n/, '')
class Foo
#{"Bar = " + preset if preset}
end
@@ -1043,7 +984,7 @@ eom
["p ", ""], # no-pop
["", "p ::Bar"], # pop
].each do |p1, p2|
- src = <<~EOM
+ src = <<-EOM.gsub(/^\s*\n/, '')
#{"Bar = " + preset if preset}
class Foo
#{p1}::Bar #{op}= 42
@@ -1390,8 +1331,6 @@ eom
begin raise; ensure return; end and self
nil&defined?0--begin e=no_method_error(); return; 0;end
return puts('ignored') #=> ignored
- BEGIN {return}
- END {return if false}
end;
.split(/\n/).map {|s|[(line+=1), *s.split(/#=> /, 2)]}
failed = proc do |n, s|
@@ -1421,54 +1360,6 @@ eom
end
end
- def test_eval_return_toplevel
- feature4840 = '[ruby-core:36785] [Feature #4840]'
- line = __LINE__+2
- code = "#{<<~"begin;"}#{<<~'end;'}"
- begin;
- eval "return"; raise
- begin eval "return"; rescue SystemExit; exit false; end
- begin eval "return"; ensure puts "ensured"; end #=> ensured
- begin ensure eval "return"; end
- begin raise; ensure; eval "return"; end
- begin raise; rescue; eval "return"; end
- eval "return false"; raise
- eval "return 1"; raise
- "#{eval "return"}"
- raise((eval "return"; "should not raise"))
- begin raise; ensure eval "return"; end; self
- begin raise; ensure eval "return"; end and self
- eval "return puts('ignored')" #=> ignored
- BEGIN {eval "return"}
- end;
- .split(/\n/).map {|s|[(line+=1), *s.split(/#=> /, 2)]}
- failed = proc do |n, s|
- RubyVM::InstructionSequence.compile(s, __FILE__, nil, n).disasm
- end
- Tempfile.create(%w"test_return_ .rb") do |lib|
- lib.close
- args = %W[-W0 -r#{lib.path}]
- all_assertions_foreach(feature4840, *[:main, :lib].product([:class, :top], code)) do |main, klass, (n, s, *ex)|
- if klass == :class
- s = "class X; #{s}; end"
- if main == :main
- assert_in_out_err(%[-W0], s, ex, /return/, proc {failed[n, s]}, success: false)
- else
- File.write(lib, s)
- assert_in_out_err(args, "", ex, /return/, proc {failed[n, s]}, success: false)
- end
- else
- if main == :main
- assert_in_out_err(%[-W0], s, ex, [], proc {failed[n, s]}, success: true)
- else
- File.write(lib, s)
- assert_in_out_err(args, "", ex, [], proc {failed[n, s]}, success: true)
- end
- end
- end
- end
- end
-
def test_return_toplevel_with_argument
assert_warn(/argument of top-level return is ignored/) {eval("return 1")}
end
@@ -1477,20 +1368,6 @@ eom
assert_in_out_err(['-e', 'class TestSyntax; proc{ return }.call; end'], "", [], /^-e:1:.*unexpected return \(LocalJumpError\)/)
end
- def test_return_in_END
- assert_normal_exit('END {return}')
- end
-
- def test_return_in_BEGIN_in_eval
- # `BEGIN` in `eval` is allowed, even inside a method, and `return`
- # from that block exits from that method without `LocalJumpError`.
- obj = Object.new
- def obj.ok
- eval("BEGIN {return :ok}")
- end
- assert_equal :ok, assert_nothing_raised(LocalJumpError) {obj.ok}
- end
-
def test_syntax_error_in_rescue
bug12613 = '[ruby-core:76531] [Bug #12613]'
assert_syntax_error("#{<<-"begin;"}\n#{<<-"end;"}", /Invalid retry/, bug12613)
@@ -1710,29 +1587,6 @@ eom
def test_command_with_cmd_brace_block
assert_valid_syntax('obj.foo (1) {}')
assert_valid_syntax('obj::foo (1) {}')
- assert_valid_syntax('bar {}')
- assert_valid_syntax('Bar {}')
- assert_valid_syntax('bar() {}')
- assert_valid_syntax('Bar() {}')
- assert_valid_syntax('Foo::bar {}')
- assert_valid_syntax('Foo::Bar {}')
- assert_valid_syntax('Foo::bar() {}')
- assert_valid_syntax('Foo::Bar() {}')
- end
-
- def test_command_newline_in_tlparen_args
- assert_valid_syntax("p (1\n2\n),(3),(4)")
- assert_valid_syntax("p (\n),(),()")
- assert_valid_syntax("a.b (1\n2\n),(3),(4)")
- assert_valid_syntax("a.b (\n),(),()")
- end
-
- def test_command_semicolon_in_tlparen_at_the_first_arg
- bug19281 = '[ruby-core:111499] [Bug #19281]'
- assert_valid_syntax('p (1;2),(3),(4)', bug19281)
- assert_valid_syntax('p (;),(),()', bug19281)
- assert_valid_syntax('a.b (1;2),(3),(4)', bug19281)
- assert_valid_syntax('a.b (;),(),()', bug19281)
end
def test_numbered_parameter
@@ -1778,23 +1632,6 @@ eom
assert_raise(NameError) {eval("_1")},
]
}
-
- assert_valid_syntax("proc {def foo(_);end;_1}")
- assert_valid_syntax("p { [_1 **2] }")
- assert_valid_syntax("proc {_1;def foo();end;_1}")
- end
-
- def test_it
- assert_no_warning(/`it`/) {eval('if false; it; end')}
- assert_no_warning(/`it`/) {eval('def foo; it; end')}
- assert_warn(/`it`/) {eval('0.times { it }')}
- assert_no_warning(/`it`/) {eval('0.times { || it }')}
- assert_no_warning(/`it`/) {eval('0.times { |_n| it }')}
- assert_warn(/`it`/) {eval('0.times { it; it = 1; it }')}
- assert_no_warning(/`it`/) {eval('0.times { it = 1; it }')}
- assert_no_warning(/`it`/) {eval('it = 1; 0.times { it }')}
- ensure
- self.class.remove_method(:foo)
end
def test_value_expr_in_condition
@@ -1805,11 +1642,6 @@ eom
assert_valid_syntax("tap {a = (break unless true)}")
end
- def test_value_expr_in_singleton
- mesg = /void value expression/
- assert_syntax_error("class << (return); end", mesg)
- end
-
def test_tautological_condition
assert_valid_syntax("def f() return if false and invalid; nil end")
assert_valid_syntax("def f() return unless true or invalid; nil end")
@@ -1847,8 +1679,6 @@ eom
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/)
- assert_syntax_error('def foo(*rest, ...) end', '... after rest argument')
- assert_syntax_error('def foo(*, ...) end', '... after rest argument')
obj1 = Object.new
def obj1.bar(*args, **kws, &block)
@@ -2049,21 +1879,6 @@ eom
assert_equal 0...1, exp.call(a: 0)
end
- def test_class_module_Object_ancestors
- assert_separately([], <<-RUBY)
- m = Module.new
- m::Bug18832 = 1
- include m
- class Bug18832; end
- RUBY
- assert_separately([], <<-RUBY)
- m = Module.new
- m::Bug18832 = 1
- include m
- module Bug18832; end
- RUBY
- end
-
def test_cdhash
assert_separately([], <<-RUBY)
n = case 1 when 2r then false else true end
diff --git a/test/ruby/test_system.rb b/test/ruby/test_system.rb
index 3fcdaa6aad..31c9cd7654 100644
--- a/test/ruby/test_system.rb
+++ b/test/ruby/test_system.rb
@@ -146,19 +146,6 @@ class TestSystem < Test::Unit::TestCase
end
end
- def test_system_closed
- assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- ios = []
- ObjectSpace.each_object(IO) {|io| ios << io}
- `echo`
- ObjectSpace.each_object(IO) do |io|
- next if ios.include?(io)
- assert_nothing_raised {io.close}
- end
- end;
- end
-
def test_empty_evstr
assert_equal("", eval('"#{}"', nil, __FILE__, __LINE__), "[ruby-dev:25113]")
end
diff --git a/test/ruby/test_thread.rb b/test/ruby/test_thread.rb
index da14c429e6..41cee124be 100644
--- a/test/ruby/test_thread.rb
+++ b/test/ruby/test_thread.rb
@@ -3,7 +3,6 @@
require 'test/unit'
require "rbconfig/sizeof"
require "timeout"
-require "fiddle"
class TestThread < Test::Unit::TestCase
class Thread < ::Thread
@@ -30,19 +29,13 @@ class TestThread < Test::Unit::TestCase
end
def test_inspect
- m = Thread::Mutex.new
- m.lock
line = __LINE__+1
- th = Module.new {break module_eval("class C\u{30b9 30ec 30c3 30c9} < Thread; self; end")}.start do
- m.synchronize {}
- end
- Thread.pass until th.stop?
+ 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)
ensure
- m.unlock
th.join
end
@@ -324,7 +317,7 @@ class TestThread < Test::Unit::TestCase
s += 1
end
Thread.pass until t.stop?
- sleep 1 if defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled? # t.stop? behaves unexpectedly with --jit-wait
+ sleep 1 if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # t.stop? behaves unexpectedly with --jit-wait
assert_equal(1, s)
t.wakeup
Thread.pass while t.alive?
@@ -396,7 +389,7 @@ class TestThread < Test::Unit::TestCase
end
INPUT
- assert_in_out_err(%w(-d), <<-INPUT, %w(false 2), %r".+")
+ assert_in_out_err(%w(--disable-gems -d), <<-INPUT, %w(false 2), %r".+")
p Thread.abort_on_exception
begin
t = Thread.new { raise }
@@ -507,7 +500,7 @@ class TestThread < Test::Unit::TestCase
def test_ignore_deadlock
if /mswin|mingw/ =~ RUBY_PLATFORM
- omit "can't trap a signal from another process on Windows"
+ skip "can't trap a signal from another process on Windows"
end
assert_in_out_err([], <<-INPUT, %w(false :sig), [], :signal=>:INT, timeout: 1, timeout_error: nil)
p Thread.ignore_deadlock
@@ -738,7 +731,7 @@ class TestThread < Test::Unit::TestCase
end
def test_no_valid_cfp
- omit 'with win32ole, cannot run this testcase because win32ole redefines Thread#initialize' if defined?(WIN32OLE)
+ skip 'with win32ole, cannot run this testcase because win32ole redefines Thread#initialize' if defined?(WIN32OLE)
bug5083 = '[ruby-dev:44208]'
assert_equal([], Thread.new(&Module.method(:nesting)).value, bug5083)
assert_instance_of(Thread, Thread.new(:to_s, &Class.new.method(:undef_method)).join, bug5083)
@@ -973,8 +966,6 @@ _eom
end
def test_thread_timer_and_interrupt
- omit "[Bug #18613]" if /freebsd/ =~ RUBY_PLATFORM
-
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'
@@ -1077,7 +1068,7 @@ q.pop
puts mth.status
Process.kill(:INT, $$)
}
- sleep
+ sleep 0.1
INPUT
end
@@ -1264,7 +1255,6 @@ q.pop
assert_predicate(status, :success?, bug18902)
ensure
th.kill
- th.join
end
end if Process.respond_to?(:fork)
@@ -1280,7 +1270,7 @@ q.pop
end if Process.respond_to?(:fork)
def test_fork_while_parent_locked
- omit 'needs fork' unless Process.respond_to?(:fork)
+ skip 'needs fork' unless Process.respond_to?(:fork)
m = Thread::Mutex.new
nr = 1
thrs = []
@@ -1301,7 +1291,7 @@ q.pop
end
def test_fork_while_mutex_locked_by_forker
- omit 'needs fork' unless Process.respond_to?(:fork)
+ skip 'needs fork' unless Process.respond_to?(:fork)
m = Thread::Mutex.new
m.synchronize do
pid = fork do
@@ -1362,61 +1352,6 @@ q.pop
t.join
end
- def test_yield_across_thread_through_enum
- bug18649 = '[ruby-core:107980] [Bug #18649]'
- @log = []
-
- def self.p(arg)
- @log << arg
- end
-
- def self.synchronize
- yield
- end
-
- def self.execute(task)
- success = true
- value = reason = nil
- end_sync = false
-
- synchronize do
- begin
- p :before
- value = task.call
- p :never_reached
- success = true
- rescue StandardError => ex
- ex = ex.class
- p [:rescue, ex]
- reason = ex
- success = false
- end
-
- end_sync = true
- p :end_sync
- end
-
- p :should_not_reach_here! unless end_sync
- [success, value, reason]
- end
-
- def self.foo
- Thread.new do
- result = execute(-> { yield 42 })
- p [:result, result]
- end.join
- end
-
- value = to_enum(:foo).first
- expected = [:before,
- [:rescue, LocalJumpError],
- :end_sync,
- [:result, [false, nil, LocalJumpError]]]
-
- assert_equal(expected, @log, bug18649)
- assert_equal(42, value, bug18649)
- end
-
def test_thread_setname_in_initialize
bug12290 = '[ruby-core:74963] [Bug #12290]'
c = Class.new(Thread) {def initialize() self.name = "foo"; super; end}
@@ -1424,7 +1359,7 @@ q.pop
end
def test_thread_native_thread_id
- omit "don't support native_thread_id" unless Thread.method_defined?(:native_thread_id)
+ skip "don't support native_thread_id" unless Thread.method_defined?(:native_thread_id)
assert_instance_of Integer, Thread.main.native_thread_id
th1 = Thread.start{sleep}
@@ -1435,8 +1370,7 @@ q.pop
Thread.pass until th1.stop?
# After a thread starts (and execute `sleep`), it returns native_thread_id
- native_tid = th1.native_thread_id
- assert_instance_of Integer, native_tid if native_tid # it can be nil
+ assert_instance_of Integer, th1.native_thread_id
th1.wakeup
Thread.pass while th1.alive?
@@ -1445,40 +1379,11 @@ q.pop
assert_nil th1.native_thread_id
end
- def test_thread_native_thread_id_across_fork_on_linux
- rtld_default = Fiddle.dlopen(nil)
- omit "this test is only for Linux" unless rtld_default.sym_defined?('gettid')
-
- gettid = Fiddle::Function.new(rtld_default['gettid'], [], Fiddle::TYPE_INT)
-
- parent_thread_id = Thread.main.native_thread_id
- real_parent_thread_id = gettid.call
-
- assert_equal real_parent_thread_id, parent_thread_id
-
- child_lines = nil
- IO.popen('-') do |pipe|
- if pipe
- # parent
- child_lines = pipe.read.lines
- else
- # child
- puts Thread.main.native_thread_id
- puts gettid.call
- end
- end
- child_thread_id = child_lines[0].chomp.to_i
- real_child_thread_id = child_lines[1].chomp.to_i
-
- assert_equal real_child_thread_id, child_thread_id
- refute_equal parent_thread_id, child_thread_id
- end
-
def test_thread_interrupt_for_killed_thread
opts = { timeout: 5, timeout_error: nil }
- # prevent SIGABRT from slow shutdown with RJIT
- opts[:reprieve] = 3 if defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled?
+ # prevent SIGABRT from slow shutdown with MJIT
+ opts[:reprieve] = 3 if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?
assert_normal_exit(<<-_end, '[Bug #8996]', **opts)
Thread.report_on_exception = false
@@ -1493,14 +1398,9 @@ q.pop
def test_signal_at_join
if /mswin|mingw/ =~ RUBY_PLATFORM
- omit "can't trap a signal from another process on Windows"
+ skip "can't trap a signal from another process on Windows"
# opt = {new_pgroup: true}
end
-
- if /freebsd/ =~ RUBY_PLATFORM
- omit "[Bug #18613]"
- end
-
assert_separately([], "#{<<~"{#"}\n#{<<~'};'}", timeout: 120)
{#
n = 1000
@@ -1547,12 +1447,4 @@ q.pop
end
};
end
-
- def test_pending_interrupt?
- t = Thread.handle_interrupt(Exception => :never) { Thread.new { Thread.stop } }
- t.raise(StandardError)
- assert_equal(true, t.pending_interrupt?)
- assert_equal(true, t.pending_interrupt?(Exception))
- assert_equal(false, t.pending_interrupt?(ArgumentError))
- end
end
diff --git a/test/ruby/test_thread_cv.rb b/test/ruby/test_thread_cv.rb
index eb88b9606c..88733419da 100644
--- a/test/ruby/test_thread_cv.rb
+++ b/test/ruby/test_thread_cv.rb
@@ -6,6 +6,12 @@ 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 = Thread::Mutex.new
condvar = Thread::ConditionVariable.new
diff --git a/test/ruby/test_thread_queue.rb b/test/ruby/test_thread_queue.rb
index 545bf98888..3fa0eae2c1 100644
--- a/test/ruby/test_thread_queue.rb
+++ b/test/ruby/test_thread_queue.rb
@@ -8,23 +8,14 @@ class TestThreadQueue < Test::Unit::TestCase
SizedQueue = Thread::SizedQueue
def test_queue_initialized
- assert_raise_with_message(TypeError, /\bQueue.* not initialized/) {
+ assert_raise(TypeError) {
Queue.allocate.push(nil)
}
end
def test_sized_queue_initialized
- assert_raise_with_message(TypeError, /\bSizedQueue.* not initialized/) {
- SizedQueue.allocate.push(nil)
- }
- end
-
- def test_freeze
- assert_raise(TypeError) {
- Queue.new.freeze
- }
assert_raise(TypeError) {
- SizedQueue.new(5).freeze
+ SizedQueue.allocate.push(nil)
}
end
@@ -120,23 +111,6 @@ class TestThreadQueue < Test::Unit::TestCase
assert_equal(0, q.num_waiting)
end
- def test_queue_pop_timeout
- q = Thread::Queue.new
- q << 1
- assert_equal 1, q.pop(timeout: 1)
-
- t1 = Thread.new { q.pop(timeout: 1) }
- assert_equal t1, t1.join(2)
- assert_nil t1.value
-
- t2 = Thread.new { q.pop(timeout: 0.1) }
- assert_equal t2, t2.join(1)
- assert_nil t2.value
- ensure
- t1&.kill&.join
- t2&.kill&.join
- end
-
def test_queue_pop_non_block
q = Thread::Queue.new
assert_raise_with_message(ThreadError, /empty/) do
@@ -152,24 +126,6 @@ class TestThreadQueue < Test::Unit::TestCase
assert_equal(0, q.num_waiting)
end
- def test_sized_queue_pop_timeout
- q = Thread::SizedQueue.new(1)
-
- q << 1
- assert_equal 1, q.pop(timeout: 1)
-
- t1 = Thread.new { q.pop(timeout: 1) }
- assert_equal t1, t1.join(2)
- assert_nil t1.value
-
- t2 = Thread.new { q.pop(timeout: 0.1) }
- assert_equal t2, t2.join(1)
- assert_nil t2.value
- ensure
- t1&.kill&.join
- t2&.kill&.join
- end
-
def test_sized_queue_pop_non_block
q = Thread::SizedQueue.new(1)
assert_raise_with_message(ThreadError, /empty/) do
@@ -177,24 +133,6 @@ class TestThreadQueue < Test::Unit::TestCase
end
end
- def test_sized_queue_push_timeout
- q = Thread::SizedQueue.new(1)
-
- q << 1
- assert_equal 1, q.size
-
- t1 = Thread.new { q.push(2, timeout: 1) }
- assert_equal t1, t1.join(2)
- assert_nil t1.value
-
- t2 = Thread.new { q.push(2, timeout: 0.1) }
- assert_equal t2, t2.join(1)
- assert_nil t2.value
- ensure
- t1&.kill&.join
- t2&.kill&.join
- end
-
def test_sized_queue_push_interrupt
q = Thread::SizedQueue.new(1)
q.push(1)
@@ -213,18 +151,16 @@ class TestThreadQueue < Test::Unit::TestCase
end
def test_thr_kill
- omit "[Bug #18613]" if /freebsd/ =~ RUBY_PLATFORM
-
bug5343 = '[ruby-core:39634]'
Dir.mktmpdir {|d|
- timeout = 60
+ timeout = EnvUtil.apply_timeout_scale(60)
total_count = 250
begin
- assert_normal_exit(<<-"_eom", bug5343, timeout: timeout, chdir: d)
- r, w = IO.pipe
+ assert_normal_exit(<<-"_eom", bug5343, **{:timeout => timeout, :chdir=>d})
#{total_count}.times do |i|
- File.open("test_thr_kill_count", "w") {|f| f.puts i }
+ open("test_thr_kill_count", "w") {|f| f.puts i }
queue = Thread::Queue.new
+ r, w = IO.pipe
th = Thread.start {
queue.push(nil)
r.read 1
@@ -594,14 +530,9 @@ class TestThreadQueue < Test::Unit::TestCase
count_items = rand(3000..5000)
count_producers = rand(10..20)
- # ensure threads do not start running too soon and complete before we check status
- mutex = Mutex.new
- mutex.lock
-
producers = count_producers.times.map do
Thread.new do
- mutex.lock
- mutex.unlock
+ sleep(rand / 100)
count_items.times{|i| q << [i,"#{i} for #{Thread.current.inspect}"]}
end
end
@@ -619,11 +550,9 @@ class TestThreadQueue < Test::Unit::TestCase
# 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.to_s =~ /\A(?:run|sleep)\z/}
-
- assert (consumers + producers).all?{|thr| thr.status.to_s =~ /\A(?:run|sleep)\z/}, 'no threads running'
+ Thread.pass until Time.now - t > 10 || (consumers + producers).all?{|thr| thr.status =~ /\A(?:run|sleep)\z/}
- mutex.unlock
+ 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
@@ -651,10 +580,10 @@ class TestThreadQueue < Test::Unit::TestCase
def test_queue_with_trap
if ENV['APPVEYOR'] == 'True' && RUBY_PLATFORM.match?(/mswin/)
- omit 'This test fails too often on AppVeyor vs140'
+ skip 'This test fails too often on AppVeyor vs140'
end
if RUBY_PLATFORM.match?(/mingw/)
- omit 'This test fails too often on MinGW'
+ skip 'This test fails too often on MinGW'
end
assert_in_out_err([], <<-INPUT, %w(INT INT exit), [])
diff --git a/test/ruby/test_time.rb b/test/ruby/test_time.rb
index 2a541bbe8c..36c79273db 100644
--- a/test/ruby/test_time.rb
+++ b/test/ruby/test_time.rb
@@ -58,102 +58,6 @@ class TestTime < Test::Unit::TestCase
assert_equal([0, 0, 0, 2, 1, 2000, 0, 2, false, "UTC"], Time.new(2000, 1, 1, 24, 0, 0, "-00:00").to_a)
end
- def test_new_from_string
- assert_raise(ArgumentError) { Time.new(2021, 1, 1, "+09:99") }
-
- t = Time.utc(2020, 12, 24, 15, 56, 17)
- assert_equal(t, Time.new("2020-12-24T15:56:17Z"))
- assert_equal(t, Time.new("2020-12-25 00:56:17 +09:00"))
- assert_equal(t, Time.new("2020-12-25 00:57:47 +09:01:30"))
- assert_equal(t, Time.new("2020-12-25 00:56:17 +0900"))
- assert_equal(t, Time.new("2020-12-25 00:57:47 +090130"))
- assert_equal(t, Time.new("2020-12-25T00:56:17+09:00"))
- assert_raise_with_message(ArgumentError, /missing sec part/) {
- Time.new("2020-12-25 00:56 +09:00")
- }
- assert_raise_with_message(ArgumentError, /missing min part/) {
- Time.new("2020-12-25 00 +09:00")
- }
-
- assert_equal(Time.new(2021), Time.new("2021"))
- assert_equal(Time.new(2021, 12, 25, in: "+09:00"), Time.new("2021-12-25+09:00"))
- assert_equal(Time.new(2021, 12, 25, in: "+09:00"), Time.new("2021-12-25+09:00", in: "-01:00"))
-
- assert_equal(0.123456r, Time.new("2021-12-25 00:00:00.123456 +09:00").subsec)
- assert_equal(0.123456789r, Time.new("2021-12-25 00:00:00.123456789876 +09:00").subsec)
- assert_equal(0.123r, Time.new("2021-12-25 00:00:00.123456789876 +09:00", precision: 3).subsec)
- assert_equal(0.123456789876r, Time.new("2021-12-25 00:00:00.123456789876 +09:00", precision: nil).subsec)
- assert_raise_with_message(ArgumentError, "subsecond expected after dot: 00:56:17. ") {
- Time.new("2020-12-25 00:56:17. +0900")
- }
- assert_raise_with_message(ArgumentError, /year must be 4 or more/) {
- Time.new("021-12-25 00:00:00.123456 +09:00")
- }
- assert_raise_with_message(ArgumentError, /fraction min is.*56\./) {
- Time.new("2020-12-25 00:56. +0900")
- }
- assert_raise_with_message(ArgumentError, /fraction hour is.*00\./) {
- Time.new("2020-12-25 00. +0900")
- }
- assert_raise_with_message(ArgumentError, /two digits sec.*:017\b/) {
- Time.new("2020-12-25 00:56:017 +0900")
- }
- assert_raise_with_message(ArgumentError, /two digits sec.*:9\b/) {
- Time.new("2020-12-25 00:56:9 +0900")
- }
- assert_raise_with_message(ArgumentError, /sec out of range/) {
- Time.new("2020-12-25 00:56:64 +0900")
- }
- assert_raise_with_message(ArgumentError, /two digits min.*:056\b/) {
- Time.new("2020-12-25 00:056:17 +0900")
- }
- assert_raise_with_message(ArgumentError, /two digits min.*:5\b/) {
- Time.new("2020-12-25 00:5:17 +0900")
- }
- assert_raise_with_message(ArgumentError, /min out of range/) {
- Time.new("2020-12-25 00:64:17 +0900")
- }
- assert_raise_with_message(ArgumentError, /two digits hour.*\b000\b/) {
- Time.new("2020-12-25 000:56:17 +0900")
- }
- assert_raise_with_message(ArgumentError, /two digits hour.*\b0\b/) {
- Time.new("2020-12-25 0:56:17 +0900")
- }
- assert_raise_with_message(ArgumentError, /hour out of range/) {
- Time.new("2020-12-25 33:56:17 +0900")
- }
- assert_raise_with_message(ArgumentError, /two digits mday.*\b025\b/) {
- Time.new("2020-12-025 00:56:17 +0900")
- }
- assert_raise_with_message(ArgumentError, /two digits mday.*\b5\b/) {
- Time.new("2020-12-5 00:56:17 +0900")
- }
- assert_raise_with_message(ArgumentError, /mday out of range/) {
- Time.new("2020-12-33 00:56:17 +0900")
- }
- assert_raise_with_message(ArgumentError, /two digits mon.*\b012\b/) {
- Time.new("2020-012-25 00:56:17 +0900")
- }
- assert_raise_with_message(ArgumentError, /two digits mon.*\b1\b/) {
- Time.new("2020-1-25 00:56:17 +0900")
- }
- assert_raise_with_message(ArgumentError, /mon out of range/) {
- Time.new("2020-17-25 00:56:17 +0900")
- }
- assert_raise_with_message(ArgumentError, /no time information/) {
- Time.new("2020-12")
- }
- assert_raise_with_message(ArgumentError, /no time information/) {
- Time.new("2020-12-02")
- }
- assert_raise_with_message(ArgumentError, /can't parse/) {
- Time.new(" 2020-12-02 00:00:00")
- }
- assert_raise_with_message(ArgumentError, /can't parse/) {
- Time.new("2020-12-02 00:00:00 ")
- }
- end
-
def test_time_add()
assert_equal(Time.utc(2000, 3, 21, 3, 30) + 3 * 3600,
Time.utc(2000, 3, 21, 6, 30))
@@ -215,7 +119,7 @@ class TestTime < Test::Unit::TestCase
assert_equal(946684800, Time.utc(2000, 1, 1, 0, 0, 0).tv_sec)
# Giveup to try 2nd test because some state is changed.
- omit if Test::Unit::Runner.current_repeat_count > 0
+ skip if Test::Unit::Runner.current_repeat_count > 0
assert_equal(0x7fffffff, Time.utc(2038, 1, 19, 3, 14, 7).tv_sec)
assert_equal(0x80000000, Time.utc(2038, 1, 19, 3, 14, 8).tv_sec)
@@ -439,7 +343,7 @@ class TestTime < Test::Unit::TestCase
end
def test_marshal_zone_gc
- assert_separately([], <<-'end;', timeout: 30)
+ assert_separately(%w(--disable-gems), <<-'end;', timeout: 30)
ENV["TZ"] = "JST-9"
s = Marshal.dump(Time.now)
t = Marshal.load(s)
@@ -1282,7 +1186,7 @@ class TestTime < Test::Unit::TestCase
def test_2038
# Giveup to try 2nd test because some state is changed.
- omit if Test::Unit::Runner.current_repeat_count > 0
+ skip if Test::Unit::Runner.current_repeat_count > 0
if no_leap_seconds?
assert_equal(0x80000000, Time.utc(2038, 1, 19, 3, 14, 8).tv_sec)
@@ -1407,41 +1311,21 @@ class TestTime < Test::Unit::TestCase
def test_memsize
# Time objects are common in some code, try to keep them small
- omit "Time object size test" if /^(?:i.?86|x86_64)-linux/ !~ RUBY_PLATFORM
- omit "GC is in debug" if GC::INTERNAL_CONSTANTS[:RVALUE_OVERHEAD] > 0
- omit "memsize is not accurate due to using malloc_usable_size" if GC::INTERNAL_CONSTANTS[:SIZE_POOL_COUNT] == 1
- omit "Only run this test on 64-bit" if RbConfig::SIZEOF["void*"] != 8
-
+ skip "Time object size test" if /^(?:i.?86|x86_64)-linux/ !~ RUBY_PLATFORM
+ skip "GC is in debug" if GC::INTERNAL_CONSTANTS[:DEBUG]
require 'objspace'
t = Time.at(0)
- sizeof_timew =
- if RbConfig::SIZEOF.key?("uint64_t") && RbConfig::SIZEOF["long"] * 2 <= RbConfig::SIZEOF["uint64_t"]
- RbConfig::SIZEOF["uint64_t"]
- else
- RbConfig::SIZEOF["void*"] # Same size as VALUE
- end
- sizeof_vtm = RbConfig::SIZEOF["void*"] * 4 + 8
- expect = GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE] + sizeof_timew + sizeof_vtm
- assert_operator ObjectSpace.memsize_of(t), :<=, expect
+ 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
+ assert_equal expect, ObjectSpace.memsize_of(t)
rescue LoadError => e
- omit "failed to load objspace: #{e.message}"
- end
-
- def test_deconstruct_keys
- t = in_timezone('JST-9') { Time.local(2022, 10, 16, 14, 1, 30, 500) }
- assert_equal(
- {year: 2022, month: 10, day: 16, wday: 0, yday: 289,
- hour: 14, min: 1, sec: 30, subsec: 1/2000r, dst: false, zone: 'JST'},
- t.deconstruct_keys(nil)
- )
-
- assert_equal(
- {year: 2022, month: 10, sec: 30},
- t.deconstruct_keys(%i[year month sec nonexistent])
- )
- end
-
- def test_parse_zero_bigint
- assert_equal 0, Time.new("2020-10-28T16:48:07.000Z").nsec, '[Bug #19390]'
+ skip "failed to load objspace: #{e.message}"
end
end
diff --git a/test/ruby/test_time_tz.rb b/test/ruby/test_time_tz.rb
index f66cd9bec2..26fe680acf 100644
--- a/test/ruby/test_time_tz.rb
+++ b/test/ruby/test_time_tz.rb
@@ -115,7 +115,7 @@ class TestTimeTZ < Test::Unit::TestCase
t = with_tz("America/Los_Angeles") {
Time.local(2000, 1, 1)
}
- omit "force_tz_test is false on this environment" unless t
+ skip "force_tz_test is false on this environment" unless t
z1 = t.zone
z2 = with_tz(tz="Asia/Singapore") {
t.localtime.zone
@@ -695,13 +695,6 @@ module TestTimeTZ::WithTZ
assert_equal(t.dst?, t2.dst?)
end
- def subtest_fractional_second(time_class, tz, tzarg, tzname, abbr, utc_offset)
- t = time_class.new(2024, 1, 1, 23, 59, 59.9r, tzarg)
- assert_equal(utc_offset[t.dst? ? 1 : 0], t.utc_offset)
- t = time_class.new(2024, 7, 1, 23, 59, 59.9r, tzarg)
- assert_equal(utc_offset[t.dst? ? 1 : 0], t.utc_offset)
- end
-
def test_invalid_zone
make_timezone("INVALID", "INV", 0)
rescue => e
@@ -726,7 +719,6 @@ module TestTimeTZ::WithTZ
"Asia/Tokyo" => ["JST", +9*3600],
"America/Los_Angeles" => ["PST", -8*3600, "PDT", -7*3600],
"Africa/Ndjamena" => ["WAT", +1*3600],
- "Etc/UTC" => ["UTC", 0],
}
def make_timezone(tzname, abbr, utc_offset, abbr2 = nil, utc_offset2 = nil)
diff --git a/test/ruby/test_transcode.rb b/test/ruby/test_transcode.rb
index 4b63263aae..c8b0034e06 100644
--- a/test/ruby/test_transcode.rb
+++ b/test/ruby/test_transcode.rb
@@ -10,9 +10,9 @@ class TestTranscode < Test::Unit::TestCase
assert_raise(Encoding::ConverterNotFoundError) { 'abc'.encode!('foo', 'bar') }
assert_raise(Encoding::ConverterNotFoundError) { 'abc'.force_encoding('utf-8').encode('foo') }
assert_raise(Encoding::ConverterNotFoundError) { 'abc'.force_encoding('utf-8').encode!('foo') }
- assert_undefined_in("\x80", 'ASCII-8BIT')
- assert_invalid_in("\x80", 'US-ASCII')
- assert_undefined_in("\xA5", 'iso-8859-3')
+ assert_raise(Encoding::UndefinedConversionError) { "\x80".encode('utf-8','ASCII-8BIT') }
+ assert_raise(Encoding::InvalidByteSequenceError) { "\x80".encode('utf-8','US-ASCII') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA5".encode('utf-8','iso-8859-3') }
assert_raise(FrozenError) { 'hello'.freeze.encode!('iso-8859-1') }
assert_raise(FrozenError) { '\u3053\u3093\u306b\u3061\u306f'.freeze.encode!('iso-8859-1') } # こんにちは
end
@@ -52,6 +52,16 @@ class TestTranscode < Test::Unit::TestCase
assert_equal("\u20AC"*200000, ("\xA4"*200000).encode!('utf-8', 'iso-8859-15'))
end
+ def check_both_ways(utf8, raw, encoding)
+ assert_equal(utf8.force_encoding('utf-8'), raw.encode('utf-8', encoding),utf8.dump+raw.dump)
+ assert_equal(raw.force_encoding(encoding), utf8.encode(encoding, 'utf-8'))
+ end
+
+ def check_both_ways2(str1, enc1, str2, enc2)
+ assert_equal(str1.force_encoding(enc1), str2.encode(enc1, enc2))
+ assert_equal(str2.force_encoding(enc2), str1.encode(enc2, enc1))
+ end
+
def test_encoding_of_ascii_originating_from_binary
binary_string = [0x82, 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20,
0x61, 0x20, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6c, 0x6f,
@@ -178,16 +188,16 @@ class TestTranscode < Test::Unit::TestCase
def test_windows_874
check_both_ways("\u20AC", "\x80", 'windows-874') # €
- assert_undefined_in("\x81", 'windows-874')
- assert_undefined_in("\x84", 'windows-874')
+ assert_raise(Encoding::UndefinedConversionError) { "\x81".encode("utf-8", 'windows-874') }
+ assert_raise(Encoding::UndefinedConversionError) { "\x84".encode("utf-8", 'windows-874') }
check_both_ways("\u2026", "\x85", 'windows-874') # …
- assert_undefined_in("\x86", 'windows-874')
- assert_undefined_in("\x8F", 'windows-874')
- assert_undefined_in("\x90", 'windows-874')
+ assert_raise(Encoding::UndefinedConversionError) { "\x86".encode("utf-8", 'windows-874') }
+ assert_raise(Encoding::UndefinedConversionError) { "\x8F".encode("utf-8", 'windows-874') }
+ assert_raise(Encoding::UndefinedConversionError) { "\x90".encode("utf-8", 'windows-874') }
check_both_ways("\u2018", "\x91", 'windows-874') # ‘
check_both_ways("\u2014", "\x97", 'windows-874') # —
- assert_undefined_in("\x98", 'windows-874')
- assert_undefined_in("\x9F", 'windows-874')
+ assert_raise(Encoding::UndefinedConversionError) { "\x98".encode("utf-8", 'windows-874') }
+ assert_raise(Encoding::UndefinedConversionError) { "\x9F".encode("utf-8", 'windows-874') }
check_both_ways("\u00A0", "\xA0", 'windows-874') # non-breaking space
check_both_ways("\u0E0F", "\xAF", 'windows-874') # ฏ
check_both_ways("\u0E10", "\xB0", 'windows-874') # ฐ
@@ -196,31 +206,31 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u0E2F", "\xCF", 'windows-874') # ฯ
check_both_ways("\u0E30", "\xD0", 'windows-874') # ะ
check_both_ways("\u0E3A", "\xDA", 'windows-874') # ฺ
- assert_undefined_in("\xDB", 'windows-874')
- assert_undefined_in("\xDE", 'windows-874')
+ assert_raise(Encoding::UndefinedConversionError) { "\xDB".encode("utf-8", 'windows-874') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xDE".encode("utf-8", 'windows-874') }
check_both_ways("\u0E3F", "\xDF", 'windows-874') # ฿
check_both_ways("\u0E40", "\xE0", 'windows-874') # เ
check_both_ways("\u0E4F", "\xEF", 'windows-874') # ๏
check_both_ways("\u0E50", "\xF0", 'windows-874') # ๐
check_both_ways("\u0E5B", "\xFB", 'windows-874') # ๛
- assert_undefined_in("\xFC", 'windows-874')
- assert_undefined_in("\xFF", 'windows-874')
+ assert_raise(Encoding::UndefinedConversionError) { "\xFC".encode("utf-8", 'windows-874') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xFF".encode("utf-8", 'windows-874') }
end
def test_windows_1250
check_both_ways("\u20AC", "\x80", 'windows-1250') # €
- assert_undefined_in("\x81", 'windows-1250')
+ assert_raise(Encoding::UndefinedConversionError) { "\x81".encode("utf-8", 'windows-1250') }
check_both_ways("\u201A", "\x82", 'windows-1250') # ‚
- assert_undefined_in("\x83", 'windows-1250')
+ assert_raise(Encoding::UndefinedConversionError) { "\x83".encode("utf-8", 'windows-1250') }
check_both_ways("\u201E", "\x84", 'windows-1250') # „
check_both_ways("\u2021", "\x87", 'windows-1250') # ‡
- assert_undefined_in("\x88", 'windows-1250')
+ assert_raise(Encoding::UndefinedConversionError) { "\x88".encode("utf-8", 'windows-1250') }
check_both_ways("\u2030", "\x89", 'windows-1250') # ‰
check_both_ways("\u0179", "\x8F", 'windows-1250') # Ź
- assert_undefined_in("\x90", 'windows-1250')
+ assert_raise(Encoding::UndefinedConversionError) { "\x90".encode("utf-8", 'windows-1250') }
check_both_ways("\u2018", "\x91", 'windows-1250') # ‘
check_both_ways("\u2014", "\x97", 'windows-1250') # —
- assert_undefined_in("\x98", 'windows-1250')
+ assert_raise(Encoding::UndefinedConversionError) { "\x98".encode("utf-8", 'windows-1250') }
check_both_ways("\u2122", "\x99", 'windows-1250') # ™
check_both_ways("\u00A0", "\xA0", 'windows-1250') # non-breaking space
check_both_ways("\u017B", "\xAF", 'windows-1250') # Ż
@@ -241,7 +251,7 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u20AC", "\x88", 'windows-1251') # €
check_both_ways("\u040F", "\x8F", 'windows-1251') # Џ
check_both_ways("\u0452", "\x90", 'windows-1251') # ђ
- assert_undefined_in("\x98", 'windows-1251')
+ assert_raise(Encoding::UndefinedConversionError) { "\x98".encode("utf-8", 'windows-1251') }
check_both_ways("\u045F", "\x9F", 'windows-1251') # џ
check_both_ways("\u00A0", "\xA0", 'windows-1251') # non-breaking space
check_both_ways("\u0407", "\xAF", 'windows-1251') # Ї
@@ -259,16 +269,16 @@ class TestTranscode < Test::Unit::TestCase
def test_windows_1252
check_both_ways("\u20AC", "\x80", 'windows-1252') # €
- assert_undefined_in("\x81", 'windows-1252')
+ assert_raise(Encoding::UndefinedConversionError) { "\x81".encode("utf-8", 'windows-1252') }
check_both_ways("\u201A", "\x82", 'windows-1252') # ‚
check_both_ways("\u0152", "\x8C", 'windows-1252') # >Œ
- assert_undefined_in("\x8D", 'windows-1252')
+ assert_raise(Encoding::UndefinedConversionError) { "\x8D".encode("utf-8", 'windows-1252') }
check_both_ways("\u017D", "\x8E", 'windows-1252') # Ž
- assert_undefined_in("\x8F", 'windows-1252')
- assert_undefined_in("\x90", 'windows-1252')
+ assert_raise(Encoding::UndefinedConversionError) { "\x8F".encode("utf-8", 'windows-1252') }
+ assert_raise(Encoding::UndefinedConversionError) { "\x90".encode("utf-8", 'windows-1252') }
check_both_ways("\u2018", "\x91", 'windows-1252') #‘
check_both_ways("\u0153", "\x9C", 'windows-1252') # œ
- assert_undefined_in("\x9D", 'windows-1252')
+ assert_raise(Encoding::UndefinedConversionError) { "\x9D".encode("utf-8", 'windows-1252') }
check_both_ways("\u017E", "\x9E", 'windows-1252') # ž
check_both_ways("\u00A0", "\xA0", 'windows-1252') # non-breaking space
check_both_ways("\u00AF", "\xAF", 'windows-1252') # ¯
@@ -286,24 +296,24 @@ class TestTranscode < Test::Unit::TestCase
def test_windows_1253
check_both_ways("\u20AC", "\x80", 'windows-1253') # €
- assert_undefined_in("\x81", 'windows-1253')
+ assert_raise(Encoding::UndefinedConversionError) { "\x81".encode("utf-8", 'windows-1253') }
check_both_ways("\u201A", "\x82", 'windows-1253') # ‚
check_both_ways("\u2021", "\x87", 'windows-1253') # ‡
- assert_undefined_in("\x88", 'windows-1253')
+ assert_raise(Encoding::UndefinedConversionError) { "\x88".encode("utf-8", 'windows-1253') }
check_both_ways("\u2030", "\x89", 'windows-1253') # ‰
- assert_undefined_in("\x8A", 'windows-1253')
+ assert_raise(Encoding::UndefinedConversionError) { "\x8A".encode("utf-8", 'windows-1253') }
check_both_ways("\u2039", "\x8B", 'windows-1253') # ‹
- assert_undefined_in("\x8C", 'windows-1253')
- assert_undefined_in("\x8F", 'windows-1253')
- assert_undefined_in("\x90", 'windows-1253')
+ assert_raise(Encoding::UndefinedConversionError) { "\x8C".encode("utf-8", 'windows-1253') }
+ assert_raise(Encoding::UndefinedConversionError) { "\x8F".encode("utf-8", 'windows-1253') }
+ assert_raise(Encoding::UndefinedConversionError) { "\x90".encode("utf-8", 'windows-1253') }
check_both_ways("\u2018", "\x91", 'windows-1253') # ‘
check_both_ways("\u2014", "\x97", 'windows-1253') # —
- assert_undefined_in("\x98", 'windows-1253')
+ assert_raise(Encoding::UndefinedConversionError) { "\x98".encode("utf-8", 'windows-1253') }
check_both_ways("\u2122", "\x99", 'windows-1253') # ™
- assert_undefined_in("\x9A", 'windows-1253')
+ assert_raise(Encoding::UndefinedConversionError) { "\x9A".encode("utf-8", 'windows-1253') }
check_both_ways("\u203A", "\x9B", 'windows-1253') # ›
- assert_undefined_in("\x9C", 'windows-1253')
- assert_undefined_in("\x9F", 'windows-1253')
+ assert_raise(Encoding::UndefinedConversionError) { "\x9C".encode("utf-8", 'windows-1253') }
+ assert_raise(Encoding::UndefinedConversionError) { "\x9F".encode("utf-8", 'windows-1253') }
check_both_ways("\u00A0", "\xA0", 'windows-1253') # non-breaking space
check_both_ways("\u2015", "\xAF", 'windows-1253') # ―
check_both_ways("\u00B0", "\xB0", 'windows-1253') # °
@@ -312,28 +322,28 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u039F", "\xCF", 'windows-1253') # Ο
check_both_ways("\u03A0", "\xD0", 'windows-1253') # Π
check_both_ways("\u03A1", "\xD1", 'windows-1253') # Ρ
- assert_undefined_in("\xD2", 'windows-1253')
+ assert_raise(Encoding::UndefinedConversionError) { "\xD2".encode("utf-8", 'windows-1253') }
check_both_ways("\u03A3", "\xD3", 'windows-1253') # Σ
check_both_ways("\u03AF", "\xDF", 'windows-1253') # ί
check_both_ways("\u03B0", "\xE0", 'windows-1253') # ΰ
check_both_ways("\u03BF", "\xEF", 'windows-1253') # ο
check_both_ways("\u03C0", "\xF0", 'windows-1253') # π
check_both_ways("\u03CE", "\xFE", 'windows-1253') # ώ
- assert_undefined_in("\xFF", 'windows-1253')
+ assert_raise(Encoding::UndefinedConversionError) { "\xFF".encode("utf-8", 'windows-1253') }
end
def test_windows_1254
check_both_ways("\u20AC", "\x80", 'windows-1254') # €
- assert_undefined_in("\x81", 'windows-1254')
+ assert_raise(Encoding::UndefinedConversionError) { "\x81".encode("utf-8", 'windows-1254') }
check_both_ways("\u201A", "\x82", 'windows-1254') # ‚
check_both_ways("\u0152", "\x8C", 'windows-1254') # Œ
- assert_undefined_in("\x8D", 'windows-1254')
- assert_undefined_in("\x8F", 'windows-1254')
- assert_undefined_in("\x90", 'windows-1254')
+ assert_raise(Encoding::UndefinedConversionError) { "\x8D".encode("utf-8", 'windows-1254') }
+ assert_raise(Encoding::UndefinedConversionError) { "\x8F".encode("utf-8", 'windows-1254') }
+ assert_raise(Encoding::UndefinedConversionError) { "\x90".encode("utf-8", 'windows-1254') }
check_both_ways("\u2018", "\x91", 'windows-1254') # ‘
check_both_ways("\u0153", "\x9C", 'windows-1254') # œ
- assert_undefined_in("\x9D", 'windows-1254')
- assert_undefined_in("\x9E", 'windows-1254')
+ assert_raise(Encoding::UndefinedConversionError) { "\x9D".encode("utf-8", 'windows-1254') }
+ assert_raise(Encoding::UndefinedConversionError) { "\x9E".encode("utf-8", 'windows-1254') }
check_both_ways("\u0178", "\x9F", 'windows-1254') # Ÿ
check_both_ways("\u00A0", "\xA0", 'windows-1254') # non-breaking space
check_both_ways("\u00AF", "\xAF", 'windows-1254') # ¯
@@ -351,20 +361,20 @@ class TestTranscode < Test::Unit::TestCase
def test_windows_1255
check_both_ways("\u20AC", "\x80", 'windows-1255') # €
- assert_undefined_in("\x81", 'windows-1255')
+ assert_raise(Encoding::UndefinedConversionError) { "\x81".encode("utf-8", 'windows-1255') }
check_both_ways("\u201A", "\x82", 'windows-1255') # ‚
check_both_ways("\u2030", "\x89", 'windows-1255') # ‰
- assert_undefined_in("\x8A", 'windows-1255')
+ assert_raise(Encoding::UndefinedConversionError) { "\x8A".encode("utf-8", 'windows-1255') }
check_both_ways("\u2039", "\x8B", 'windows-1255') # ‹
- assert_undefined_in("\x8C", 'windows-1255')
- assert_undefined_in("\x8F", 'windows-1255')
- assert_undefined_in("\x90", 'windows-1255')
+ assert_raise(Encoding::UndefinedConversionError) { "\x8C".encode("utf-8", 'windows-1255') }
+ assert_raise(Encoding::UndefinedConversionError) { "\x8F".encode("utf-8", 'windows-1255') }
+ assert_raise(Encoding::UndefinedConversionError) { "\x90".encode("utf-8", 'windows-1255') }
check_both_ways("\u2018", "\x91", 'windows-1255') # ‘
check_both_ways("\u2122", "\x99", 'windows-1255') # ™
- assert_undefined_in("\x9A", 'windows-1255')
+ assert_raise(Encoding::UndefinedConversionError) { "\x9A".encode("utf-8", 'windows-1255') }
check_both_ways("\u203A", "\x9B", 'windows-1255') # ›
- assert_undefined_in("\x9C", 'windows-1255')
- assert_undefined_in("\x9F", 'windows-1255')
+ assert_raise(Encoding::UndefinedConversionError) { "\x9C".encode("utf-8", 'windows-1255') }
+ assert_raise(Encoding::UndefinedConversionError) { "\x9F".encode("utf-8", 'windows-1255') }
check_both_ways("\u00A0", "\xA0", 'windows-1255') # non-breaking space
check_both_ways("\u00A1", "\xA1", 'windows-1255') # ¡
check_both_ways("\u00D7", "\xAA", 'windows-1255') # ×
@@ -381,17 +391,17 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u05C0", "\xD0", 'windows-1255') # ׀
check_both_ways("\u05F3", "\xD7", 'windows-1255') # ׳
check_both_ways("\u05F4", "\xD8", 'windows-1255') # ״
- assert_undefined_in("\xD9", 'windows-1255')
- assert_undefined_in("\xDF", 'windows-1255')
+ assert_raise(Encoding::UndefinedConversionError) { "\xD9".encode("utf-8", 'windows-1255') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xDF".encode("utf-8", 'windows-1255') }
check_both_ways("\u05D0", "\xE0", 'windows-1255') # א
check_both_ways("\u05DF", "\xEF", 'windows-1255') # ן
check_both_ways("\u05E0", "\xF0", 'windows-1255') # נ
check_both_ways("\u05EA", "\xFA", 'windows-1255') # ת
- assert_undefined_in("\xFB", 'windows-1255')
- assert_undefined_in("\xFC", 'windows-1255')
+ assert_raise(Encoding::UndefinedConversionError) { "\xFB".encode("utf-8", 'windows-1255') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xFC".encode("utf-8", 'windows-1255') }
check_both_ways("\u200E", "\xFD", 'windows-1255') # left-to-right mark
check_both_ways("\u200F", "\xFE", 'windows-1255') # right-to-left mark
- assert_undefined_in("\xFF", 'windows-1255')
+ assert_raise(Encoding::UndefinedConversionError) { "\xFF".encode("utf-8", 'windows-1255') }
end
def test_windows_1256
@@ -419,35 +429,35 @@ class TestTranscode < Test::Unit::TestCase
def test_windows_1257
check_both_ways("\u20AC", "\x80", 'windows-1257') # €
- assert_undefined_in("\x81", 'windows-1257')
+ assert_raise(Encoding::UndefinedConversionError) { "\x81".encode("utf-8", 'windows-1257') }
check_both_ways("\u201A", "\x82", 'windows-1257') # ‚
- assert_undefined_in("\x83", 'windows-1257')
+ assert_raise(Encoding::UndefinedConversionError) { "\x83".encode("utf-8", 'windows-1257') }
check_both_ways("\u201E", "\x84", 'windows-1257') # „
check_both_ways("\u2021", "\x87", 'windows-1257') # ‡
- assert_undefined_in("\x88", 'windows-1257')
+ assert_raise(Encoding::UndefinedConversionError) { "\x88".encode("utf-8", 'windows-1257') }
check_both_ways("\u2030", "\x89", 'windows-1257') # ‰
- assert_undefined_in("\x8A", 'windows-1257')
+ assert_raise(Encoding::UndefinedConversionError) { "\x8A".encode("utf-8", 'windows-1257') }
check_both_ways("\u2039", "\x8B", 'windows-1257') # ‹
- assert_undefined_in("\x8C", 'windows-1257')
+ assert_raise(Encoding::UndefinedConversionError) { "\x8C".encode("utf-8", 'windows-1257') }
check_both_ways("\u00A8", "\x8D", 'windows-1257') # ¨
check_both_ways("\u02C7", "\x8E", 'windows-1257') # ˇ
check_both_ways("\u00B8", "\x8F", 'windows-1257') # ¸
- assert_undefined_in("\x90", 'windows-1257')
+ assert_raise(Encoding::UndefinedConversionError) { "\x90".encode("utf-8", 'windows-1257') }
check_both_ways("\u2018", "\x91", 'windows-1257') # ‘
check_both_ways("\u2014", "\x97", 'windows-1257') # —
- assert_undefined_in("\x98", 'windows-1257')
+ assert_raise(Encoding::UndefinedConversionError) { "\x98".encode("utf-8", 'windows-1257') }
check_both_ways("\u2122", "\x99", 'windows-1257') # ™
- assert_undefined_in("\x9A", 'windows-1257')
+ assert_raise(Encoding::UndefinedConversionError) { "\x9A".encode("utf-8", 'windows-1257') }
check_both_ways("\u203A", "\x9B", 'windows-1257') # ›
- assert_undefined_in("\x9C", 'windows-1257')
+ assert_raise(Encoding::UndefinedConversionError) { "\x9C".encode("utf-8", 'windows-1257') }
check_both_ways("\u00AF", "\x9D", 'windows-1257') # ¯
check_both_ways("\u02DB", "\x9E", 'windows-1257') # ˛
- assert_undefined_in("\x9F", 'windows-1257')
+ assert_raise(Encoding::UndefinedConversionError) { "\x9F".encode("utf-8", 'windows-1257') }
check_both_ways("\u00A0", "\xA0", 'windows-1257') # non-breaking space
- assert_undefined_in("\xA1", 'windows-1257')
+ assert_raise(Encoding::UndefinedConversionError) { "\xA1".encode("utf-8", 'windows-1257') }
check_both_ways("\u00A2", "\xA2", 'windows-1257') # ¢
check_both_ways("\u00A4", "\xA4", 'windows-1257') # ¤
- assert_undefined_in("\xA5", 'windows-1257')
+ assert_raise(Encoding::UndefinedConversionError) { "\xA5".encode("utf-8", 'windows-1257') }
check_both_ways("\u00A6", "\xA6", 'windows-1257') # ¦
check_both_ways("\u00C6", "\xAF", 'windows-1257') # Æ
check_both_ways("\u00B0", "\xB0", 'windows-1257') # °
@@ -482,9 +492,9 @@ class TestTranscode < Test::Unit::TestCase
end
def test_IBM720
- assert_undefined_in("\x80", 'IBM720')
- assert_undefined_in("\x8F", 'IBM720')
- assert_undefined_in("\x90", 'IBM720')
+ assert_raise(Encoding::UndefinedConversionError) { "\x80".encode("utf-8", 'IBM720') }
+ assert_raise(Encoding::UndefinedConversionError) { "\x8F".encode("utf-8", 'IBM720') }
+ assert_raise(Encoding::UndefinedConversionError) { "\x90".encode("utf-8", 'IBM720') }
check_both_ways("\u0627", "\x9F", 'IBM720') # ا
check_both_ways("\u0628", "\xA0", 'IBM720') # ب
check_both_ways("\u00BB", "\xAF", 'IBM720') # »
@@ -570,17 +580,17 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u00A4", "\xCF", 'IBM857') # ¤
check_both_ways("\u00BA", "\xD0", 'IBM857') # º
check_both_ways("\u00C8", "\xD4", 'IBM857') # È
- assert_undefined_in("\xD5", 'IBM857')
+ assert_raise(Encoding::UndefinedConversionError) { "\xD5".encode("utf-8", 'IBM857') }
check_both_ways("\u00CD", "\xD6", 'IBM857') # Í
check_both_ways("\u2580", "\xDF", 'IBM857') # ▀
check_both_ways("\u00D3", "\xE0", 'IBM857') # Ó
check_both_ways("\u00B5", "\xE6", 'IBM857') # µ
- assert_undefined_in("\xE7", 'IBM857')
+ assert_raise(Encoding::UndefinedConversionError) { "\xE7".encode("utf-8", 'IBM857') }
check_both_ways("\u00D7", "\xE8", 'IBM857') # ×
check_both_ways("\u00B4", "\xEF", 'IBM857') # ´
check_both_ways("\u00AD", "\xF0", 'IBM857') # soft hyphen
check_both_ways("\u00B1", "\xF1", 'IBM857') # ±
- assert_undefined_in("\xF2", 'IBM857')
+ assert_raise(Encoding::UndefinedConversionError) { "\xF2".encode("utf-8", 'IBM857') }
check_both_ways("\u00BE", "\xF3", 'IBM857') # ¾
check_both_ways("\u00A0", "\xFF", 'IBM857') # non-breaking space
end
@@ -700,16 +710,16 @@ class TestTranscode < Test::Unit::TestCase
end
def test_IBM869
- assert_undefined_in("\x80", 'IBM869')
- assert_undefined_in("\x85", 'IBM869')
+ assert_raise(Encoding::UndefinedConversionError) { "\x80".encode("utf-8", 'IBM869') }
+ assert_raise(Encoding::UndefinedConversionError) { "\x85".encode("utf-8", 'IBM869') }
check_both_ways("\u0386", "\x86", 'IBM869') # Ά
- assert_undefined_in("\x87", 'IBM869')
+ assert_raise(Encoding::UndefinedConversionError) { "\x87".encode("utf-8", 'IBM869') }
check_both_ways("\u00B7", "\x88", 'IBM869') # ·
check_both_ways("\u0389", "\x8F", 'IBM869') # Ή
check_both_ways("\u038A", "\x90", 'IBM869') # Ί
check_both_ways("\u038C", "\x92", 'IBM869') # Ό
- assert_undefined_in("\x93", 'IBM869')
- assert_undefined_in("\x94", 'IBM869')
+ assert_raise(Encoding::UndefinedConversionError) { "\x93".encode("utf-8", 'IBM869') }
+ assert_raise(Encoding::UndefinedConversionError) { "\x94".encode("utf-8", 'IBM869') }
check_both_ways("\u038E", "\x95", 'IBM869') # Ύ
check_both_ways("\u03AF", "\x9F", 'IBM869') # ί
check_both_ways("\u03CA", "\xA0", 'IBM869') # ϊ
@@ -798,7 +808,7 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u03BF", "\xEF", 'macGreek') # ο
check_both_ways("\u03C0", "\xF0", 'macGreek') # π
check_both_ways("\u03B0", "\xFE", 'macGreek') # ΰ
- assert_undefined_in("\xFF", 'macGreek')
+ assert_raise(Encoding::UndefinedConversionError) { "\xFF".encode("utf-8", 'macGreek') }
end
def test_macIceland
@@ -877,7 +887,7 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u00D4", "\xEF", 'macTurkish') # Ô
#check_both_ways("\uF8FF", "\xF0", 'macTurkish') # Apple logo
check_both_ways("\u00D9", "\xF4", 'macTurkish') # Ù
- assert_undefined_in("\xF5", 'macTurkish')
+ assert_raise(Encoding::UndefinedConversionError) { "\xF5".encode("utf-8", 'macTurkish') }
check_both_ways("\u02C6", "\xF6", 'macTurkish') # ˆ
check_both_ways("\u02C7", "\xFF", 'macTurkish') # ˇ
end
@@ -948,11 +958,11 @@ class TestTranscode < Test::Unit::TestCase
end
def test_TIS_620
- assert_undefined_in("\x80", 'TIS-620')
- assert_undefined_in("\x8F", 'TIS-620')
- assert_undefined_in("\x90", 'TIS-620')
- assert_undefined_in("\x9F", 'TIS-620')
- assert_undefined_in("\xA0", 'TIS-620')
+ assert_raise(Encoding::UndefinedConversionError) { "\x80".encode("utf-8", 'TIS-620') }
+ assert_raise(Encoding::UndefinedConversionError) { "\x8F".encode("utf-8", 'TIS-620') }
+ assert_raise(Encoding::UndefinedConversionError) { "\x90".encode("utf-8", 'TIS-620') }
+ assert_raise(Encoding::UndefinedConversionError) { "\x9F".encode("utf-8", 'TIS-620') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA0".encode("utf-8", 'TIS-620') }
check_both_ways("\u0E01", "\xA1", 'TIS-620') # ก
check_both_ways("\u0E0F", "\xAF", 'TIS-620') # ฏ
check_both_ways("\u0E10", "\xB0", 'TIS-620') # ฐ
@@ -961,15 +971,15 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u0E2F", "\xCF", 'TIS-620') # ฯ
check_both_ways("\u0E30", "\xD0", 'TIS-620') # ะ
check_both_ways("\u0E3A", "\xDA", 'TIS-620') # ฺ
- assert_undefined_in("\xDB", 'TIS-620')
- assert_undefined_in("\xDE", 'TIS-620')
+ assert_raise(Encoding::UndefinedConversionError) { "\xDB".encode("utf-8", 'TIS-620') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xDE".encode("utf-8", 'TIS-620') }
check_both_ways("\u0E3F", "\xDF", 'TIS-620') # ฿
check_both_ways("\u0E40", "\xE0", 'TIS-620') # เ
check_both_ways("\u0E4F", "\xEF", 'TIS-620') # ๏
check_both_ways("\u0E50", "\xF0", 'TIS-620') # ๐
check_both_ways("\u0E5B", "\xFB", 'TIS-620') # ๛
- assert_undefined_in("\xFC", 'TIS-620')
- assert_undefined_in("\xFF", 'TIS-620')
+ assert_raise(Encoding::UndefinedConversionError) { "\xFC".encode("utf-8", 'TIS-620') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xFF".encode("utf-8", 'TIS-620') }
end
def test_CP850
@@ -1172,15 +1182,15 @@ class TestTranscode < Test::Unit::TestCase
expected = "\u{3042}\u{3044}\u{20bb7}"
assert_equal(expected, %w/fffe4230443042d8b7df/.pack("H*").encode("UTF-8","UTF-16"))
check_both_ways(expected, %w/feff30423044d842dfb7/.pack("H*"), "UTF-16")
- assert_invalid_in(%w/feffdfb7/.pack("H*"), "UTF-16")
- assert_invalid_in(%w/fffeb7df/.pack("H*"), "UTF-16")
+ assert_raise(Encoding::InvalidByteSequenceError){%w/feffdfb7/.pack("H*").encode("UTF-8","UTF-16")}
+ assert_raise(Encoding::InvalidByteSequenceError){%w/fffeb7df/.pack("H*").encode("UTF-8","UTF-16")}
end
def test_utf_32_bom
expected = "\u{3042}\u{3044}\u{20bb7}"
assert_equal(expected, %w/fffe00004230000044300000b70b0200/.pack("H*").encode("UTF-8","UTF-32"))
check_both_ways(expected, %w/0000feff000030420000304400020bb7/.pack("H*"), "UTF-32")
- assert_invalid_in(%w/0000feff00110000/.pack("H*"), "UTF-32")
+ assert_raise(Encoding::InvalidByteSequenceError){%w/0000feff00110000/.pack("H*").encode("UTF-8","UTF-32")}
end
def check_utf_32_both_ways(utf8, raw)
@@ -1362,24 +1372,24 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u71FC", "\xE0\x9E", 'shift_jis') # 燼
check_both_ways("\u71F9", "\xE0\x9F", 'shift_jis') # 燹
check_both_ways("\u73F1", "\xE0\xFC", 'shift_jis') # 珱
- assert_undefined_in("\xEF\x40", 'shift_jis')
- assert_undefined_in("\xEF\x7E", 'shift_jis')
- assert_undefined_in("\xEF\x80", 'shift_jis')
- assert_undefined_in("\xEF\x9E", 'shift_jis')
- assert_undefined_in("\xEF\x9F", 'shift_jis')
- assert_undefined_in("\xEF\xFC", 'shift_jis')
- assert_undefined_in("\xF0\x40", 'shift_jis')
- assert_undefined_in("\xF0\x7E", 'shift_jis')
- assert_undefined_in("\xF0\x80", 'shift_jis')
- assert_undefined_in("\xF0\x9E", 'shift_jis')
- assert_undefined_in("\xF0\x9F", 'shift_jis')
- assert_undefined_in("\xF0\xFC", 'shift_jis')
+ assert_raise(Encoding::UndefinedConversionError) { "\xEF\x40".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xEF\x7E".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xEF\x80".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xEF\x9E".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xEF\x9F".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xEF\xFC".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xF0\x40".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xF0\x7E".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xF0\x80".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xF0\x9E".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xF0\x9F".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xF0\xFC".encode("utf-8", 'shift_jis') }
#check_both_ways("\u9ADC", "\xFC\x40", 'shift_jis') # 髜 (IBM extended)
- assert_undefined_in("\xFC\x7E", 'shift_jis')
- assert_undefined_in("\xFC\x80", 'shift_jis')
- assert_undefined_in("\xFC\x9E", 'shift_jis')
- assert_undefined_in("\xFC\x9F", 'shift_jis')
- assert_undefined_in("\xFC\xFC", 'shift_jis')
+ assert_raise(Encoding::UndefinedConversionError) { "\xFC\x7E".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xFC\x80".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xFC\x9E".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xFC\x9F".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xFC\xFC".encode("utf-8", 'shift_jis') }
check_both_ways("\u677E\u672C\u884C\u5F18", "\x8f\xbc\x96\x7b\x8d\x73\x8d\x4f", 'shift_jis') # 松本行弘
check_both_ways("\u9752\u5C71\u5B66\u9662\u5927\u5B66", "\x90\xC2\x8E\x52\x8A\x77\x89\x40\x91\xE5\x8A\x77", 'shift_jis') # 青山学院大学
check_both_ways("\u795E\u6797\u7FA9\u535A", "\x90\x5F\x97\xD1\x8B\x60\x94\x8E", 'shift_jis') # 神林義博
@@ -1399,34 +1409,34 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u00F7", "\xA1\xE0", 'euc-jp') # ÷
check_both_ways("\u25C7", "\xA1\xFE", 'euc-jp') # ◇
check_both_ways("\u25C6", "\xA2\xA1", 'euc-jp') # ◆
- assert_undefined_in("\xA2\xAF", 'euc-jp')
- assert_undefined_in("\xA2\xB9", 'euc-jp')
- assert_undefined_in("\xA2\xC2", 'euc-jp')
- assert_undefined_in("\xA2\xC9", 'euc-jp')
- assert_undefined_in("\xA2\xD1", 'euc-jp')
- assert_undefined_in("\xA2\xDB", 'euc-jp')
- assert_undefined_in("\xA2\xEB", 'euc-jp')
- assert_undefined_in("\xA2\xF1", 'euc-jp')
- assert_undefined_in("\xA2\xFA", 'euc-jp')
- assert_undefined_in("\xA2\xFD", 'euc-jp')
+ assert_raise(Encoding::UndefinedConversionError) { "\xA2\xAF".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA2\xB9".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA2\xC2".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA2\xC9".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA2\xD1".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA2\xDB".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA2\xEB".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA2\xF1".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA2\xFA".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA2\xFD".encode("utf-8", 'euc-jp') }
check_both_ways("\u25EF", "\xA2\xFE", 'euc-jp') # ◯
- assert_undefined_in("\xA3\xAF", 'euc-jp')
- assert_undefined_in("\xA3\xBA", 'euc-jp')
- assert_undefined_in("\xA3\xC0", 'euc-jp')
- assert_undefined_in("\xA3\xDB", 'euc-jp')
- assert_undefined_in("\xA3\xE0", 'euc-jp')
- assert_undefined_in("\xA3\xFB", 'euc-jp')
- assert_undefined_in("\xA4\xF4", 'euc-jp')
- assert_undefined_in("\xA5\xF7", 'euc-jp')
- assert_undefined_in("\xA6\xB9", 'euc-jp')
- assert_undefined_in("\xA6\xC0", 'euc-jp')
- assert_undefined_in("\xA6\xD9", 'euc-jp')
- assert_undefined_in("\xA7\xC2", 'euc-jp')
- assert_undefined_in("\xA7\xD0", 'euc-jp')
- assert_undefined_in("\xA7\xF2", 'euc-jp')
- assert_undefined_in("\xA8\xC1", 'euc-jp')
- assert_undefined_in("\xCF\xD4", 'euc-jp')
- assert_undefined_in("\xCF\xFE", 'euc-jp')
+ assert_raise(Encoding::UndefinedConversionError) { "\xA3\xAF".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA3\xBA".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA3\xC0".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA3\xDB".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA3\xE0".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA3\xFB".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA4\xF4".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA5\xF7".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA6\xB9".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA6\xC0".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA6\xD9".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA7\xC2".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA7\xD0".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA7\xF2".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA8\xC1".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xCF\xD4".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xCF\xFE".encode("utf-8", 'euc-jp') }
check_both_ways("\u6A97", "\xDD\xA1", 'euc-jp') # 檗
check_both_ways("\u6BEF", "\xDD\xDF", 'euc-jp') # 毯
check_both_ways("\u9EBE", "\xDD\xE0", 'euc-jp') # 麾
@@ -1439,7 +1449,7 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u71FC", "\xDF\xFE", 'euc-jp') # 燼
check_both_ways("\u71F9", "\xE0\xA1", 'euc-jp') # 燹
check_both_ways("\u73F1", "\xE0\xFE", 'euc-jp') # 珱
- assert_undefined_in("\xF4\xA7", 'euc-jp')
+ assert_raise(Encoding::UndefinedConversionError) { "\xF4\xA7".encode("utf-8", 'euc-jp') }
#check_both_ways("\u9ADC", "\xFC\xE3", 'euc-jp') # 髜 (IBM extended)
check_both_ways("\u677E\u672C\u884C\u5F18", "\xBE\xBE\xCB\xDC\xB9\xD4\xB9\xB0", 'euc-jp') # 松本行弘
@@ -1471,7 +1481,7 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u2127", "\xA3\xE0", 'euc-jis-2004') # ℧
check_both_ways("\u30A0", "\xA3\xFB", 'euc-jis-2004') # ゠
check_both_ways("\uFF54", "\xA3\xF4", 'euc-jis-2004') # t
- assert_undefined_in("\xA5\xF7", 'euc-jis-2004')
+ assert_raise(Encoding::UndefinedConversionError) { "\xA5\xF7".encode("utf-8", 'euc-jis-2004') }
check_both_ways("\u2664", "\xA6\xB9", 'euc-jis-2004') # ♤
check_both_ways("\u2663", "\xA6\xC0", 'euc-jis-2004') # ♣
check_both_ways("\u03C2", "\xA6\xD9", 'euc-jis-2004') # ς
@@ -1556,33 +1566,33 @@ class TestTranscode < Test::Unit::TestCase
end
def test_eucjp_sjis_undef
- assert_undefined_conversion("\x8e\xe0", "Shift_JIS", "EUC-JP")
- assert_undefined_conversion("\x8e\xfe", "Shift_JIS", "EUC-JP")
- assert_undefined_conversion("\x8f\xa1\xa1", "Shift_JIS", "EUC-JP")
- assert_undefined_conversion("\x8f\xa1\xfe", "Shift_JIS", "EUC-JP")
- assert_undefined_conversion("\x8f\xfe\xa1", "Shift_JIS", "EUC-JP")
- assert_undefined_conversion("\x8f\xfe\xfe", "Shift_JIS", "EUC-JP")
-
- assert_undefined_conversion("\xf0\x40", "EUC-JP", "Shift_JIS")
- assert_undefined_conversion("\xf0\x7e", "EUC-JP", "Shift_JIS")
- assert_undefined_conversion("\xf0\x80", "EUC-JP", "Shift_JIS")
- assert_undefined_conversion("\xf0\xfc", "EUC-JP", "Shift_JIS")
- assert_undefined_conversion("\xfc\x40", "EUC-JP", "Shift_JIS")
- assert_undefined_conversion("\xfc\x7e", "EUC-JP", "Shift_JIS")
- assert_undefined_conversion("\xfc\x80", "EUC-JP", "Shift_JIS")
- assert_undefined_conversion("\xfc\xfc", "EUC-JP", "Shift_JIS")
+ assert_raise(Encoding::UndefinedConversionError) { "\x8e\xe0".encode("Shift_JIS", "EUC-JP") }
+ assert_raise(Encoding::UndefinedConversionError) { "\x8e\xfe".encode("Shift_JIS", "EUC-JP") }
+ assert_raise(Encoding::UndefinedConversionError) { "\x8f\xa1\xa1".encode("Shift_JIS", "EUC-JP") }
+ assert_raise(Encoding::UndefinedConversionError) { "\x8f\xa1\xfe".encode("Shift_JIS", "EUC-JP") }
+ assert_raise(Encoding::UndefinedConversionError) { "\x8f\xfe\xa1".encode("Shift_JIS", "EUC-JP") }
+ assert_raise(Encoding::UndefinedConversionError) { "\x8f\xfe\xfe".encode("Shift_JIS", "EUC-JP") }
+
+ assert_raise(Encoding::UndefinedConversionError) { "\xf0\x40".encode("EUC-JP", "Shift_JIS") }
+ assert_raise(Encoding::UndefinedConversionError) { "\xf0\x7e".encode("EUC-JP", "Shift_JIS") }
+ assert_raise(Encoding::UndefinedConversionError) { "\xf0\x80".encode("EUC-JP", "Shift_JIS") }
+ assert_raise(Encoding::UndefinedConversionError) { "\xf0\xfc".encode("EUC-JP", "Shift_JIS") }
+ assert_raise(Encoding::UndefinedConversionError) { "\xfc\x40".encode("EUC-JP", "Shift_JIS") }
+ assert_raise(Encoding::UndefinedConversionError) { "\xfc\x7e".encode("EUC-JP", "Shift_JIS") }
+ assert_raise(Encoding::UndefinedConversionError) { "\xfc\x80".encode("EUC-JP", "Shift_JIS") }
+ assert_raise(Encoding::UndefinedConversionError) { "\xfc\xfc".encode("EUC-JP", "Shift_JIS") }
end
def test_iso_2022_jp
- assert_invalid_in("\x1b(A", "iso-2022-jp")
- assert_invalid_in("\x1b$(A", "iso-2022-jp")
- assert_invalid_in("\x1b$C", "iso-2022-jp")
- assert_invalid_in("\x0e", "iso-2022-jp")
- assert_invalid_in("\x80", "iso-2022-jp")
- assert_invalid_in("\x1b$(Dd!\x1b(B", "iso-2022-jp")
- assert_undefined_conversion("\u9299", "iso-2022-jp")
- assert_undefined_conversion("\uff71\uff72\uff73\uff74\uff75", "iso-2022-jp")
- assert_invalid_in("\x1b(I12345\x1b(B", "iso-2022-jp")
+ assert_raise(Encoding::InvalidByteSequenceError) { "\x1b(A".encode("utf-8", "iso-2022-jp") }
+ assert_raise(Encoding::InvalidByteSequenceError) { "\x1b$(A".encode("utf-8", "iso-2022-jp") }
+ assert_raise(Encoding::InvalidByteSequenceError) { "\x1b$C".encode("utf-8", "iso-2022-jp") }
+ assert_raise(Encoding::InvalidByteSequenceError) { "\x0e".encode("utf-8", "iso-2022-jp") }
+ assert_raise(Encoding::InvalidByteSequenceError) { "\x80".encode("utf-8", "iso-2022-jp") }
+ assert_raise(Encoding::InvalidByteSequenceError) { "\x1b$(Dd!\x1b(B".encode("utf-8", "iso-2022-jp") }
+ assert_raise(Encoding::UndefinedConversionError) { "\u9299".encode("iso-2022-jp") }
+ assert_raise(Encoding::UndefinedConversionError) { "\uff71\uff72\uff73\uff74\uff75".encode("iso-2022-jp") }
+ assert_raise(Encoding::InvalidByteSequenceError) { "\x1b(I12345\x1b(B".encode("utf-8", "iso-2022-jp") }
assert_equal("\xA1\xA1".force_encoding("euc-jp"),
"\e$B!!\e(B".encode("EUC-JP", "ISO-2022-JP"))
assert_equal("\e$B!!\e(B".force_encoding("ISO-2022-JP"),
@@ -1645,11 +1655,11 @@ class TestTranscode < Test::Unit::TestCase
assert_equal("\u005C", "\e(J\x5C\e(B".encode("UTF-8", "ISO-2022-JP"))
assert_equal("\u005C", "\x5C".encode("stateless-ISO-2022-JP", "ISO-2022-JP"))
assert_equal("\u005C", "\e(J\x5C\e(B".encode("stateless-ISO-2022-JP", "ISO-2022-JP"))
- assert_undefined_conversion("\u00A5", "Shift_JIS")
- assert_undefined_conversion("\u00A5", "Windows-31J")
- assert_undefined_conversion("\u00A5", "EUC-JP")
- assert_undefined_conversion("\u00A5", "eucJP-ms")
- assert_undefined_conversion("\u00A5", "CP51932")
+ assert_raise(Encoding::UndefinedConversionError) { "\u00A5".encode("Shift_JIS") }
+ assert_raise(Encoding::UndefinedConversionError) { "\u00A5".encode("Windows-31J") }
+ assert_raise(Encoding::UndefinedConversionError) { "\u00A5".encode("EUC-JP") }
+ assert_raise(Encoding::UndefinedConversionError) { "\u00A5".encode("eucJP-ms") }
+ assert_raise(Encoding::UndefinedConversionError) { "\u00A5".encode("CP51932") }
# FULLWIDTH REVERSE SOLIDUS
check_both_ways("\uFF3C", "\x81\x5F", "Shift_JIS")
@@ -1670,21 +1680,21 @@ class TestTranscode < Test::Unit::TestCase
assert_equal("\u007E", "\e(J\x7E\e(B".encode("UTF-8", "ISO-2022-JP"))
assert_equal("\u007E", "\x7E".encode("stateless-ISO-2022-JP", "ISO-2022-JP"))
assert_equal("\u007E", "\e(J\x7E\e(B".encode("stateless-ISO-2022-JP", "ISO-2022-JP"))
- assert_undefined_conversion("\u203E", "Shift_JIS")
- assert_undefined_conversion("\u203E", "Windows-31J")
- assert_undefined_conversion("\u203E", "EUC-JP")
- assert_undefined_conversion("\u203E", "eucJP-ms")
- assert_undefined_conversion("\u203E", "CP51932")
+ assert_raise(Encoding::UndefinedConversionError) { "\u203E".encode("Shift_JIS") }
+ assert_raise(Encoding::UndefinedConversionError) { "\u203E".encode("Windows-31J") }
+ assert_raise(Encoding::UndefinedConversionError) { "\u203E".encode("EUC-JP") }
+ assert_raise(Encoding::UndefinedConversionError) { "\u203E".encode("eucJP-ms") }
+ assert_raise(Encoding::UndefinedConversionError) { "\u203E".encode("CP51932") }
end
def test_gb2312
check_both_ways("\u3000", "\xA1\xA1", 'GB2312') # full-width space
check_both_ways("\u3013", "\xA1\xFE", 'GB2312') # 〓
- assert_undefined_in("\xA2\xB0", 'GB2312')
+ assert_raise(Encoding::UndefinedConversionError) { "\xA2\xB0".encode("utf-8", 'GB2312') }
check_both_ways("\u2488", "\xA2\xB1", 'GB2312') # ⒈
- assert_undefined_in("\xA2\xE4", 'GB2312')
+ assert_raise(Encoding::UndefinedConversionError) { "\xA2\xE4".encode("utf-8", 'GB2312') }
check_both_ways("\u3220", "\xA2\xE5", 'GB2312') # ㈠
- assert_undefined_in("\xA2\xF0", 'GB2312')
+ assert_raise(Encoding::UndefinedConversionError) { "\xA2\xF0".encode("utf-8", 'GB2312') }
check_both_ways("\u2160", "\xA2\xF1", 'GB2312') # Ⅰ
check_both_ways("\uFF01", "\xA3\xA1", 'GB2312') # !
check_both_ways("\uFFE3", "\xA3\xFE", 'GB2312') #  ̄
@@ -1695,9 +1705,9 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u0410", "\xA7\xA1", 'GB2312') # А
check_both_ways("\u0430", "\xA7\xD1", 'GB2312') # а
check_both_ways("\u0101", "\xA8\xA1", 'GB2312') # ā
- assert_undefined_in("\xA8\xC4", 'GB2312')
+ assert_raise(Encoding::UndefinedConversionError) { "\xA8\xC4".encode("utf-8", 'GB2312') }
check_both_ways("\u3105", "\xA8\xC5", 'GB2312') # ㄅ
- assert_undefined_in("\xA9\xA3", 'GB2312')
+ assert_raise(Encoding::UndefinedConversionError) { "\xA9\xA3".encode("utf-8", 'GB2312') }
check_both_ways("\u2500", "\xA9\xA4", 'GB2312') # ─
check_both_ways("\u554A", "\xB0\xA1", 'GB2312') # 啊
check_both_ways("\u5265", "\xB0\xFE", 'GB2312') # 剥
@@ -1711,7 +1721,7 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u7384", "\xD0\xFE", 'GB2312') # 玄
check_both_ways("\u4F4F", "\xD7\xA1", 'GB2312') # 住
check_both_ways("\u5EA7", "\xD7\xF9", 'GB2312') # 座
- assert_undefined_in("\xD7\xFA", 'GB2312')
+ assert_raise(Encoding::UndefinedConversionError) { "\xD7\xFA".encode("utf-8", 'GB2312') }
check_both_ways("\u647A", "\xDF\xA1", 'GB2312') # 摺
check_both_ways("\u553C", "\xDF\xFE", 'GB2312') # 唼
check_both_ways("\u5537", "\xE0\xA1", 'GB2312') # 唷
@@ -1749,48 +1759,48 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u3000", "\xA1\xA1", 'GBK') # full-width space
check_both_ways("\u3001", "\xA1\xA2", 'GBK') # 、
check_both_ways("\u3013", "\xA1\xFE", 'GBK') # 〓
- assert_undefined_in("\xA2\xA0", 'GBK')
+ assert_raise(Encoding::UndefinedConversionError) { "\xA2\xA0".encode("utf-8", 'GBK') }
check_both_ways("\u2170", "\xA2\xA1", 'GBK') # ⅰ
- assert_undefined_in("\xA2\xB0", 'GBK')
+ assert_raise(Encoding::UndefinedConversionError) { "\xA2\xB0".encode("utf-8", 'GBK') }
check_both_ways("\u2488", "\xA2\xB1", 'GBK') # ⒈
- assert_undefined_in("\xA2\xE4", 'GBK')
+ assert_raise(Encoding::UndefinedConversionError) { "\xA2\xE4".encode("utf-8", 'GBK') }
check_both_ways("\u3220", "\xA2\xE5", 'GBK') # ㈠
- assert_undefined_in("\xA2\xF0", 'GBK')
+ assert_raise(Encoding::UndefinedConversionError) { "\xA2\xF0".encode("utf-8", 'GBK') }
check_both_ways("\u2160", "\xA2\xF1", 'GBK') # Ⅰ
- assert_undefined_in("\xA3\xA0", 'GBK')
+ assert_raise(Encoding::UndefinedConversionError) { "\xA3\xA0".encode("utf-8", 'GBK') }
check_both_ways("\uFF01", "\xA3\xA1", 'GBK') # !
check_both_ways("\uFFE3", "\xA3\xFE", 'GBK') #  ̄
- assert_undefined_in("\xA4\xA0", 'GBK')
+ assert_raise(Encoding::UndefinedConversionError) { "\xA4\xA0".encode("utf-8", 'GBK') }
check_both_ways("\u3041", "\xA4\xA1", 'GBK') # ぁ
- assert_undefined_in("\xA5\xA0", 'GBK')
+ assert_raise(Encoding::UndefinedConversionError) { "\xA5\xA0".encode("utf-8", 'GBK') }
check_both_ways("\u30A1", "\xA5\xA1", 'GBK') # ァ
check_both_ways("\u0391", "\xA6\xA1", 'GBK') # Α
check_both_ways("\u03B1", "\xA6\xC1", 'GBK') # α
- assert_undefined_in("\xA6\xED", 'GBK')
+ assert_raise(Encoding::UndefinedConversionError) { "\xA6\xED".encode("utf-8", 'GBK') }
check_both_ways("\uFE3B", "\xA6\xEE", 'GBK') # ︻
check_both_ways("\u0410", "\xA7\xA1", 'GBK') # А
check_both_ways("\u0430", "\xA7\xD1", 'GBK') # а
check_both_ways("\u02CA", "\xA8\x40", 'GBK') # ˊ
check_both_ways("\u2587", "\xA8\x7E", 'GBK') # ▇
- assert_undefined_in("\xA8\x96", 'GBK')
+ assert_raise(Encoding::UndefinedConversionError) { "\xA8\x96".encode("utf-8", 'GBK') }
check_both_ways("\u0101", "\xA8\xA1", 'GBK') # ā
- assert_undefined_in("\xA8\xBC", 'GBK')
- assert_undefined_in("\xA8\xBF", 'GBK')
- assert_undefined_in("\xA8\xC4", 'GBK')
+ assert_raise(Encoding::UndefinedConversionError) { "\xA8\xBC".encode("utf-8", 'GBK') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA8\xBF".encode("utf-8", 'GBK') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA8\xC4".encode("utf-8", 'GBK') }
check_both_ways("\u3105", "\xA8\xC5", 'GBK') # ㄅ
check_both_ways("\u3021", "\xA9\x40", 'GBK') # 〡
- assert_undefined_in("\xA9\x58", 'GBK')
- assert_undefined_in("\xA9\x5B", 'GBK')
- assert_undefined_in("\xA9\x5D", 'GBK')
+ assert_raise(Encoding::UndefinedConversionError) { "\xA9\x58".encode("utf-8", 'GBK') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA9\x5B".encode("utf-8", 'GBK') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA9\x5D".encode("utf-8", 'GBK') }
check_both_ways("\u3007", "\xA9\x96", 'GBK') # 〇
- assert_undefined_in("\xA9\xA3", 'GBK')
+ assert_raise(Encoding::UndefinedConversionError) { "\xA9\xA3".encode("utf-8", 'GBK') }
check_both_ways("\u2500", "\xA9\xA4", 'GBK') # ─
- assert_undefined_in("\xA9\xF0", 'GBK')
+ assert_raise(Encoding::UndefinedConversionError) { "\xA9\xF0".encode("utf-8", 'GBK') }
check_both_ways("\u7588", "\xAF\x40", 'GBK') # 疈
check_both_ways("\u7607", "\xAF\x7E", 'GBK') # 瘇
check_both_ways("\u7608", "\xAF\x80", 'GBK') # 瘈
check_both_ways("\u7644", "\xAF\xA0", 'GBK') # 癄
- assert_undefined_in("\xAF\xA1", 'GBK')
+ assert_raise(Encoding::UndefinedConversionError) { "\xAF\xA1".encode("utf-8", 'GBK') }
check_both_ways("\u7645", "\xB0\x40", 'GBK') # 癅
check_both_ways("\u769B", "\xB0\x7E", 'GBK') # 皛
check_both_ways("\u769C", "\xB0\x80", 'GBK') # 皜
@@ -1831,10 +1841,10 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u9F78", "\xFD\x7E", 'GBK') # 齸
check_both_ways("\u9F79", "\xFD\x80", 'GBK') # 齹
check_both_ways("\uF9F1", "\xFD\xA0", 'GBK') # 隣
- assert_undefined_in("\xFD\xA1", 'GBK')
+ assert_raise(Encoding::UndefinedConversionError) { "\xFD\xA1".encode("utf-8", 'GBK') }
check_both_ways("\uFA0C", "\xFE\x40", 'GBK') # 兀
check_both_ways("\uFA29", "\xFE\x4F", 'GBK') # 﨩
- assert_undefined_in("\xFE\x50", 'GBK')
+ assert_raise(Encoding::UndefinedConversionError) { "\xFE\x50".encode("utf-8", 'GBK') }
check_both_ways("\u9752\u5C71\u5B66\u9662\u5927\u5B66", "\xC7\xE0\xC9\xBD\xD1\xA7\xD4\xBA\xB4\xF3\xD1\xA7", 'GBK') # 青山学院大学
check_both_ways("\u795E\u6797\u7FA9\u535A", "\xC9\xF1\xC1\xD6\xC1\x78\xB2\xA9", 'GBK') # 神林義博
end
@@ -1870,48 +1880,48 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u3000", "\xA1\xA1", 'GB18030') # full-width space
check_both_ways("\u3001", "\xA1\xA2", 'GB18030') #
check_both_ways("\u3013", "\xA1\xFE", 'GB18030') #
- #assert_undefined_in("\xA2\xA0", 'GB18030')
+ #assert_raise(Encoding::UndefinedConversionError) { "\xA2\xA0".encode("utf-8", 'GB18030') }
check_both_ways("\u2170", "\xA2\xA1", 'GB18030') # ⅰ
- #assert_undefined_in("\xA2\xB0", 'GB18030')
+ #assert_raise(Encoding::UndefinedConversionError) { "\xA2\xB0".encode("utf-8", 'GB18030') }
check_both_ways("\u2488", "\xA2\xB1", 'GB18030') #
- #assert_undefined_in("\xA2\xE4", 'GB18030')
+ #assert_raise(Encoding::UndefinedConversionError) { "\xA2\xE4".encode("utf-8", 'GB18030') }
check_both_ways("\u3220", "\xA2\xE5", 'GB18030') # ㈠
- #assert_undefined_in("\xA2\xF0", 'GB18030')
+ #assert_raise(Encoding::UndefinedConversionError) { "\xA2\xF0".encode("utf-8", 'GB18030') }
check_both_ways("\u2160", "\xA2\xF1", 'GB18030') # Ⅰ
- #assert_undefined_in("\xA3\xA0", 'GB18030')
+ #assert_raise(Encoding::UndefinedConversionError) { "\xA3\xA0".encode("utf-8", 'GB18030') }
check_both_ways("\uFF01", "\xA3\xA1", 'GB18030') # E
check_both_ways("\uFFE3", "\xA3\xFE", 'GB18030') # E
- #assert_undefined_in("\xA4\xA0", 'GB18030')
+ #assert_raise(Encoding::UndefinedConversionError) { "\xA4\xA0".encode("utf-8", 'GB18030') }
check_both_ways("\u3041", "\xA4\xA1", 'GB18030') #
- #assert_undefined_in("\xA5\xA0", 'GB18030')
+ #assert_raise(Encoding::UndefinedConversionError) { "\xA5\xA0".encode("utf-8", 'GB18030') }
check_both_ways("\u30A1", "\xA5\xA1", 'GB18030') # ァ
check_both_ways("\u0391", "\xA6\xA1", 'GB18030') #
check_both_ways("\u03B1", "\xA6\xC1", 'GB18030') # α
- #assert_undefined_in("\xA6\xED", 'GB18030')
+ #assert_raise(Encoding::UndefinedConversionError) { "\xA6\xED".encode("utf-8", 'GB18030') }
check_both_ways("\uFE3B", "\xA6\xEE", 'GB18030') # E
check_both_ways("\u0410", "\xA7\xA1", 'GB18030') #
check_both_ways("\u0430", "\xA7\xD1", 'GB18030') # а
check_both_ways("\u02CA", "\xA8\x40", 'GB18030') #
check_both_ways("\u2587", "\xA8\x7E", 'GB18030') #
- #assert_undefined_in("\xA8\x96", 'GB18030')
+ #assert_raise(Encoding::UndefinedConversionError) { "\xA8\x96".encode("utf-8", 'GB18030') }
check_both_ways("\u0101", "\xA8\xA1", 'GB18030') #
- #assert_undefined_in("\xA8\xBC", 'GB18030')
- #assert_undefined_in("\xA8\xBF", 'GB18030')
- #assert_undefined_in("\xA8\xC4", 'GB18030')
+ #assert_raise(Encoding::UndefinedConversionError) { "\xA8\xBC".encode("utf-8", 'GB18030') }
+ #assert_raise(Encoding::UndefinedConversionError) { "\xA8\xBF".encode("utf-8", 'GB18030') }
+ #assert_raise(Encoding::UndefinedConversionError) { "\xA8\xC4".encode("utf-8", 'GB18030') }
check_both_ways("\u3105", "\xA8\xC5", 'GB18030') #
check_both_ways("\u3021", "\xA9\x40", 'GB18030') # 〡
- #assert_undefined_in("\xA9\x58", 'GB18030')
- #assert_undefined_in("\xA9\x5B", 'GB18030')
- #assert_undefined_in("\xA9\x5D", 'GB18030')
+ #assert_raise(Encoding::UndefinedConversionError) { "\xA9\x58".encode("utf-8", 'GB18030') }
+ #assert_raise(Encoding::UndefinedConversionError) { "\xA9\x5B".encode("utf-8", 'GB18030') }
+ #assert_raise(Encoding::UndefinedConversionError) { "\xA9\x5D".encode("utf-8", 'GB18030') }
check_both_ways("\u3007", "\xA9\x96", 'GB18030') #
- #assert_undefined_in("\xA9\xA3", 'GB18030')
+ #assert_raise(Encoding::UndefinedConversionError) { "\xA9\xA3".encode("utf-8", 'GB18030') }
check_both_ways("\u2500", "\xA9\xA4", 'GB18030') # ─
- #assert_undefined_in("\xA9\xF0", 'GB18030')
+ #assert_raise(Encoding::UndefinedConversionError) { "\xA9\xF0".encode("utf-8", 'GB18030') }
check_both_ways("\u7588", "\xAF\x40", 'GB18030') #
check_both_ways("\u7607", "\xAF\x7E", 'GB18030') #
check_both_ways("\u7608", "\xAF\x80", 'GB18030') #
check_both_ways("\u7644", "\xAF\xA0", 'GB18030') #
- #assert_undefined_in("\xAF\xA1", 'GB18030')
+ #assert_raise(Encoding::UndefinedConversionError) { "\xAF\xA1".encode("utf-8", 'GB18030') }
check_both_ways("\u7645", "\xB0\x40", 'GB18030') #
check_both_ways("\u769B", "\xB0\x7E", 'GB18030') #
check_both_ways("\u769C", "\xB0\x80", 'GB18030') #
@@ -1952,10 +1962,10 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u9F78", "\xFD\x7E", 'GB18030') # 齸
check_both_ways("\u9F79", "\xFD\x80", 'GB18030') # 齹
check_both_ways("\uF9F1", "\xFD\xA0", 'GB18030') # E
- #assert_undefined_in("\xFD\xA1", 'GB18030')
+ #assert_raise(Encoding::UndefinedConversionError) { "\xFD\xA1".encode("utf-8", 'GB18030') }
check_both_ways("\uFA0C", "\xFE\x40", 'GB18030') # E
check_both_ways("\uFA29", "\xFE\x4F", 'GB18030') # E
- #assert_undefined_in("\xFE\x50", 'GB18030')
+ #assert_raise(Encoding::UndefinedConversionError) { "\xFE\x50".encode("utf-8", 'GB18030') }
check_both_ways("\u9752\u5C71\u5B66\u9662\u5927\u5B66", "\xC7\xE0\xC9\xBD\xD1\xA7\xD4\xBA\xB4\xF3\xD1\xA7", 'GB18030') # 青山学院大学
check_both_ways("\u795E\u6797\u7FA9\u535A", "\xC9\xF1\xC1\xD6\xC1\x78\xB2\xA9", 'GB18030') # 神林義
@@ -2010,7 +2020,7 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u310F", "\xA3\x7E", 'Big5') # ㄏ
check_both_ways("\u3110", "\xA3\xA1", 'Big5') # ㄐ
check_both_ways("\u02CB", "\xA3\xBF", 'Big5') # ˋ
- assert_undefined_in("\xA3\xC0", 'Big5')
+ assert_raise(Encoding::UndefinedConversionError) { "\xA3\xC0".encode("utf-8", 'Big5') }
check_both_ways("\u6D6C", "\xAF\x40", 'Big5') # 浬
check_both_ways("\u7837", "\xAF\x7E", 'Big5') # 砷
check_both_ways("\u7825", "\xAF\xA1", 'Big5') # 砥
@@ -2029,9 +2039,9 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u77AC", "\xC0\xFE", 'Big5') # 瞬
check_both_ways("\u8B96", "\xC6\x40", 'Big5') # 讖
check_both_ways("\u7C72", "\xC6\x7E", 'Big5') # 籲
- #assert_undefined_in("\xC6\xA1", 'Big5')
- #assert_undefined_in("\xC7\x40", 'Big5')
- #assert_undefined_in("\xC8\x40", 'Big5')
+ #assert_raise(Encoding::UndefinedConversionError) { "\xC6\xA1".encode("utf-8", 'Big5') }
+ #assert_raise(Encoding::UndefinedConversionError) { "\xC7\x40".encode("utf-8", 'Big5') }
+ #assert_raise(Encoding::UndefinedConversionError) { "\xC8\x40".encode("utf-8", 'Big5') }
check_both_ways("\u4E42", "\xC9\x40", 'Big5') # 乂
check_both_ways("\u6C15", "\xC9\x7E", 'Big5') # 氕
check_both_ways("\u6C36", "\xC9\xA1", 'Big5') # 氶
@@ -2064,7 +2074,7 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u9F0A", "\xF9\x7E", 'Big5') # 鼊
check_both_ways("\u9FA4", "\xF9\xA1", 'Big5') # 龤
check_both_ways("\u9F98", "\xF9\xD5", 'Big5') # 龘
- #assert_undefined_in("\xF9\xD6", 'Big5')
+ #assert_raise(Encoding::UndefinedConversionError) { "\xF9\xD6".encode("utf-8", 'Big5') }
check_both_ways("\u795E\u6797\u7FA9\u535A", "\xAF\xAB\xAA\x4C\xB8\x71\xB3\xD5", 'Big5') # 神林義博
end
@@ -2077,7 +2087,7 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u310F", "\xA3\x7E", 'Big5-HKSCS') # ㄏ
check_both_ways("\u3110", "\xA3\xA1", 'Big5-HKSCS') # ㄐ
check_both_ways("\u02CB", "\xA3\xBF", 'Big5-HKSCS') # ˋ
- #assert_undefined_in("\xA3\xC0", 'Big5-HKSCS')
+ #assert_raise(Encoding::UndefinedConversionError) { "\xA3\xC0".encode("utf-8", 'Big5-HKSCS') }
check_both_ways("\u6D6C", "\xAF\x40", 'Big5-HKSCS') # 浬
check_both_ways("\u7837", "\xAF\x7E", 'Big5-HKSCS') # 砷
check_both_ways("\u7825", "\xAF\xA1", 'Big5-HKSCS') # 砥
@@ -2096,9 +2106,9 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u77AC", "\xC0\xFE", 'Big5-HKSCS') # 瞬
check_both_ways("\u8B96", "\xC6\x40", 'Big5-HKSCS') # 讖
check_both_ways("\u7C72", "\xC6\x7E", 'Big5-HKSCS') # 籲
- #assert_undefined_in("\xC6\xA1", 'Big5-HKSCS')
- #assert_undefined_in("\xC7\x40", 'Big5-HKSCS')
- #assert_undefined_in("\xC8\x40", 'Big5-HKSCS')
+ #assert_raise(Encoding::UndefinedConversionError) { "\xC6\xA1".encode("utf-8", 'Big5-HKSCS') }
+ #assert_raise(Encoding::UndefinedConversionError) { "\xC7\x40".encode("utf-8", 'Big5-HKSCS') }
+ #assert_raise(Encoding::UndefinedConversionError) { "\xC8\x40".encode("utf-8", 'Big5-HKSCS') }
check_both_ways("\u4E42", "\xC9\x40", 'Big5-HKSCS') # 乂
check_both_ways("\u6C15", "\xC9\x7E", 'Big5-HKSCS') # 氕
check_both_ways("\u6C36", "\xC9\xA1", 'Big5-HKSCS') # 氶
@@ -2132,7 +2142,7 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u9FA4", "\xF9\xA1", 'Big5-HKSCS') # 龤
check_both_ways("\u9F98", "\xF9\xD5", 'Big5-HKSCS') # 龘
#check_both_ways("\u{23ED7}", "\x8E\x40", 'Big5-HKSCS') # 𣻗
- #assert_undefined_in("\xF9\xD6", 'Big5-HKSCS')
+ #assert_raise(Encoding::UndefinedConversionError) { "\xF9\xD6".encode("utf-8", 'Big5-HKSCS') }
check_both_ways("\u795E\u6797\u7FA9\u535A", "\xAF\xAB\xAA\x4C\xB8\x71\xB3\xD5", 'Big5-HKSCS') # 神林義博
end
@@ -2222,12 +2232,12 @@ class TestTranscode < Test::Unit::TestCase
assert_equal("U+3042", "\u{3042}".encode("US-ASCII", fallback: fallback))
end
- def test_pseudo_encoding_inspect
- s = 'aaa'.encode "UTF-16"
- assert_equal '"\xFE\xFF\x00\x61\x00\x61\x00\x61"', s.inspect
-
- s = 'aaa'.encode "UTF-32"
- assert_equal '"\x00\x00\xFE\xFF\x00\x00\x00\x61\x00\x00\x00\x61\x00\x00\x00\x61"', s.inspect
+ bug8940 = '[ruby-core:57318] [Bug #8940]'
+ %w[UTF-32 UTF-16].each do |enc|
+ define_method("test_pseudo_encoding_inspect(#{enc})") do
+ assert_normal_exit("'aaa'.encode('#{enc}').inspect", bug8940)
+ assert_equal(4, 'aaa'.encode(enc).length, "should count in #{enc} with BOM")
+ end
end
def test_encode_with_invalid_chars
@@ -2295,37 +2305,5 @@ class TestTranscode < Test::Unit::TestCase
assert_equal("A\rB\r\rC", s.encode(usascii, newline: :cr))
assert_equal("A\r\nB\r\r\nC", s.encode(usascii, crlf_newline: true))
assert_equal("A\r\nB\r\r\nC", s.encode(usascii, newline: :crlf))
- assert_equal("A\nB\nC", s.encode(usascii, lf_newline: true))
- assert_equal("A\nB\nC", s.encode(usascii, newline: :lf))
- end
-
- private
-
- def assert_conversion_both_ways_utf8(utf8, raw, encoding)
- assert_conversion_both_ways(utf8, 'utf-8', raw, encoding)
- end
- alias check_both_ways assert_conversion_both_ways_utf8
-
- def assert_conversion_both_ways(str1, enc1, str2, enc2)
- message = str1.dump+str2.dump
- assert_equal(str1.force_encoding(enc1), str2.encode(enc1, enc2), message)
- assert_equal(str2.force_encoding(enc2), str1.encode(enc2, enc1), message)
- end
- alias check_both_ways2 assert_conversion_both_ways
-
- def assert_undefined_conversion(str, to, from = nil)
- assert_raise(Encoding::UndefinedConversionError) { str.encode(to, from) }
- end
-
- def assert_undefined_in(str, encoding)
- assert_undefined_conversion(str, 'utf-8', encoding)
- end
-
- def assert_invalid_byte_sequence(str, to, from = nil)
- assert_raise(Encoding::InvalidByteSequenceError) { str.encode(to, from) }
- end
-
- def assert_invalid_in(str, encoding)
- assert_invalid_byte_sequence(str, 'utf-8', encoding)
end
end
diff --git a/test/ruby/test_variable.rb b/test/ruby/test_variable.rb
index 86f2e4bb84..d425b43b0d 100644
--- a/test/ruby/test_variable.rb
+++ b/test/ruby/test_variable.rb
@@ -174,21 +174,6 @@ class TestVariable < Test::Unit::TestCase
end
end
- def test_set_class_variable_on_frozen_object
- set_cvar = EnvUtil.labeled_class("SetCVar")
- set_cvar.class_eval "#{<<~"begin;"}\n#{<<~'end;'}"
- begin;
- def self.set(val)
- @@a = val # inline cache
- end
- end;
- set_cvar.set(1) # fill write cache
- set_cvar.freeze
- assert_raise(FrozenError, "[Bug #19341]") do
- set_cvar.set(2) # hit write cache, but should check frozen status
- end
- end
-
def test_variable
assert_instance_of(Integer, $$)
@@ -266,84 +251,6 @@ class TestVariable < Test::Unit::TestCase
assert_include(gv, :$12)
end
- def prepare_klass_for_test_svar_with_ifunc
- Class.new do
- include Enumerable
- def each(&b)
- @b = b
- end
-
- def check1
- check2.merge({check1: $1})
- end
-
- def check2
- @b.call('foo')
- {check2: $1}
- end
- end
- end
-
- def test_svar_with_ifunc
- c = prepare_klass_for_test_svar_with_ifunc
-
- expected_check1_result = {
- check1: nil, check2: nil
- }.freeze
-
- obj = c.new
- result = nil
- obj.grep(/(f..)/){
- result = $1
- }
- assert_equal nil, result
- assert_equal nil, $1
- assert_equal expected_check1_result, obj.check1
- assert_equal 'foo', result
- assert_equal 'foo', $1
-
- # this frame was escaped so try it again
- $~ = nil
- obj = c.new
- result = nil
- obj.grep(/(f..)/){
- result = $1
- }
- assert_equal nil, result
- assert_equal nil, $1
- assert_equal expected_check1_result, obj.check1
- assert_equal 'foo', result
- assert_equal 'foo', $1
-
- # different context
- result = nil
- Fiber.new{
- obj = c.new
- obj.grep(/(f..)/){
- result = $1
- }
- }.resume # obj is created in antoher Fiber
- assert_equal nil, result
- assert_equal expected_check1_result, obj.check1
- assert_equal 'foo', result
- assert_equal 'foo', $1
-
- # different thread context
- result = nil
- Thread.new{
- obj = c.new
- obj.grep(/(f..)/){
- result = $1
- }
- }.join # obj is created in another Thread
-
- assert_equal nil, result
- assert_equal expected_check1_result, obj.check1
- assert_equal 'foo', result
- assert_equal 'foo', $1
- end
-
-
def test_global_variable_0
assert_in_out_err(["-e", "$0='t'*1000;print $0"], "", /\At+\z/, [])
end
@@ -373,12 +280,6 @@ class TestVariable < Test::Unit::TestCase
v.instance_variable_set(:@foo, :bar)
end
- assert_raise_with_message(FrozenError, msg, "[Bug #19339]") do
- v.instance_eval do
- @a = 1
- end
- end
-
assert_nil EnvUtil.suppress_warning {v.instance_variable_get(:@foo)}
assert_not_send([v, :instance_variable_defined?, :@foo])
@@ -413,18 +314,6 @@ class TestVariable < Test::Unit::TestCase
assert_equal(%i(v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11), v, bug11674)
end
- def test_many_instance_variables
- objects = [Object.new, Hash.new, Module.new]
- objects.each do |obj|
- 1000.times do |i|
- obj.instance_variable_set("@var#{i}", i)
- end
- 1000.times do |i|
- assert_equal(i, obj.instance_variable_get("@var#{i}"))
- end
- end
- end
-
private
def with_kwargs_11(v1:, v2:, v3:, v4:, v5:, v6:, v7:, v8:, v9:, v10:, v11:)
local_variables
diff --git a/test/ruby/test_vm_dump.rb b/test/ruby/test_vm_dump.rb
index 9c06ec14fb..679ce94b91 100644
--- a/test/ruby/test_vm_dump.rb
+++ b/test/ruby/test_vm_dump.rb
@@ -3,7 +3,7 @@ require 'test/unit'
class TestVMDump < Test::Unit::TestCase
def assert_darwin_vm_dump_works(args)
- omit if RUBY_PLATFORM !~ /darwin/
+ skip if RUBY_PLATFORM !~ /darwin/
assert_in_out_err(args, "", [], /^\[IMPORTANT\]/)
end
diff --git a/test/ruby/test_weakkeymap.rb b/test/ruby/test_weakkeymap.rb
deleted file mode 100644
index 799cee2d75..0000000000
--- a/test/ruby/test_weakkeymap.rb
+++ /dev/null
@@ -1,144 +0,0 @@
-# frozen_string_literal: false
-require 'test/unit'
-
-class TestWeakKeyMap < Test::Unit::TestCase
- def setup
- @wm = ObjectSpace::WeakKeyMap.new
- end
-
- def test_map
- x = Object.new
- k = "foo"
- @wm[k] = x
- assert_same(x, @wm[k])
- assert_same(x, @wm["FOO".downcase])
- end
-
- def test_aset_const
- x = Object.new
- 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[2**128] = x }
- assert_raise(ArgumentError) { @wm[1.23] = x }
- assert_raise(ArgumentError) { @wm[:foo] = x }
- assert_raise(ArgumentError) { @wm["foo#{rand}".to_sym] = x }
- end
-
- def test_getkey
- k = "foo"
- @wm[k] = true
- assert_same(k, @wm.getkey("FOO".downcase))
- end
-
- def test_key?
- assert_weak_include(:key?, "foo")
- assert_not_send([@wm, :key?, "bar"])
- end
-
- def test_delete
- k1 = "foo"
- x1 = Object.new
- @wm[k1] = x1
- assert_equal x1, @wm[k1]
- assert_equal x1, @wm.delete(k1)
- assert_nil @wm[k1]
- assert_nil @wm.delete(k1)
-
- fallback = @wm.delete(k1) do |key|
- assert_equal k1, key
- 42
- end
- assert_equal 42, fallback
- end
-
- def test_clear
- k = "foo"
- @wm[k] = true
- assert @wm[k]
- assert_same @wm, @wm.clear
- refute @wm[k]
- end
-
- def test_inspect
- x = Object.new
- k = Object.new
- @wm[k] = x
- assert_match(/\A\#<#{@wm.class.name}:[\dxa-f]+ size=\d+>\z/, @wm.inspect)
-
- 1000.times do |i|
- @wm[i.to_s] = Object.new
- @wm.inspect
- end
- assert_match(/\A\#<#{@wm.class.name}:[\dxa-f]+ size=\d+>\z/, @wm.inspect)
- end
-
- def test_no_hash_method
- k = BasicObject.new
- assert_raise NoMethodError do
- @wm[k] = 42
- end
- end
-
- def test_frozen_object
- o = Object.new.freeze
- assert_nothing_raised(FrozenError) {@wm[o] = 'foo'}
- assert_nothing_raised(FrozenError) {@wm['foo'] = o}
- end
-
- def test_inconsistent_hash_key
- assert_no_memory_leak [], '', <<~RUBY
- class BadHash
- def initialize
- @hash = 0
- end
-
- def hash
- @hash += 1
- end
- end
-
- k = BadHash.new
- wm = ObjectSpace::WeakKeyMap.new
-
- 100_000.times do |i|
- wm[k] = i
- end
- RUBY
- end
-
- def test_compaction
- omit "compaction is not supported on this platform" unless GC.respond_to?(:compact)
-
- assert_separately(%w(-robjspace), <<-'end;')
- wm = ObjectSpace::WeakKeyMap.new
- key = Object.new
- val = Object.new
- wm[key] = val
-
- GC.verify_compaction_references(expand_heap: true, toward: :empty)
-
- assert_equal(val, wm[key])
- end;
- end
-
- def test_gc_compact_stress
- EnvUtil.under_gc_compact_stress { ObjectSpace::WeakKeyMap.new }
- end
-
- private
-
- def assert_weak_include(m, k, n = 100)
- if n > 0
- return assert_weak_include(m, k, n-1)
- end
- 1.times do
- x = Object.new
- @wm[k] = x
- assert_send([@wm, m, k])
- assert_send([@wm, m, "FOO".downcase])
- x = Object.new
- end
- end
-end
diff --git a/test/ruby/test_weakmap.rb b/test/ruby/test_weakmap.rb
index 0371afa77a..5ca6b0fbdd 100644
--- a/test/ruby/test_weakmap.rb
+++ b/test/ruby/test_weakmap.rb
@@ -59,7 +59,7 @@ class TestWeakMap < Test::Unit::TestCase
assert_weak_include(m, k)
end
GC.start
- pend('TODO: failure introduced from 837fd5e494731d7d44786f29e7d6e8c27029806f')
+ skip('TODO: failure introduced from r60440')
assert_not_send([@wm, m, k])
end
alias test_member? test_include?
@@ -82,22 +82,6 @@ class TestWeakMap < Test::Unit::TestCase
@wm.inspect)
end
- def test_delete
- k1 = "foo"
- x1 = Object.new
- @wm[k1] = x1
- assert_equal x1, @wm[k1]
- assert_equal x1, @wm.delete(k1)
- assert_nil @wm[k1]
- assert_nil @wm.delete(k1)
-
- fallback = @wm.delete(k1) do |key|
- assert_equal k1, key
- 42
- end
- assert_equal 42, fallback
- end
-
def test_each
m = __callee__[/test_(.*)/, 1]
x1 = Object.new
@@ -193,17 +177,14 @@ class TestWeakMap < Test::Unit::TestCase
end;
end
- def test_compaction
- omit "compaction is not supported on this platform" unless GC.respond_to?(:compact)
-
- # [Bug #19529]
+ def test_compaction_bug_19529
obj = Object.new
100.times do |i|
GC.compact
@wm[i] = obj
end
- assert_separately([], <<-'end;')
+ assert_separately(%w(--disable-gems), <<-'end;')
wm = ObjectSpace::WeakMap.new
obj = Object.new
100.times do
@@ -212,49 +193,5 @@ class TestWeakMap < Test::Unit::TestCase
end
GC.compact
end;
-
- assert_separately(%w(-robjspace), <<-'end;')
- wm = ObjectSpace::WeakMap.new
- key = Object.new
- val = Object.new
- wm[key] = val
-
- GC.verify_compaction_references(expand_heap: true, toward: :empty)
-
- assert_equal(val, wm[key])
- end;
-
- assert_separately(["-W0"], <<-'end;')
- wm = ObjectSpace::WeakMap.new
-
- ary = 10_000.times.map do
- o = Object.new
- wm[o] = 1
- o
- end
-
- GC.verify_compaction_references(expand_heap: true, toward: :empty)
- end;
- end
-
- def test_gc_compact_stress
- EnvUtil.under_gc_compact_stress { ObjectSpace::WeakMap.new }
- end
-
- def test_replaced_values_bug_19531
- a = "A".dup
- b = "B".dup
-
- @wm[1] = a
- @wm[1] = a
- @wm[1] = a
-
- @wm[1] = b
- assert_equal b, @wm[1]
-
- a = nil
- GC.start
-
- assert_equal b, @wm[1]
end
end
diff --git a/test/ruby/test_yjit.rb b/test/ruby/test_yjit.rb
index 55b86bea78..48b3e4acea 100644
--- a/test/ruby/test_yjit.rb
+++ b/test/ruby/test_yjit.rb
@@ -1,27 +1,17 @@
# frozen_string_literal: true
-#
-# This set of tests can be run with:
-# make test-all TESTS='test/ruby/test_yjit.rb'
-
require 'test/unit'
require 'envutil'
require 'tmpdir'
-require_relative '../lib/jit_support'
-
-return unless JITSupport.yjit_supported?
-require 'stringio'
+return unless defined?(RubyVM::YJIT) && RubyVM::YJIT.enabled?
# Tests for YJIT with assertions on compilation and side exits
-# insipired by the RJIT tests in test/ruby/test_rjit.rb
+# insipired by the MJIT tests in test/ruby/test_jit.rb
class TestYJIT < Test::Unit::TestCase
- running_with_yjit = defined?(RubyVM::YJIT) && RubyVM::YJIT.enabled?
-
def test_yjit_in_ruby_description
assert_includes(RUBY_DESCRIPTION, '+YJIT')
- end if running_with_yjit
+ end
- # Check that YJIT is in the version string
def test_yjit_in_version
[
%w(--version --yjit),
@@ -31,107 +21,33 @@ class TestYJIT < Test::Unit::TestCase
%w(--version --disable=yjit --yjit),
%w(--version --disable=yjit --enable-yjit),
%w(--version --disable=yjit --enable=yjit),
- %w(--version --jit),
- %w(--version --disable-jit --jit),
- %w(--version --disable-jit --enable-jit),
- %w(--version --disable-jit --enable=jit),
- %w(--version --disable=jit --yjit),
- %w(--version --disable=jit --enable-jit),
- %w(--version --disable=jit --enable=jit),
+ *([
+ %w(--version --jit),
+ %w(--version --disable-jit --jit),
+ %w(--version --disable-jit --enable-jit),
+ %w(--version --disable-jit --enable=jit),
+ %w(--version --disable=jit --yjit),
+ %w(--version --disable=jit --enable-jit),
+ %w(--version --disable=jit --enable=jit),
+ ] if RUBY_PLATFORM.start_with?('x86_64-') && RUBY_PLATFORM !~ /mswin|mingw|msys/),
].each do |version_args|
assert_in_out_err(version_args) do |stdout, stderr|
assert_equal(RUBY_DESCRIPTION, stdout.first)
assert_equal([], stderr)
end
end
- end if running_with_yjit
+ end
def test_command_line_switches
assert_in_out_err('--yjit-', '', [], /invalid option --yjit-/)
assert_in_out_err('--yjithello', '', [], /invalid option --yjithello/)
- #assert_in_out_err('--yjit-call-threshold', '', [], /--yjit-call-threshold needs an argument/)
- #assert_in_out_err('--yjit-call-threshold=', '', [], /--yjit-call-threshold needs an argument/)
- end
-
- def test_yjit_enable
- args = []
- args << "--disable=yjit" if RubyVM::YJIT.enabled?
- assert_separately(args, <<~RUBY)
- assert_false RubyVM::YJIT.enabled?
- assert_false RUBY_DESCRIPTION.include?("+YJIT")
-
- RubyVM::YJIT.enable
-
- assert_true RubyVM::YJIT.enabled?
- assert_true RUBY_DESCRIPTION.include?("+YJIT")
- RUBY
- end
-
- def test_yjit_enable_stats_false
- assert_separately(["--yjit-disable", "--yjit-stats"], <<~RUBY, ignore_stderr: true)
- assert_false RubyVM::YJIT.enabled?
- assert_nil RubyVM::YJIT.runtime_stats
-
- RubyVM::YJIT.enable
-
- assert_true RubyVM::YJIT.enabled?
- assert_true RubyVM::YJIT.runtime_stats[:all_stats]
- RUBY
- end
-
- def test_yjit_enable_stats_true
- args = []
- args << "--disable=yjit" if RubyVM::YJIT.enabled?
- assert_separately(args, <<~RUBY, ignore_stderr: true)
- assert_false RubyVM::YJIT.enabled?
- assert_nil RubyVM::YJIT.runtime_stats
-
- RubyVM::YJIT.enable(stats: true)
-
- assert_true RubyVM::YJIT.enabled?
- assert_true RubyVM::YJIT.runtime_stats[:all_stats]
- RUBY
- end
-
- def test_yjit_enable_stats_quiet
- assert_in_out_err(['--yjit-disable', '-e', 'RubyVM::YJIT.enable(stats: true)']) do |_stdout, stderr, _status|
- assert_not_empty stderr
- end
- assert_in_out_err(['--yjit-disable', '-e', 'RubyVM::YJIT.enable(stats: :quiet)']) do |_stdout, stderr, _status|
- assert_empty stderr
- end
- end
-
- def test_yjit_enable_with_call_threshold
- assert_separately(%w[--yjit-disable --yjit-call-threshold=1], <<~RUBY)
- def not_compiled = nil
- def will_compile = nil
- def compiled_counts = RubyVM::YJIT.runtime_stats&.dig(:compiled_iseq_count)
-
- not_compiled
- assert_nil compiled_counts
- assert_false RubyVM::YJIT.enabled?
-
- RubyVM::YJIT.enable
-
- will_compile
- assert compiled_counts > 0
- assert_true RubyVM::YJIT.enabled?
- RUBY
- end
-
- def test_yjit_enable_with_monkey_patch
- assert_separately(%w[--yjit-disable], <<~RUBY)
- # This lets rb_method_entry_at(rb_mKernel, ...) return NULL
- Kernel.prepend(Module.new)
-
- # This must not crash with "undefined optimized method!"
- RubyVM::YJIT.enable
- RUBY
+ assert_in_out_err('--yjit-call-threshold', '', [], /--yjit-call-threshold needs an argument/)
+ assert_in_out_err('--yjit-call-threshold=', '', [], /--yjit-call-threshold needs an argument/)
+ assert_in_out_err('--yjit-greedy-versioning=1', '', [], /warning: argument to --yjit-greedy-versioning is ignored/)
end
def test_yjit_stats_and_v_no_error
- _stdout, stderr, _status = invoke_ruby(%w(-v --yjit-stats), '', true, true)
+ _stdout, stderr, _status = EnvUtil.invoke_ruby(%w(-v --yjit-stats), '', true, true)
refute_includes(stderr, "NoMethodError")
end
@@ -143,7 +59,7 @@ class TestYJIT < Test::Unit::TestCase
end
assert_in_out_err([yjit_child_env, '-e puts RUBY_DESCRIPTION'], '', [RUBY_DESCRIPTION])
assert_in_out_err([yjit_child_env, '-e p RubyVM::YJIT.enabled?'], '', ['true'])
- end if running_with_yjit
+ end
def test_compile_setclassvariable
script = 'class Foo; def self.foo; @@foo = 1; end; end; Foo.foo'
@@ -165,10 +81,6 @@ class TestYJIT < Test::Unit::TestCase
assert_compiles(':foo', insns: %i[putobject], result: :foo)
end
- def test_compile_opt_succ
- assert_compiles('1.succ', insns: %i[opt_succ], result: 2)
- end
-
def test_compile_opt_not
assert_compiles('!false', insns: %i[opt_not], result: true)
assert_compiles('!nil', insns: %i[opt_not], result: true)
@@ -399,32 +311,6 @@ class TestYJIT < Test::Unit::TestCase
RUBY
end
- def test_string_concat_utf8
- assert_compiles(<<~RUBY, frozen_string_literal: true, result: true)
- def str_cat_utf8
- s = String.new
- 10.times { s << "✅" }
- s
- end
-
- str_cat_utf8 == "✅" * 10
- RUBY
- end
-
- def test_string_concat_ascii
- # Constant-get for classes (e.g. String, Encoding) can cause a side-exit in getinlinecache. For now, ignore exits.
- assert_compiles(<<~RUBY, exits: :any)
- str_arg = "b".encode(Encoding::ASCII)
- def str_cat_ascii(arg)
- s = String.new(encoding: Encoding::ASCII)
- 10.times { s << arg }
- s
- end
-
- str_cat_ascii(str_arg) == str_arg * 10
- RUBY
- end
-
def test_opt_length_in_method
assert_compiles(<<~RUBY, insns: %i[opt_length], result: 5)
def foo(str)
@@ -468,31 +354,8 @@ class TestYJIT < Test::Unit::TestCase
assert_compiles("'foo' =~ /(o)./; $2", insns: %i[getspecial], result: nil)
end
- def test_compile_getconstant
- assert_compiles(<<~RUBY, insns: %i[getconstant], result: [], call_threshold: 1)
- def get_argv(klass)
- klass::ARGV
- end
-
- get_argv(Object)
- RUBY
- end
-
- def test_compile_getconstant_with_sp_offset
- assert_compiles(<<~RUBY, insns: %i[getconstant], result: 2, call_threshold: 1)
- class Foo
- Bar = 1
- end
-
- 2.times do
- s = Foo # this opt_getconstant_path needs warmup, so 2.times is needed
- Class.new(Foo).const_set(:Bar, s::Bar)
- end
- RUBY
- end
-
- def test_compile_opt_getconstant_path
- assert_compiles(<<~RUBY, insns: %i[opt_getconstant_path], result: 123, call_threshold: 2)
+ def test_compile_opt_getinlinecache
+ assert_compiles(<<~RUBY, insns: %i[opt_getinlinecache], result: 123, min_calls: 2)
def get_foo
FOO
end
@@ -504,8 +367,8 @@ class TestYJIT < Test::Unit::TestCase
RUBY
end
- def test_opt_getconstant_path_slowpath
- assert_compiles(<<~RUBY, exits: { opt_getconstant_path: 1 }, result: [42, 42, 1, 1], call_threshold: 2)
+ def test_opt_getinlinecache_slowpath
+ assert_compiles(<<~RUBY, exits: { opt_getinlinecache: 1 }, result: [42, 42, 1, 1], min_calls: 2)
class A
FOO = 42
class << self
@@ -532,34 +395,8 @@ class TestYJIT < Test::Unit::TestCase
RUBY
end
- def test_opt_getconstant_path_general
- assert_compiles(<<~RUBY, result: [1, 1])
- module Base
- Const = 1
- end
-
- class Sub
- def const
- _const = nil # make a non-entry block for opt_getconstant_path
- Const
- end
-
- def self.const_missing(n)
- Base.const_get(n)
- end
- end
-
-
- sub = Sub.new
- result = []
- result << sub.const # generate the general case
- result << sub.const # const_missing does not invalidate the block
- result
- RUBY
- end
-
def test_string_interpolation
- assert_compiles(<<~'RUBY', insns: %i[objtostring anytostring concatstrings], result: "foobar", call_threshold: 2)
+ assert_compiles(<<~'RUBY', insns: %i[objtostring anytostring concatstrings], result: "foobar", min_calls: 2)
def make_str(foo, bar)
"#{foo}#{bar}"
end
@@ -615,249 +452,6 @@ class TestYJIT < Test::Unit::TestCase
RUBY
end
- def test_getblockparam
- assert_compiles(<<~'RUBY', insns: [:getblockparam])
- def foo &blk
- 2.times do
- blk
- end
- end
-
- foo {}
- foo {}
- RUBY
- end
-
- def test_getblockparamproxy
- assert_compiles(<<~'RUBY', insns: [:getblockparamproxy], exits: {})
- def foo &blk
- p blk.call
- p blk.call
- end
-
- foo { 1 }
- foo { 2 }
- RUBY
- end
-
- def test_ifunc_getblockparamproxy
- assert_compiles(<<~'RUBY', insns: [:getblockparamproxy], exits: {})
- class Foo
- include Enumerable
-
- def each(&block)
- block.call 1
- block.call 2
- block.call 3
- end
- end
-
- foo = Foo.new
- foo.map { _1 * 2 }
- foo.map { _1 * 2 }
- RUBY
- end
-
- def test_send_blockarg
- assert_compiles(<<~'RUBY', insns: [:getblockparamproxy, :send], exits: {})
- def bar
- end
-
- def foo &blk
- bar(&blk)
- bar(&blk)
- end
-
- foo
- foo
-
- foo { }
- foo { }
- RUBY
- end
-
- def test_send_splat
- assert_compiles(<<~'RUBY', result: "3#1,2,3/P", exits: {})
- def internal_method(*args)
- "#{args.size}##{args.join(",")}"
- end
-
- def jit_method
- send(:internal_method, *[1, 2, 3]) + "/P"
- end
-
- jit_method
- RUBY
- end
-
- def test_send_multiarg
- assert_compiles(<<~'RUBY', result: "3#1,2,3/Q")
- def internal_method(*args)
- "#{args.size}##{args.join(",")}"
- end
-
- def jit_method
- send(:internal_method, 1, 2, 3) + "/Q"
- end
-
- jit_method
- RUBY
- end
-
- def test_send_kwargs
- # For now, this side-exits when calls include keyword args
- assert_compiles(<<~'RUBY', result: "2#a:1,b:2/A")
- def internal_method(**kw)
- "#{kw.size}##{kw.keys.map { |k| "#{k}:#{kw[k]}" }.join(",")}"
- end
-
- def jit_method
- send(:internal_method, a: 1, b: 2) + "/A"
- end
- jit_method
- RUBY
- end
-
- def test_send_kwargs_in_receiver_only
- assert_compiles(<<~'RUBY', result: "0/RK", exits: {})
- def internal_method(**kw)
- "#{kw.size}"
- end
-
- def jit_method
- send(:internal_method) + "/RK"
- end
- jit_method
- RUBY
- end
-
- def test_send_with_underscores
- assert_compiles(<<~'RUBY', result: "0/RK", exits: {})
- def internal_method(**kw)
- "#{kw.size}"
- end
-
- def jit_method
- __send__(:internal_method) + "/RK"
- end
- jit_method
- RUBY
- end
-
- def test_send_kwargs_splat
- # For now, this side-exits when calling with a splat
- assert_compiles(<<~'RUBY', result: "2#a:1,b:2/B")
- def internal_method(**kw)
- "#{kw.size}##{kw.keys.map { |k| "#{k}:#{kw[k]}" }.join(",")}"
- end
-
- def jit_method
- send(:internal_method, **{ a: 1, b: 2 }) + "/B"
- end
- jit_method
- RUBY
- end
-
- def test_send_block
- # Setlocal_wc_0 sometimes side-exits on write barrier
- assert_compiles(<<~'RUBY', result: "b:n/b:y/b:y/b:n")
- def internal_method(&b)
- "b:#{block_given? ? "y" : "n"}"
- end
-
- def jit_method
- b7 = proc { 7 }
- [
- send(:internal_method),
- send(:internal_method, &b7),
- send(:internal_method) { 7 },
- send(:internal_method, &nil),
- ].join("/")
- end
- jit_method
- RUBY
- end
-
- def test_send_block_calling
- assert_compiles(<<~'RUBY', result: "1a2", exits: {})
- def internal_method
- out = yield
- "1" + out + "2"
- end
-
- def jit_method
- __send__(:internal_method) { "a" }
- end
- jit_method
- RUBY
- end
-
- def test_send_block_only_receiver
- assert_compiles(<<~'RUBY', result: "b:n", exits: {})
- def internal_method(&b)
- "b:#{block_given? ? "y" : "n"}"
- end
-
- def jit_method
- send(:internal_method)
- end
- jit_method
- RUBY
- end
-
- def test_send_block_only_sender
- assert_compiles(<<~'RUBY', result: "Y/Y/Y/Y", exits: {})
- def internal_method
- "Y"
- end
-
- def jit_method
- b7 = proc { 7 }
- [
- send(:internal_method),
- send(:internal_method, &b7),
- send(:internal_method) { 7 },
- send(:internal_method, &nil),
- ].join("/")
- end
- jit_method
- RUBY
- end
-
- def test_multisend
- assert_compiles(<<~'RUBY', result: "77")
- def internal_method
- "7"
- end
-
- def jit_method
- send(:send, :internal_method) + send(:send, :send, :internal_method)
- end
- jit_method
- RUBY
- end
-
- def test_getivar_opt_plus
- assert_no_exits(<<~RUBY)
- class TheClass
- def initialize
- @levar = 1
- end
-
- def get_sum
- sum = 0
- # The type of levar is unknown,
- # but this still should not exit
- sum += @levar
- sum
- end
- end
-
- obj = TheClass.new
- obj.get_sum
- RUBY
- end
-
def test_super_iseq
assert_compiles(<<~'RUBY', insns: %i[invokesuper opt_plus opt_mult], result: 15)
class A
@@ -876,25 +470,6 @@ class TestYJIT < Test::Unit::TestCase
RUBY
end
- def test_super_with_alias
- assert_compiles(<<~'RUBY', insns: %i[invokesuper opt_plus opt_mult], result: 15)
- class A
- def foo = 1 + 2
- end
-
- module M
- def foo = super() * 5
- alias bar foo
-
- def foo = :bad
- end
-
- A.prepend M
-
- A.new.bar
- RUBY
- end
-
def test_super_cfunc
assert_compiles(<<~'RUBY', insns: %i[invokesuper], result: "Hello")
class Gnirts < String
@@ -913,7 +488,7 @@ class TestYJIT < Test::Unit::TestCase
# Tests calling a variadic cfunc with many args
def test_build_large_struct
- assert_compiles(<<~RUBY, insns: %i[opt_send_without_block], call_threshold: 2)
+ assert_compiles(<<~RUBY, insns: %i[opt_send_without_block], min_calls: 2)
::Foo = Struct.new(:a, :b, :c, :d, :e, :f, :g, :h)
def build_foo
@@ -947,15 +522,8 @@ class TestYJIT < Test::Unit::TestCase
RUBY
end
- def test_cfunc_kwarg
- assert_no_exits('{}.store(:value, foo: 123)')
- assert_no_exits('{}.store(:value, foo: 123, bar: 456, baz: 789)')
- assert_no_exits('{}.merge(foo: 123)')
- assert_no_exits('{}.merge(foo: 123, bar: 456, baz: 789)')
- end
-
- # regression test simplified from URI::Generic#hostname=
def test_ctx_different_mappings
+ # regression test simplified from URI::Generic#hostname=
assert_compiles(<<~'RUBY', frozen_string_literal: true)
def foo(v)
!(v&.start_with?('[')) && v&.index(':')
@@ -991,553 +559,12 @@ class TestYJIT < Test::Unit::TestCase
RUBY
end
- def test_int_equal
- assert_compiles(<<~'RUBY', exits: :any, result: [true, false, true, false, true, false, true, false])
- def eq(a, b)
- a == b
- end
-
- def eqq(a, b)
- a === b
- end
-
- big1 = 2 ** 65
- big2 = big1 + 1
- [eq(1, 1), eq(1, 2), eq(big1, big1), eq(big1, big2), eqq(1, 1), eqq(1, 2), eqq(big1, big1), eqq(big1, big2)]
- RUBY
- end
-
- def test_opt_case_dispatch
- assert_compiles(<<~'RUBY', exits: :any, result: [:"1", "2", 3])
- def case_dispatch(val)
- case val
- when 1
- :"#{val}"
- when 2
- "#{val}"
- else
- val
- end
- end
-
- [case_dispatch(1), case_dispatch(2), case_dispatch(3)]
- RUBY
- end
-
- def test_code_gc
- assert_compiles(code_gc_helpers + <<~'RUBY', exits: :any, result: :ok)
- return :not_paged unless add_pages(100) # prepare freeable pages
- RubyVM::YJIT.code_gc # first code GC
- return :not_compiled1 unless compiles { nil } # should be JITable again
-
- RubyVM::YJIT.code_gc # second code GC
- return :not_compiled2 unless compiles { nil } # should be JITable again
-
- code_gc_count = RubyVM::YJIT.runtime_stats[:code_gc_count]
- return :"code_gc_#{code_gc_count}" if code_gc_count != 2
-
- :ok
- RUBY
- end
-
- def test_on_stack_code_gc_call
- assert_compiles(code_gc_helpers + <<~'RUBY', exits: :any, result: :ok)
- fiber = Fiber.new {
- # Loop to call the same basic block again after Fiber.yield
- while true
- Fiber.yield(nil.to_i)
- end
- }
-
- return :not_paged1 unless add_pages(400) # go to a page without initial ocb code
- return :broken_resume1 if fiber.resume != 0 # JIT the fiber
- RubyVM::YJIT.code_gc # first code GC, which should not free the fiber page
- return :broken_resume2 if fiber.resume != 0 # The code should be still callable
-
- code_gc_count = RubyVM::YJIT.runtime_stats[:code_gc_count]
- return :"code_gc_#{code_gc_count}" if code_gc_count != 1
-
- :ok
- RUBY
- end
-
- def test_on_stack_code_gc_twice
- assert_compiles(code_gc_helpers + <<~'RUBY', exits: :any, result: :ok)
- fiber = Fiber.new {
- # Loop to call the same basic block again after Fiber.yield
- while Fiber.yield(nil.to_i); end
- }
-
- return :not_paged1 unless add_pages(400) # go to a page without initial ocb code
- return :broken_resume1 if fiber.resume(true) != 0 # JIT the fiber
- RubyVM::YJIT.code_gc # first code GC, which should not free the fiber page
-
- return :not_paged2 unless add_pages(300) # add some stuff to be freed
- # Not calling fiber.resume here to test the case that the YJIT payload loses some
- # information at the previous code GC. The payload should still be there, and
- # thus we could know the fiber ISEQ is still on stack on this second code GC.
- RubyVM::YJIT.code_gc # second code GC, which should still not free the fiber page
-
- return :not_paged3 unless add_pages(200) # attempt to overwrite the fiber page (it shouldn't)
- return :broken_resume2 if fiber.resume(true) != 0 # The fiber code should be still fine
-
- return :broken_resume3 if fiber.resume(false) != nil # terminate the fiber
- RubyVM::YJIT.code_gc # third code GC, freeing a page that used to be on stack
-
- return :not_paged4 unless add_pages(100) # check everything still works
-
- code_gc_count = RubyVM::YJIT.runtime_stats[:code_gc_count]
- return :"code_gc_#{code_gc_count}" if code_gc_count != 3
-
- :ok
- RUBY
- end
-
- def test_disable_code_gc_with_many_iseqs
- assert_compiles(code_gc_helpers + <<~'RUBY', exits: :any, result: :ok, mem_size: 1, code_gc: false)
- fiber = Fiber.new {
- # Loop to call the same basic block again after Fiber.yield
- while true
- Fiber.yield(nil.to_i)
- end
- }
-
- return :not_paged1 unless add_pages(250) # use some pages
- return :broken_resume1 if fiber.resume != 0 # leave an on-stack code as well
-
- add_pages(2000) # use a whole lot of pages to run out of 1MiB
- return :broken_resume2 if fiber.resume != 0 # on-stack code should be callable
-
- code_gc_count = RubyVM::YJIT.runtime_stats[:code_gc_count]
- return :"code_gc_#{code_gc_count}" if code_gc_count != 0
-
- :ok
- RUBY
- end
-
- def test_code_gc_with_many_iseqs
- assert_compiles(code_gc_helpers + <<~'RUBY', exits: :any, result: :ok, mem_size: 1, code_gc: true)
- fiber = Fiber.new {
- # Loop to call the same basic block again after Fiber.yield
- while true
- Fiber.yield(nil.to_i)
- end
- }
-
- return :not_paged1 unless add_pages(250) # use some pages
- return :broken_resume1 if fiber.resume != 0 # leave an on-stack code as well
-
- add_pages(2000) # use a whole lot of pages to run out of 1MiB
- return :broken_resume2 if fiber.resume != 0 # on-stack code should be callable
-
- code_gc_count = RubyVM::YJIT.runtime_stats[:code_gc_count]
- return :"code_gc_#{code_gc_count}" if code_gc_count == 0
-
- :ok
- RUBY
- end
-
- def test_code_gc_with_auto_compact
- assert_compiles((code_gc_helpers + <<~'RUBY'), exits: :any, result: :ok, mem_size: 1, code_gc: true)
- # Test ISEQ moves in the middle of code GC
- GC.auto_compact = true
-
- fiber = Fiber.new {
- # Loop to call the same basic block again after Fiber.yield
- while true
- Fiber.yield(nil.to_i)
- end
- }
-
- return :not_paged1 unless add_pages(250) # use some pages
- return :broken_resume1 if fiber.resume != 0 # leave an on-stack code as well
-
- add_pages(2000) # use a whole lot of pages to run out of 1MiB
- return :broken_resume2 if fiber.resume != 0 # on-stack code should be callable
-
- code_gc_count = RubyVM::YJIT.runtime_stats[:code_gc_count]
- return :"code_gc_#{code_gc_count}" if code_gc_count == 0
-
- :ok
- RUBY
- end
-
- def test_code_gc_partial_last_page
- # call_threshold: 2 to avoid JIT-ing code_gc itself. If code_gc were JITed right before
- # code_gc is called, the last page would be on stack.
- assert_compiles(<<~'RUBY', exits: :any, result: :ok, call_threshold: 2)
- # Leave a bunch of off-stack pages
- i = 0
- while i < 1000
- eval("x = proc { 1.to_s }; x.call; x.call")
- i += 1
- end
-
- # On Linux, memory page size != code page size. So the last code page could be partially
- # mapped. This call tests that assertions and other things work fine under the situation.
- RubyVM::YJIT.code_gc
-
- :ok
- RUBY
- end
-
- def test_trace_script_compiled # not ISEQ_TRACE_EVENTS
- assert_compiles(<<~'RUBY', exits: :any, result: :ok)
- @eval_counter = 0
- def eval_script
- eval('@eval_counter += 1')
- end
-
- @trace_counter = 0
- trace = TracePoint.new(:script_compiled) do |t|
- @trace_counter += 1
- end
-
- eval_script # JIT without TracePoint
- trace.enable
- eval_script # call with TracePoint
- trace.disable
-
- return :"eval_#{@eval_counter}" if @eval_counter != 2
- return :"trace_#{@trace_counter}" if @trace_counter != 1
-
- :ok
- RUBY
- end
-
- def test_trace_b_call # ISEQ_TRACE_EVENTS
- assert_compiles(<<~'RUBY', exits: :any, result: :ok)
- @call_counter = 0
- def block_call
- 1.times { @call_counter += 1 }
- end
-
- @trace_counter = 0
- trace = TracePoint.new(:b_call) do |t|
- @trace_counter += 1
- end
-
- block_call # JIT without TracePoint
- trace.enable
- block_call # call with TracePoint
- trace.disable
-
- return :"call_#{@call_counter}" if @call_counter != 2
- return :"trace_#{@trace_counter}" if @trace_counter != 1
-
- :ok
- RUBY
- end
-
- def test_send_to_call
- assert_compiles(<<~'RUBY', result: :ok)
- ->{ :ok }.send(:call)
- RUBY
- end
-
- def test_invokeblock_many_locals
- # [Bug #19299]
- assert_compiles(<<~'RUBY', result: :ok)
- def foo
- yield
- end
-
- foo do
- a1=a2=a3=a4=a5=a6=a7=a8=a9=a10=a11=a12=a13=a14=a15=a16=a17=a18=a19=a20=a21=a22=a23=a24=a25=a26=a27=a28=a29=a30 = :ok
- a30
- end
- RUBY
- end
-
- def test_bug_19316
- n = 2 ** 64
- # foo's extra param and the splats are relevant
- assert_compiles(<<~'RUBY', result: [[n, -n], [n, -n]], exits: :any)
- def foo(_, a, b, c)
- [a & b, ~c]
- end
-
- n = 2 ** 64
- args = [0, -n, n, n-1]
-
- GC.stress = true
- [foo(*args), foo(*args)]
- RUBY
- end
-
- def test_gc_compact_cyclic_branch
- assert_compiles(<<~'RUBY', result: 2)
- def foo
- i = 0
- while i < 2
- i += 1
- end
- i
- end
-
- foo
- GC.compact
- foo
- RUBY
- end
-
- def test_invalidate_cyclic_branch
- assert_compiles(<<~'RUBY', result: 2, exits: { opt_plus: 1 })
- def foo
- i = 0
- while i < 2
- i += 1
- end
- i
- end
-
- foo
- class Integer
- def +(x) = self - -x
- end
- foo
- RUBY
- end
-
- def test_tracing_str_uplus
- assert_compiles(<<~RUBY, frozen_string_literal: true, result: :ok, exits: { putspecialobject: 1, definemethod: 1 })
- def str_uplus
- _ = 1
- _ = 2
- ret = [+"frfr", __LINE__]
- _ = 3
- _ = 4
-
- ret
- end
-
- str_uplus
- require 'objspace'
- ObjectSpace.trace_object_allocations_start
-
- str, expected_line = str_uplus
- alloc_line = ObjectSpace.allocation_sourceline(str)
-
- if expected_line == alloc_line
- :ok
- else
- [expected_line, alloc_line]
- end
- RUBY
- end
-
- def test_str_uplus_subclass
- assert_compiles(<<~RUBY, frozen_string_literal: true, result: :subclass)
- class S < String
- def encoding
- :subclass
- end
- end
-
- def test(str)
- (+str).encoding
- end
-
- test ""
- test S.new
- RUBY
- end
-
- def test_return_to_invalidated_block
- # [Bug #19463]
- assert_compiles(<<~RUBY, result: [1, 1, :ugokanai], exits: { definesmethod: 1, getlocal_WC_0: 1 })
- klass = Class.new do
- def self.lookup(hash, key) = hash[key]
-
- def self.foo(a, b) = []
-
- def self.test(hash, key)
- [lookup(hash, key), key, "".freeze]
- # 05 opt_send_without_block :lookup
- # 07 getlocal_WC_0 :hash
- # 09 opt_str_freeze ""
- # 12 newarray 3
- # 14 leave
- #
- # YJIT will put instructions (07..14) into a block.
- # When String#freeze is redefined from within lookup(),
- # the return address to the block is still on-stack. We rely
- # on invalidation patching the code at the return address
- # to service this situation correctly.
- end
- end
-
- # get YJIT to compile test()
- hash = { 1 => [] }
- 31.times { klass.test(hash, 1) }
-
- # inject invalidation into lookup()
- evil_hash = Hash.new do |_, key|
- class String
- undef :freeze
- def freeze = :ugokanai
- end
-
- key
- end
- klass.test(evil_hash, 1)
- RUBY
- end
-
- def test_return_to_invalidated_frame
- assert_compiles(code_gc_helpers + <<~RUBY, exits: :any, result: :ok)
- def jump
- [] # something not inlined
- end
-
- def entry(code_gc)
- jit_exception(code_gc)
- jump # faulty jump after code GC. #jit_exception should not come back.
- end
-
- def jit_exception(code_gc)
- if code_gc
- tap do
- RubyVM::YJIT.code_gc
- break # jit_exec_exception catches TAG_BREAK and re-enters JIT code
- end
- end
- end
-
- add_pages(100)
- jump # Compile #jump in a non-first page
- add_pages(100)
- entry(false) # Compile #entry and its call to #jump in another page
- entry(true) # Free #jump but not #entry
-
- :ok
- RUBY
- end
-
- def test_setivar_on_class
- # Bug in https://github.com/ruby/ruby/pull/8152
- assert_compiles(<<~RUBY, result: :ok)
- class Base
- def self.or_equal
- @or_equal ||= Object.new
- end
- end
-
- Base.or_equal # ensure compiled
-
- class Child < Base
- end
-
- 200.times do |iv| # Need to be more than MAX_IVAR
- Child.instance_variable_set("@_iv_\#{iv}", Object.new)
- end
-
- Child.or_equal
- :ok
- RUBY
- end
-
- def test_nested_send
- #[Bug #19464]
- assert_compiles(<<~RUBY, result: [:ok, :ok], exits: { defineclass: 1 })
- klass = Class.new do
- class << self
- alias_method :my_send, :send
-
- def bar = :ok
-
- def foo = bar
- end
- end
-
- with_break = -> { break klass.send(:my_send, :foo) }
- wo_break = -> { klass.send(:my_send, :foo) }
-
- [with_break[], wo_break[]]
- RUBY
- end
-
- def test_str_concat_encoding_mismatch
- assert_compiles(<<~'RUBY', result: "incompatible character encodings: ASCII-8BIT and EUC-JP")
- def bar(a, b)
- a << b
- rescue => e
- e.message
- end
-
- def foo(a, b, h)
- h[nil]
- bar(a, b) # Ruby call, not set cfp->pc
- end
-
- h = Hash.new { nil }
- foo("\x80".b, "\xA1A1".force_encoding("EUC-JP"), h)
- foo("\x80".b, "\xA1A1".force_encoding("EUC-JP"), h)
- RUBY
- end
-
- def test_io_reopen_clobbering_singleton_class
- assert_compiles(<<~RUBY, result: [:ok, :ok], exits: { definesmethod: 1, opt_eq: 2 })
- def $stderr.to_i = :i
-
- def test = $stderr.to_i
-
- [test, test]
- $stderr.reopen($stderr.dup)
- [test, test].map { :ok unless _1 == :i }
- RUBY
- end
-
- def test_opt_aref_with
- assert_compiles(<<~RUBY, insns: %i[opt_aref_with], result: "bar")
- h = {"foo" => "bar"}
-
- h["foo"]
- RUBY
- end
-
- def test_proc_block_arg
- assert_compiles(<<~RUBY, result: [:proc, :no_block])
- def yield_if_given = block_given? ? yield : :no_block
-
- def call(block_arg = nil) = yield_if_given(&block_arg)
-
- [call(-> { :proc }), call]
- RUBY
- end
-
- def test_opt_mult_overflow
- assert_no_exits('0xfff_ffff_ffff_ffff * 0x10')
- end
-
- def test_disable_stats
- assert_in_out_err(%w[--yjit-stats --yjit-disable])
- end
-
- private
-
- def code_gc_helpers
- <<~'RUBY'
- def compiles(&block)
- failures = RubyVM::YJIT.runtime_stats[:compilation_failure]
- block.call
- failures == RubyVM::YJIT.runtime_stats[:compilation_failure]
- end
-
- def add_pages(num_jits)
- pages = RubyVM::YJIT.runtime_stats[:live_page_count]
- num_jits.times { return false unless eval('compiles { nil.to_i }') }
- pages.nil? || pages < RubyVM::YJIT.runtime_stats[:live_page_count]
- end
- RUBY
- end
-
def assert_no_exits(script)
assert_compiles(script)
end
ANY = Object.new
- def assert_compiles(test_script, insns: [], call_threshold: 1, stdout: nil, exits: {}, result: ANY, frozen_string_literal: nil, mem_size: nil, code_gc: false)
+ def assert_compiles(test_script, insns: [], min_calls: 1, stdout: nil, exits: {}, result: ANY, frozen_string_literal: nil)
reset_stats = <<~RUBY
RubyVM::YJIT.runtime_stats
RubyVM::YJIT.reset_stats!
@@ -1546,17 +573,29 @@ class TestYJIT < Test::Unit::TestCase
write_results = <<~RUBY
stats = RubyVM::YJIT.runtime_stats
- def collect_insns(iseq)
- insns = RubyVM::YJIT.insns_compiled(iseq)
- iseq.each_child { |c| insns.concat collect_insns(c) }
- insns
+ def collect_blocks(blocks)
+ blocks.sort_by(&:address).map { |b| [b.iseq_start_index, b.iseq_end_index] }
+ end
+
+ def collect_iseqs(iseq)
+ iseq_array = iseq.to_a
+ insns = iseq_array.last.grep(Array)
+ blocks = RubyVM::YJIT.blocks_for(iseq)
+ h = {
+ name: iseq_array[5],
+ insns: insns,
+ blocks: collect_blocks(blocks),
+ }
+ arr = [h]
+ iseq.each_child { |c| arr.concat collect_iseqs(c) }
+ arr
end
iseq = RubyVM::InstructionSequence.of(_test_proc)
IO.open(3).write Marshal.dump({
result: #{result == ANY ? "nil" : "result"},
stats: stats,
- insns: collect_insns(iseq),
+ iseqs: collect_iseqs(iseq),
disasm: iseq.disasm
})
RUBY
@@ -1571,7 +610,7 @@ class TestYJIT < Test::Unit::TestCase
#{write_results}
RUBY
- status, out, err, stats = eval_with_jit(script, call_threshold:, mem_size:, code_gc:)
+ status, out, err, stats = eval_with_jit(script, min_calls: min_calls)
assert status.success?, "exited with status #{status.to_i}, stderr:\n#{err}"
@@ -1582,88 +621,83 @@ class TestYJIT < Test::Unit::TestCase
end
runtime_stats = stats[:stats]
- insns_compiled = stats[:insns]
+ iseqs = stats[:iseqs]
disasm = stats[:disasm]
- # Check that exit counts are as expected
- # Full stats are only available when --enable-yjit=dev
+ # Only available when RUBY_DEBUG enabled
if runtime_stats[:all_stats]
recorded_exits = runtime_stats.select { |k, v| k.to_s.start_with?("exit_") }
recorded_exits = recorded_exits.reject { |k, v| v == 0 }
recorded_exits.transform_keys! { |k| k.to_s.gsub("exit_", "").to_sym }
- # Exits can be specified as a hash of stat-name symbol to integer for exact exits.
- # or stat-name symbol to range if the number of side exits might vary (e.g. write
- # barriers, cache misses.)
- if exits != :any &&
- exits != recorded_exits &&
- (exits.keys != recorded_exits.keys || !exits.all? { |k, v| v === recorded_exits[k] }) # triple-equal checks range membership or integer equality
- stats_reasons = StringIO.new
- ::RubyVM::YJIT.send(:_print_stats_reasons, runtime_stats, stats_reasons)
- stats_reasons = stats_reasons.string
- flunk <<~EOM
- Expected #{exits.empty? ? "no" : exits.inspect} exits, but got:
- #{recorded_exits.inspect}
- Reasons:
- #{stats_reasons}
- EOM
+ if exits != :any && exits != recorded_exits
+ flunk "Expected #{exits.empty? ? "no" : exits.inspect} exits" \
+ ", but got\n#{recorded_exits.inspect}"
end
end
- # Only available when --enable-yjit=dev
+ # Only available when RUBY_DEBUG enabled
if runtime_stats[:all_stats]
missed_insns = insns.dup
+ all_compiled_blocks = {}
+ iseqs.each do |iseq|
+ compiled_blocks = iseq[:blocks].map { |from, to| (from...to) }
+ all_compiled_blocks[iseq[:name]] = compiled_blocks
+ compiled_insns = iseq[:insns]
+ next_idx = 0
+ compiled_insns.map! do |insn|
+ # TODO: not sure this is accurate for determining insn size
+ idx = next_idx
+ next_idx += insn.length
+ [idx, *insn]
+ end
+
+ compiled_insns.each do |idx, op, *arguments|
+ next unless missed_insns.include?(op)
+ next unless compiled_blocks.any? { |block| block === idx }
- insns_compiled.each do |op|
- if missed_insns.include?(op)
# This instruction was compiled
missed_insns.delete(op)
end
end
unless missed_insns.empty?
- flunk "Expected to compile instructions #{missed_insns.join(", ")} but didn't.\niseq:\n#{disasm}"
+ flunk "Expected to compile instructions #{missed_insns.join(", ")} but didn't.\nCompiled ranges: #{all_compiled_blocks.inspect}\niseq:\n#{disasm}"
end
end
end
- def script_shell_encode(s)
- # We can't pass utf-8-encoded characters directly in a shell arg. But we can use Ruby \u constants.
- s.chars.map { |c| c.ascii_only? ? c : "\\u%x" % c.codepoints[0] }.join
- end
-
- def eval_with_jit(script, call_threshold: 1, timeout: 1000, mem_size: nil, code_gc: false)
+ def eval_with_jit(script, min_calls: 1, timeout: 1000)
args = [
"--disable-gems",
- "--yjit-call-threshold=#{call_threshold}",
- "--yjit-stats=quiet"
+ "--yjit-call-threshold=#{min_calls}",
+ "--yjit-stats"
]
- args << "--yjit-exec-mem-size=#{mem_size}" if mem_size
- args << "--yjit-code-gc" if code_gc
- args << "-e" << script_shell_encode(script)
+ args << "-e" << script
stats_r, stats_w = IO.pipe
- # Separate thread so we don't deadlock when
- # the child ruby blocks writing the stats to fd 3
- stats = ''
- stats_reader = Thread.new do
- stats = stats_r.read
- stats_r.close
- end
- out, err, status = invoke_ruby(args, '', true, true, timeout: timeout, ios: { 3 => stats_w })
+ out, err, status = EnvUtil.invoke_ruby(args,
+ '', true, true, timeout: timeout, ios: {3 => stats_w}
+ )
stats_w.close
- stats_reader.join(timeout)
+ stats = stats_r.read
stats = Marshal.load(stats) if !stats.empty?
+ stats_r.close
[status, out, err, stats]
- ensure
- stats_reader&.kill
- stats_reader&.join(timeout)
- stats_r&.close
- stats_w&.close
end
- # A wrapper of EnvUtil.invoke_ruby that uses RbConfig.ruby instead of EnvUtil.ruby
- # that might use a wrong Ruby depending on your environment.
- def invoke_ruby(*args, **kwargs)
- EnvUtil.invoke_ruby(*args, rubybin: RbConfig.ruby, **kwargs)
+ def test_bug_19316
+ n = 2 ** 64
+ # foo's extra param and the splats are relevant
+ assert_compiles(<<~'RUBY', result: [[n, -n], [n, -n]], exits: :any)
+ def foo(_, a, b, c)
+ [a & b, ~c]
+ end
+
+ n = 2 ** 64
+ args = [0, -n, n, n-1]
+
+ GC.stress = true
+ [foo(*args), foo(*args)]
+ RUBY
end
end
diff --git a/test/ruby/test_yjit_exit_locations.rb b/test/ruby/test_yjit_exit_locations.rb
deleted file mode 100644
index 816ab457ce..0000000000
--- a/test/ruby/test_yjit_exit_locations.rb
+++ /dev/null
@@ -1,96 +0,0 @@
-# frozen_string_literal: true
-#
-# This set of tests can be run with:
-# make test-all TESTS='test/ruby/test_yjit_exit_locations.rb'
-
-require 'test/unit'
-require 'envutil'
-require 'tmpdir'
-require_relative '../lib/jit_support'
-
-return unless JITSupport.yjit_supported?
-
-# Tests for YJIT with assertions on tracing exits
-# insipired by the RJIT tests in test/ruby/test_yjit.rb
-class TestYJITExitLocations < Test::Unit::TestCase
- def test_yjit_trace_exits_and_v_no_error
- _stdout, stderr, _status = EnvUtil.invoke_ruby(%w(-v --yjit-trace-exits), '', true, true)
- refute_includes(stderr, "NoMethodError")
- end
-
- def test_trace_exits_expandarray_splat
- assert_exit_locations('*arr = []')
- end
-
- private
-
- def assert_exit_locations(test_script)
- write_results = <<~RUBY
- IO.open(3).write Marshal.dump({
- enabled: RubyVM::YJIT.trace_exit_locations_enabled?,
- exit_locations: RubyVM::YJIT.exit_locations
- })
- RUBY
-
- script = <<~RUBY
- _test_proc = -> {
- #{test_script}
- }
- result = _test_proc.call
- #{write_results}
- RUBY
-
- run_script = eval_with_jit(script)
- # If stats are disabled when configuring, --yjit-exit-locations
- # can't be true. We don't want to check if exit_locations hash
- # is not empty because that could indicate a bug in the exit
- # locations collection.
- return unless run_script[:enabled]
- exit_locations = run_script[:exit_locations]
-
- assert exit_locations.key?(:raw)
- assert exit_locations.key?(:frames)
- assert exit_locations.key?(:lines)
- assert exit_locations.key?(:samples)
- assert exit_locations.key?(:missed_samples)
- assert exit_locations.key?(:gc_samples)
-
- assert_equal 0, exit_locations[:missed_samples]
- assert_equal 0, exit_locations[:gc_samples]
-
- assert_not_empty exit_locations[:raw]
- assert_not_empty exit_locations[:frames]
- assert_not_empty exit_locations[:lines]
-
- exit_locations[:frames].each do |frame_id, frame|
- assert frame.key?(:name)
- assert frame.key?(:file)
- assert frame.key?(:samples)
- assert frame.key?(:total_samples)
- assert frame.key?(:edges)
- end
- end
-
- def eval_with_jit(script)
- args = [
- "--disable-gems",
- "--yjit-call-threshold=1",
- "--yjit-trace-exits"
- ]
- args << "-e" << script_shell_encode(script)
- stats_r, stats_w = IO.pipe
- _out, _err, _status = EnvUtil.invoke_ruby(args,
- '', true, true, timeout: 1000, ios: { 3 => stats_w }
- )
- stats_w.close
- stats = stats_r.read
- stats = Marshal.load(stats) if !stats.empty?
- stats_r.close
- stats
- end
-
- def script_shell_encode(s)
- # We can't pass utf-8-encoded characters directly in a shell arg. But we can use Ruby \u constants.
- s.chars.map { |c| c.ascii_only? ? c : "\\u%x" % c.codepoints[0] }.join
- end
-end