aboutsummaryrefslogtreecommitdiffstats
path: root/spec/ruby/core
diff options
context:
space:
mode:
Diffstat (limited to 'spec/ruby/core')
-rw-r--r--spec/ruby/core/basicobject/instance_eval_spec.rb68
-rw-r--r--spec/ruby/core/enumerable/sum_spec.rb17
-rw-r--r--spec/ruby/core/io/gets_spec.rb2
-rw-r--r--spec/ruby/core/io/print_spec.rb25
-rw-r--r--spec/ruby/core/io/read_nonblock_spec.rb49
-rw-r--r--spec/ruby/core/io/read_spec.rb10
-rw-r--r--spec/ruby/core/io/readchar_spec.rb66
-rw-r--r--spec/ruby/core/io/readpartial_spec.rb15
-rw-r--r--spec/ruby/core/io/rewind_spec.rb15
-rw-r--r--spec/ruby/core/io/set_encoding_by_bom_spec.rb187
-rw-r--r--spec/ruby/core/io/set_encoding_spec.rb17
-rw-r--r--spec/ruby/core/io/shared/each.rb22
-rw-r--r--spec/ruby/core/io/shared/write.rb10
-rw-r--r--spec/ruby/core/io/sysread_spec.rb31
-rw-r--r--spec/ruby/core/io/syswrite_spec.rb10
-rw-r--r--spec/ruby/core/io/write_nonblock_spec.rb10
-rw-r--r--spec/ruby/core/io/write_spec.rb10
-rw-r--r--spec/ruby/core/kernel/p_spec.rb6
-rw-r--r--spec/ruby/core/method/fixtures/classes.rb24
-rw-r--r--spec/ruby/core/method/super_method_spec.rb28
-rw-r--r--spec/ruby/core/module/const_defined_spec.rb7
-rw-r--r--spec/ruby/core/module/define_method_spec.rb43
-rw-r--r--spec/ruby/core/module/fixtures/classes.rb8
-rw-r--r--spec/ruby/core/module/included_modules_spec.rb2
-rw-r--r--spec/ruby/core/module/instance_method_spec.rb34
-rw-r--r--spec/ruby/core/module/shared/class_eval.rb21
-rw-r--r--spec/ruby/core/string/split_spec.rb26
-rw-r--r--spec/ruby/core/thread/backtrace/location/absolute_path_spec.rb9
-rw-r--r--spec/ruby/core/thread/backtrace/location/fixtures/subdir/absolute_path_main_chdir.rb11
-rw-r--r--spec/ruby/core/thread/backtrace/location/fixtures/subdir/sibling.rb1
-rw-r--r--spec/ruby/core/unboundmethod/fixtures/classes.rb10
-rw-r--r--spec/ruby/core/unboundmethod/hash_spec.rb7
-rw-r--r--spec/ruby/core/unboundmethod/super_method_spec.rb25
33 files changed, 782 insertions, 44 deletions
diff --git a/spec/ruby/core/basicobject/instance_eval_spec.rb b/spec/ruby/core/basicobject/instance_eval_spec.rb
index b6a146095d..350b08a30e 100644
--- a/spec/ruby/core/basicobject/instance_eval_spec.rb
+++ b/spec/ruby/core/basicobject/instance_eval_spec.rb
@@ -20,12 +20,18 @@ describe "BasicObject#instance_eval" do
a.instance_eval('self').equal?(a).should be_true
end
- it "expects a block with no arguments" do
- -> { "hola".instance_eval }.should raise_error(ArgumentError)
+ it "raises an ArgumentError when no arguments and no block are given" do
+ -> { "hola".instance_eval }.should raise_error(ArgumentError, "wrong number of arguments (given 0, expected 1..3)")
end
- it "takes no arguments with a block" do
- -> { "hola".instance_eval(4, 5) {|a,b| a + b } }.should raise_error(ArgumentError)
+ it "raises an ArgumentError when a block and normal arguments are given" do
+ -> { "hola".instance_eval(4, 5) {|a,b| a + b } }.should raise_error(ArgumentError, "wrong number of arguments (given 2, expected 0)")
+ end
+
+ it "raises an ArgumentError when more than 3 arguments are given" do
+ -> {
+ "hola".instance_eval("1 + 1", "some file", 0, "bogus")
+ }.should raise_error(ArgumentError, "wrong number of arguments (given 4, expected 1..3)")
end
it "yields the object to the block" do
@@ -185,4 +191,58 @@ end
x.should == :value
end
+
+ it "converts string argument with #to_str method" do
+ source_code = Object.new
+ def source_code.to_str() "1" end
+
+ a = BasicObject.new
+ a.instance_eval(source_code).should == 1
+ end
+
+ it "raises ArgumentError if returned value is not String" do
+ source_code = Object.new
+ def source_code.to_str() :symbol end
+
+ a = BasicObject.new
+ -> { a.instance_eval(source_code) }.should raise_error(TypeError, /can't convert Object to String/)
+ end
+
+ it "converts filename argument with #to_str method" do
+ filename = Object.new
+ def filename.to_str() "file.rb" end
+
+ err = begin
+ Object.new.instance_eval("raise", filename)
+ rescue => e
+ e
+ end
+ err.backtrace.first.split(":")[0].should == "file.rb"
+ end
+
+ it "raises ArgumentError if returned value is not String" do
+ filename = Object.new
+ def filename.to_str() :symbol end
+
+ -> { Object.new.instance_eval("raise", filename) }.should raise_error(TypeError, /can't convert Object to String/)
+ end
+
+ it "converts lineno argument with #to_int method" do
+ lineno = Object.new
+ def lineno.to_int() 15 end
+
+ err = begin
+ Object.new.instance_eval("raise", "file.rb", lineno)
+ rescue => e
+ e
+ end
+ err.backtrace.first.split(":")[1].should == "15"
+ end
+
+ it "raises ArgumentError if returned value is not Integer" do
+ lineno = Object.new
+ def lineno.to_int() :symbol end
+
+ -> { Object.new.instance_eval("raise", "file.rb", lineno) }.should raise_error(TypeError, /can't convert Object to Integer/)
+ end
end
diff --git a/spec/ruby/core/enumerable/sum_spec.rb b/spec/ruby/core/enumerable/sum_spec.rb
index 4a978794e5..fc173e4173 100644
--- a/spec/ruby/core/enumerable/sum_spec.rb
+++ b/spec/ruby/core/enumerable/sum_spec.rb
@@ -22,8 +22,21 @@ describe 'Enumerable#sum' do
@enum.sum.should == 5/3r
end
- it 'takes a block to transform the elements' do
- @enum.sum { |element| element * 2 }.should == 10/3r
+ context 'with a block' do
+ it 'transforms the elements' do
+ @enum.sum { |element| element * 2 }.should == 10/3r
+ end
+
+ it 'does not destructure array elements' do
+ class << @enum
+ def each
+ yield [1,2]
+ yield [3]
+ end
+ end
+
+ @enum.sum(&:last).should == 5
+ end
end
# https://bugs.ruby-lang.org/issues/12217
diff --git a/spec/ruby/core/io/gets_spec.rb b/spec/ruby/core/io/gets_spec.rb
index b9f82f8133..07be99f400 100644
--- a/spec/ruby/core/io/gets_spec.rb
+++ b/spec/ruby/core/io/gets_spec.rb
@@ -213,6 +213,8 @@ describe "IO#gets" do
it "returns empty string when 0 passed as a limit" do
@io.gets(0).should == ""
+ @io.gets(nil, 0).should == ""
+ @io.gets("", 0).should == ""
end
end
diff --git a/spec/ruby/core/io/print_spec.rb b/spec/ruby/core/io/print_spec.rb
index 04e971ef6d..085852024c 100644
--- a/spec/ruby/core/io/print_spec.rb
+++ b/spec/ruby/core/io/print_spec.rb
@@ -3,16 +3,27 @@ require_relative 'fixtures/classes'
describe "IO#print" do
before :each do
- @old_separator = $\
- suppress_warning {$\ = '->'}
+ @old_record_separator = $\
+ @old_field_separator = $,
+ suppress_warning {
+ $\ = '->'
+ $, = '^^'
+ }
@name = tmp("io_print")
end
after :each do
- suppress_warning {$\ = @old_separator}
+ suppress_warning {
+ $\ = @old_record_separator
+ $, = @old_field_separator
+ }
rm_r @name
end
+ it "returns nil" do
+ touch(@name) { |f| f.print.should be_nil }
+ end
+
it "writes $_.to_s followed by $\\ (if any) to the stream if no arguments given" do
o = mock('o')
o.should_receive(:to_s).and_return("mockmockmock")
@@ -38,13 +49,15 @@ describe "IO#print" do
IO.read(@name).should == "hello#{$\}"
end
- it "writes each obj.to_s to the stream and appends $\\ (if any) given multiple objects" do
+ it "writes each obj.to_s to the stream separated by $, (if any) and appends $\\ (if any) given multiple objects" do
o, o2 = Object.new, Object.new
def o.to_s(); 'o'; end
def o2.to_s(); 'o2'; end
- touch(@name) { |f| f.print(o, o2) }
- IO.read(@name).should == "#{o.to_s}#{o2.to_s}#{$\}"
+ suppress_warning {
+ touch(@name) { |f| f.print(o, o2) }
+ }
+ IO.read(@name).should == "#{o.to_s}#{$,}#{o2.to_s}#{$\}"
end
it "raises IOError on closed stream" do
diff --git a/spec/ruby/core/io/read_nonblock_spec.rb b/spec/ruby/core/io/read_nonblock_spec.rb
index e50531d336..a62b75274c 100644
--- a/spec/ruby/core/io/read_nonblock_spec.rb
+++ b/spec/ruby/core/io/read_nonblock_spec.rb
@@ -55,6 +55,27 @@ describe "IO#read_nonblock" do
@read.read_nonblock(4).should == "hell"
end
+ it "reads after ungetc with data in the buffer" do
+ @write.write("foobar")
+ @read.set_encoding(
+ 'utf-8', universal_newline: false
+ )
+ c = @read.getc
+ @read.ungetc(c)
+ @read.read_nonblock(3).should == "foo"
+ @read.read_nonblock(3).should == "bar"
+ end
+
+ it "raises an exception after ungetc with data in the buffer and character conversion enabled" do
+ @write.write("foobar")
+ @read.set_encoding(
+ 'utf-8', universal_newline: true
+ )
+ c = @read.getc
+ @read.ungetc(c)
+ -> { @read.read_nonblock(3).should == "foo" }.should raise_error(IOError)
+ end
+
it "returns less data if that is all that is available" do
@write << "hello"
@read.read_nonblock(10).should == "hello"
@@ -70,6 +91,10 @@ describe "IO#read_nonblock" do
@read.read_nonblock(1).should == "1"
end
+ it "raises ArgumentError when length is less than 0" do
+ -> { @read.read_nonblock(-1) }.should raise_error(ArgumentError)
+ end
+
it "reads into the passed buffer" do
buffer = ""
@write.write("1")
@@ -84,6 +109,21 @@ describe "IO#read_nonblock" do
output.should equal(buffer)
end
+ it "discards the existing buffer content upon successful read" do
+ buffer = "existing content"
+ @write.write("hello world")
+ @write.close
+ @read.read_nonblock(11, buffer)
+ buffer.should == "hello world"
+ end
+
+ it "discards the existing buffer content upon error" do
+ buffer = "existing content"
+ @write.close
+ -> { @read.read_nonblock(1, buffer) }.should raise_error(EOFError)
+ buffer.should be_empty
+ end
+
it "raises IOError on closed stream" do
-> { IOSpecs.closed_io.read_nonblock(5) }.should raise_error(IOError)
end
@@ -96,4 +136,13 @@ describe "IO#read_nonblock" do
-> { @read.read_nonblock(5) }.should raise_error(EOFError)
end
+
+ it "preserves the encoding of the given buffer" do
+ buffer = ''.encode(Encoding::ISO_8859_1)
+ @write.write("abc")
+ @write.close
+ @read.read_nonblock(10, buffer)
+
+ buffer.encoding.should == Encoding::ISO_8859_1
+ end
end
diff --git a/spec/ruby/core/io/read_spec.rb b/spec/ruby/core/io/read_spec.rb
index 28cab13340..d34f7bd0eb 100644
--- a/spec/ruby/core/io/read_spec.rb
+++ b/spec/ruby/core/io/read_spec.rb
@@ -270,6 +270,13 @@ describe "IO#read" do
@io.read(nil, buf).should equal buf
end
+ it "returns the given buffer when there is nothing to read" do
+ buf = ""
+
+ @io.read
+ @io.read(nil, buf).should equal buf
+ end
+
it "coerces the second argument to string and uses it as a buffer" do
buf = "ABCDE"
obj = mock("buff")
@@ -312,6 +319,9 @@ describe "IO#read" do
-> { IOSpecs.closed_io.read }.should raise_error(IOError)
end
+ it "raises ArgumentError when length is less than 0" do
+ -> { @io.read(-1) }.should raise_error(ArgumentError)
+ end
platform_is_not :windows do
it "raises IOError when stream is closed by another thread" do
diff --git a/spec/ruby/core/io/readchar_spec.rb b/spec/ruby/core/io/readchar_spec.rb
index b5f762a846..a66773851a 100644
--- a/spec/ruby/core/io/readchar_spec.rb
+++ b/spec/ruby/core/io/readchar_spec.rb
@@ -1,6 +1,16 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+describe :io_readchar_internal_encoding, shared: true do
+ it "returns a transcoded String" do
+ @io.readchar.should == "あ"
+ end
+
+ it "sets the String encoding to the internal encoding" do
+ @io.readchar.encoding.should equal(Encoding::UTF_8)
+ end
+end
+
describe "IO#readchar" do
before :each do
@io = IOSpecs.io_fixture "lines.txt"
@@ -29,6 +39,62 @@ describe "IO#readchar" do
end
end
+describe "IO#readchar with internal encoding" do
+ after :each do
+ @io.close if @io
+ end
+
+ describe "not specified" do
+ before :each do
+ @io = IOSpecs.io_fixture "read_euc_jp.txt", "r:euc-jp"
+ end
+
+ it "does not transcode the String" do
+ @io.readchar.should == ("あ").encode(Encoding::EUC_JP)
+ end
+
+ it "sets the String encoding to the external encoding" do
+ @io.readchar.encoding.should equal(Encoding::EUC_JP)
+ end
+ end
+
+ describe "specified by open mode" do
+ before :each do
+ @io = IOSpecs.io_fixture "read_euc_jp.txt", "r:euc-jp:utf-8"
+ end
+
+ it_behaves_like :io_readchar_internal_encoding, nil
+ end
+
+ describe "specified by mode: option" do
+ before :each do
+ @io = IOSpecs.io_fixture "read_euc_jp.txt", mode: "r:euc-jp:utf-8"
+ end
+
+ it_behaves_like :io_readchar_internal_encoding, nil
+ end
+
+ describe "specified by internal_encoding: option" do
+ before :each do
+ options = { mode: "r",
+ internal_encoding: "utf-8",
+ external_encoding: "euc-jp" }
+ @io = IOSpecs.io_fixture "read_euc_jp.txt", options
+ end
+
+ it_behaves_like :io_readchar_internal_encoding, nil
+ end
+
+ describe "specified by encoding: option" do
+ before :each do
+ options = { mode: "r", encoding: "euc-jp:utf-8" }
+ @io = IOSpecs.io_fixture "read_euc_jp.txt", options
+ end
+
+ it_behaves_like :io_readchar_internal_encoding, nil
+ end
+end
+
describe "IO#readchar" do
before :each do
@io = IOSpecs.io_fixture "empty.txt"
diff --git a/spec/ruby/core/io/readpartial_spec.rb b/spec/ruby/core/io/readpartial_spec.rb
index 2b33a0d5b1..324ae0b6e6 100644
--- a/spec/ruby/core/io/readpartial_spec.rb
+++ b/spec/ruby/core/io/readpartial_spec.rb
@@ -59,7 +59,7 @@ describe "IO#readpartial" do
end
it "discards the existing buffer content upon successful read" do
- buffer = "existing"
+ buffer = "existing content"
@wr.write("hello world")
@wr.close
@rd.readpartial(11, buffer)
@@ -93,4 +93,17 @@ describe "IO#readpartial" do
@rd.readpartial(0).should == ""
end
+ it "clears and returns the given buffer if the length argument is 0" do
+ buffer = "existing content"
+ @rd.readpartial(0, buffer).should == buffer
+ buffer.should == ""
+ end
+
+ it "preserves the encoding of the given buffer" do
+ buffer = ''.encode(Encoding::ISO_8859_1)
+ @wr.write("abc")
+ @wr.close
+ @rd.readpartial(10, buffer)
+ buffer.encoding.should == Encoding::ISO_8859_1
+ end
end
diff --git a/spec/ruby/core/io/rewind_spec.rb b/spec/ruby/core/io/rewind_spec.rb
index 649041afaf..5579cbd988 100644
--- a/spec/ruby/core/io/rewind_spec.rb
+++ b/spec/ruby/core/io/rewind_spec.rb
@@ -18,6 +18,17 @@ describe "IO#rewind" do
@io.readline.should == "Voici la ligne une.\n"
end
+ it "positions the instance to the beginning of output for write-only IO" do
+ name = tmp("io_rewind_spec")
+ io = File.open(name, "w")
+ io.write("Voici la ligne une.\n")
+ io.rewind
+ io.pos.should == 0
+ ensure
+ io.close
+ rm_r name
+ end
+
it "positions the instance to the beginning of input and clears EOF" do
value = @io.read
@io.rewind
@@ -32,6 +43,10 @@ describe "IO#rewind" do
@io.lineno.should == 0
end
+ it "returns 0" do
+ @io.rewind.should == 0
+ end
+
it "raises IOError on closed stream" do
-> { IOSpecs.closed_io.rewind }.should raise_error(IOError)
end
diff --git a/spec/ruby/core/io/set_encoding_by_bom_spec.rb b/spec/ruby/core/io/set_encoding_by_bom_spec.rb
index b52d3a943a..92433d6640 100644
--- a/spec/ruby/core/io/set_encoding_by_bom_spec.rb
+++ b/spec/ruby/core/io/set_encoding_by_bom_spec.rb
@@ -12,45 +12,232 @@ describe "IO#set_encoding_by_bom" do
rm_r @name
end
+ it "returns nil if not readable" do
+ not_readable_io = new_io(@name, 'wb')
+
+ not_readable_io.set_encoding_by_bom.should be_nil
+ not_readable_io.external_encoding.should == Encoding::ASCII_8BIT
+ ensure
+ not_readable_io.close
+ end
+
it "returns the result encoding if found BOM UTF-8 sequence" do
+ File.binwrite(@name, "\u{FEFF}")
+
+ @io.set_encoding_by_bom.should == Encoding::UTF_8
+ @io.external_encoding.should == Encoding::UTF_8
+ @io.read.b.should == "".b
+ @io.rewind
+ @io.set_encoding(Encoding::ASCII_8BIT)
+
File.binwrite(@name, "\u{FEFF}abc")
@io.set_encoding_by_bom.should == Encoding::UTF_8
@io.external_encoding.should == Encoding::UTF_8
+ @io.read.b.should == "abc".b
end
it "returns the result encoding if found BOM UTF_16LE sequence" do
+ File.binwrite(@name, "\xFF\xFE")
+
+ @io.set_encoding_by_bom.should == Encoding::UTF_16LE
+ @io.external_encoding.should == Encoding::UTF_16LE
+ @io.read.b.should == "".b
+ @io.rewind
+ @io.set_encoding(Encoding::ASCII_8BIT)
+
File.binwrite(@name, "\xFF\xFEabc")
@io.set_encoding_by_bom.should == Encoding::UTF_16LE
@io.external_encoding.should == Encoding::UTF_16LE
+ @io.read.b.should == "abc".b
end
it "returns the result encoding if found BOM UTF_16BE sequence" do
+ File.binwrite(@name, "\xFE\xFF")
+
+ @io.set_encoding_by_bom.should == Encoding::UTF_16BE
+ @io.external_encoding.should == Encoding::UTF_16BE
+ @io.read.b.should == "".b
+ @io.rewind
+ @io.set_encoding(Encoding::ASCII_8BIT)
+
File.binwrite(@name, "\xFE\xFFabc")
@io.set_encoding_by_bom.should == Encoding::UTF_16BE
@io.external_encoding.should == Encoding::UTF_16BE
+ @io.read.b.should == "abc".b
end
it "returns the result encoding if found BOM UTF_32LE sequence" do
+ File.binwrite(@name, "\xFF\xFE\x00\x00")
+
+ @io.set_encoding_by_bom.should == Encoding::UTF_32LE
+ @io.external_encoding.should == Encoding::UTF_32LE
+ @io.read.b.should == "".b
+ @io.rewind
+ @io.set_encoding(Encoding::ASCII_8BIT)
+
File.binwrite(@name, "\xFF\xFE\x00\x00abc")
@io.set_encoding_by_bom.should == Encoding::UTF_32LE
@io.external_encoding.should == Encoding::UTF_32LE
+ @io.read.b.should == "abc".b
end
it "returns the result encoding if found BOM UTF_32BE sequence" do
+ File.binwrite(@name, "\x00\x00\xFE\xFF")
+
+ @io.set_encoding_by_bom.should == Encoding::UTF_32BE
+ @io.external_encoding.should == Encoding::UTF_32BE
+ @io.read.b.should == "".b
+ @io.rewind
+ @io.set_encoding(Encoding::ASCII_8BIT)
+
File.binwrite(@name, "\x00\x00\xFE\xFFabc")
@io.set_encoding_by_bom.should == Encoding::UTF_32BE
@io.external_encoding.should == Encoding::UTF_32BE
+ @io.read.b.should == "abc".b
+ end
+
+ it "returns nil if io is empty" do
+ @io.set_encoding_by_bom.should be_nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ end
+
+ it "returns nil if UTF-8 BOM sequence is incomplete" do
+ File.write(@name, "\xEF")
+
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\xEF".b
+ @io.rewind
+
+ File.write(@name, "\xEFa")
+
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\xEFa".b
+ @io.rewind
+
+ File.write(@name, "\xEF\xBB")
+
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\xEF\xBB".b
+ @io.rewind
+
+ File.write(@name, "\xEF\xBBa")
+
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\xEF\xBBa".b
+ end
+
+ it "returns nil if UTF-16BE BOM sequence is incomplete" do
+ File.write(@name, "\xFE")
+
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\xFE".b
+ @io.rewind
+
+ File.write(@name, "\xFEa")
+
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\xFEa".b
+ end
+
+ it "returns nil if UTF-16LE/UTF-32LE BOM sequence is incomplete" do
+ File.write(@name, "\xFF")
+
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\xFF".b
+ @io.rewind
+
+ File.write(@name, "\xFFa")
+
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\xFFa".b
+ end
+
+ it "returns UTF-16LE if UTF-32LE BOM sequence is incomplete" do
+ File.write(@name, "\xFF\xFE")
+
+ @io.set_encoding_by_bom.should == Encoding::UTF_16LE
+ @io.external_encoding.should == Encoding::UTF_16LE
+ @io.read.b.should == "".b
+ @io.rewind
+ @io.set_encoding(Encoding::ASCII_8BIT)
+
+ File.write(@name, "\xFF\xFE\x00")
+
+ @io.set_encoding_by_bom.should == Encoding::UTF_16LE
+ @io.external_encoding.should == Encoding::UTF_16LE
+ @io.read.b.should == "\x00".b
+ @io.rewind
+ @io.set_encoding(Encoding::ASCII_8BIT)
+
+ File.write(@name, "\xFF\xFE\x00a")
+
+ @io.set_encoding_by_bom.should == Encoding::UTF_16LE
+ @io.external_encoding.should == Encoding::UTF_16LE
+ @io.read.b.should == "\x00a".b
+ end
+
+ it "returns nil if UTF-32BE BOM sequence is incomplete" do
+ File.write(@name, "\x00")
+
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\x00".b
+ @io.rewind
+
+ File.write(@name, "\x00a")
+
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\x00a".b
+ @io.rewind
+
+ File.write(@name, "\x00\x00")
+
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\x00\x00".b
+ @io.rewind
+
+ File.write(@name, "\x00\x00a")
+
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\x00\x00a".b
+ @io.rewind
+
+ File.write(@name, "\x00\x00\xFE")
+
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\x00\x00\xFE".b
+ @io.rewind
+
+ File.write(@name, "\x00\x00\xFEa")
+
+ @io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read.b.should == "\x00\x00\xFEa".b
end
it "returns nil if found BOM sequence not provided" do
File.write(@name, "abc")
@io.set_encoding_by_bom.should == nil
+ @io.external_encoding.should == Encoding::ASCII_8BIT
+ @io.read(3).should == "abc".b
end
it 'returns exception if io not in binary mode' do
diff --git a/spec/ruby/core/io/set_encoding_spec.rb b/spec/ruby/core/io/set_encoding_spec.rb
index 5aec6a96c3..bc448acfce 100644
--- a/spec/ruby/core/io/set_encoding_spec.rb
+++ b/spec/ruby/core/io/set_encoding_spec.rb
@@ -188,4 +188,21 @@ describe "IO#set_encoding" do
@io.external_encoding.should == Encoding::UTF_8
@io.internal_encoding.should == Encoding::UTF_16BE
end
+
+ it "saves encoding options passed as a hash in the last argument" do
+ File.write(@name, "\xff")
+ io = File.open(@name)
+ io.set_encoding(Encoding::EUC_JP, Encoding::SHIFT_JIS, invalid: :replace, replace: ".")
+ io.read.should == "."
+ ensure
+ io.close
+ end
+
+ it "raises ArgumentError when no arguments are given" do
+ -> { @io.set_encoding() }.should raise_error(ArgumentError)
+ end
+
+ it "raises ArgumentError when too many arguments are given" do
+ -> { @io.set_encoding(1, 2, 3) }.should raise_error(ArgumentError)
+ end
end
diff --git a/spec/ruby/core/io/shared/each.rb b/spec/ruby/core/io/shared/each.rb
index 607e7de03e..1b8abce5ff 100644
--- a/spec/ruby/core/io/shared/each.rb
+++ b/spec/ruby/core/io/shared/each.rb
@@ -113,6 +113,13 @@ describe :io_each, shared: true do
@io.send(@method, "") { |s| ScratchPad << s }
ScratchPad.recorded.should == IOSpecs.paragraphs
end
+
+ it "discards leading newlines" do
+ @io.readline
+ @io.readline
+ @io.send(@method, "") { |s| ScratchPad << s }
+ ScratchPad.recorded.should == IOSpecs.paragraphs[1..-1]
+ end
end
describe "with both separator and limit" do
@@ -152,6 +159,13 @@ describe :io_each, shared: true do
@io.send(@method, "", 1024) { |s| ScratchPad << s }
ScratchPad.recorded.should == IOSpecs.paragraphs
end
+
+ it "discards leading newlines" do
+ @io.readline
+ @io.readline
+ @io.send(@method, "", 1024) { |s| ScratchPad << s }
+ ScratchPad.recorded.should == IOSpecs.paragraphs[1..-1]
+ end
end
end
end
@@ -220,6 +234,14 @@ describe :io_each, shared: true do
]
end
end
+
+ describe "when passed too many arguments" do
+ it "raises ArgumentError" do
+ -> {
+ @io.send(@method, "", 1, "excess argument", chomp: true) {}
+ }.should raise_error(ArgumentError)
+ end
+ end
end
describe :io_each_default_separator, shared: true do
diff --git a/spec/ruby/core/io/shared/write.rb b/spec/ruby/core/io/shared/write.rb
index 270b84ac39..9503f94212 100644
--- a/spec/ruby/core/io/shared/write.rb
+++ b/spec/ruby/core/io/shared/write.rb
@@ -69,16 +69,6 @@ describe :io_write, shared: true do
-> { IOSpecs.closed_io.send(@method, "hello") }.should raise_error(IOError)
end
- it "does not modify the passed argument" do
- File.open(@filename, "w") do |f|
- f.set_encoding(Encoding::IBM437)
- # A character whose codepoint differs between UTF-8 and IBM437
- f.write "ƒ".freeze
- end
-
- File.binread(@filename).bytes.should == [159]
- end
-
describe "on a pipe" do
before :each do
@r, @w = IO.pipe
diff --git a/spec/ruby/core/io/sysread_spec.rb b/spec/ruby/core/io/sysread_spec.rb
index 8201ad47ca..e7f63cefec 100644
--- a/spec/ruby/core/io/sysread_spec.rb
+++ b/spec/ruby/core/io/sysread_spec.rb
@@ -6,7 +6,7 @@ describe "IO#sysread on a file" do
@file_name = tmp("IO_sysread_file") + $$.to_s
File.open(@file_name, "w") do |f|
# write some stuff
- f.write("012345678901234567890123456789")
+ f.write("012345678901234567890123456789\nabcdef")
end
@file = File.open(@file_name, "r+")
end
@@ -84,6 +84,29 @@ describe "IO#sysread on a file" do
it "raises IOError on closed stream" do
-> { IOSpecs.closed_io.sysread(5) }.should raise_error(IOError)
end
+
+ it "immediately returns an empty string if the length argument is 0" do
+ @file.sysread(0).should == ""
+ end
+
+ it "immediately returns the given buffer if the length argument is 0" do
+ buffer = "existing content"
+ @file.sysread(0, buffer).should == buffer
+ buffer.should == "existing content"
+ end
+
+ it "discards the existing buffer content upon successful read" do
+ buffer = "existing content"
+ @file.sysread(11, buffer)
+ buffer.should == "01234567890"
+ end
+
+ it "discards the existing buffer content upon error" do
+ buffer = "existing content"
+ @file.seek(0, :END)
+ -> { @file.sysread(1, buffer) }.should raise_error(EOFError)
+ buffer.should be_empty
+ end
end
describe "IO#sysread" do
@@ -100,4 +123,10 @@ describe "IO#sysread" do
@write.syswrite "ab"
@read.sysread(3).should == "ab"
end
+
+ guard_not -> { platform_is :windows and ruby_version_is ""..."3.2" } do # https://bugs.ruby-lang.org/issues/18880
+ it "raises ArgumentError when length is less than 0" do
+ -> { @read.sysread(-1) }.should raise_error(ArgumentError)
+ end
+ end
end
diff --git a/spec/ruby/core/io/syswrite_spec.rb b/spec/ruby/core/io/syswrite_spec.rb
index a28cc62174..eeb8d302a7 100644
--- a/spec/ruby/core/io/syswrite_spec.rb
+++ b/spec/ruby/core/io/syswrite_spec.rb
@@ -29,6 +29,16 @@ describe "IO#syswrite on a file" do
end
end
+ it "does not modify the passed argument" do
+ File.open(@filename, "w") do |f|
+ f.set_encoding(Encoding::IBM437)
+ # A character whose codepoint differs between UTF-8 and IBM437
+ f.syswrite("ƒ".freeze)
+ end
+
+ File.binread(@filename).bytes.should == [198, 146]
+ end
+
it "warns if called immediately after a buffered IO#write" do
@file.write("abcde")
-> { @file.syswrite("fghij") }.should complain(/syswrite/)
diff --git a/spec/ruby/core/io/write_nonblock_spec.rb b/spec/ruby/core/io/write_nonblock_spec.rb
index a8b9ce0a36..5532556d8a 100644
--- a/spec/ruby/core/io/write_nonblock_spec.rb
+++ b/spec/ruby/core/io/write_nonblock_spec.rb
@@ -31,6 +31,16 @@ platform_is_not :windows do
end
end
+ it "does not modify the passed argument" do
+ File.open(@filename, "w") do |f|
+ f.set_encoding(Encoding::IBM437)
+ # A character whose codepoint differs between UTF-8 and IBM437
+ f.write_nonblock("ƒ".freeze)
+ end
+
+ File.binread(@filename).bytes.should == [198, 146]
+ end
+
it "checks if the file is writable if writing zero bytes" do
-> {
@readonly_file.write_nonblock("")
diff --git a/spec/ruby/core/io/write_spec.rb b/spec/ruby/core/io/write_spec.rb
index f29fdf3a01..bcc0582d9e 100644
--- a/spec/ruby/core/io/write_spec.rb
+++ b/spec/ruby/core/io/write_spec.rb
@@ -44,6 +44,16 @@ describe "IO#write on a file" do
@file.write("hellø").should == 6
end
+ it "does not modify the passed argument" do
+ File.open(@filename, "w") do |f|
+ f.set_encoding(Encoding::IBM437)
+ # A character whose codepoint differs between UTF-8 and IBM437
+ f.write("ƒ".freeze)
+ end
+
+ File.binread(@filename).bytes.should == [159]
+ end
+
it "uses the encoding from the given option for non-ascii encoding" do
File.open(@filename, "w", encoding: Encoding::UTF_32LE) do |file|
file.write("hi").should == 8
diff --git a/spec/ruby/core/kernel/p_spec.rb b/spec/ruby/core/kernel/p_spec.rb
index 1bdd1740ca..eae191aa54 100644
--- a/spec/ruby/core/kernel/p_spec.rb
+++ b/spec/ruby/core/kernel/p_spec.rb
@@ -76,10 +76,8 @@ describe "Kernel#p" do
-> { p(*[]) }.should output("")
end
-=begin Not sure how to spec this, but wanted to note the behavior here
- it "does not flush if receiver is not a TTY or a File" do
- end
-=end
+ # Not sure how to spec this, but wanted to note the behavior here
+ it "does not flush if receiver is not a TTY or a File"
end
describe "Kernel.p" do
diff --git a/spec/ruby/core/method/fixtures/classes.rb b/spec/ruby/core/method/fixtures/classes.rb
index be96f65e25..50daa773e1 100644
--- a/spec/ruby/core/method/fixtures/classes.rb
+++ b/spec/ruby/core/method/fixtures/classes.rb
@@ -213,4 +213,28 @@ module MethodSpecs
n * m
end
end
+
+ module InheritedMethods
+ module A
+ private
+ def derp(message)
+ 'A'
+ end
+ end
+
+ module B
+ private
+ def derp
+ 'B' + super('superclass')
+ end
+ end
+
+ class C
+ include A
+ include B
+
+ public :derp
+ alias_method :meow, :derp
+ end
+ end
end
diff --git a/spec/ruby/core/method/super_method_spec.rb b/spec/ruby/core/method/super_method_spec.rb
index e5d8b87a06..dc8764f6c7 100644
--- a/spec/ruby/core/method/super_method_spec.rb
+++ b/spec/ruby/core/method/super_method_spec.rb
@@ -42,4 +42,32 @@ describe "Method#super_method" do
method.super_method.should == nil
end
+
+ # https://github.com/jruby/jruby/issues/7240
+ context "after changing an inherited methods visibility" do
+ it "calls the proper super method" do
+ MethodSpecs::InheritedMethods::C.new.derp.should == 'BA'
+ end
+
+ ruby_version_is ""..."3.2" do
+ it "returns the expected super_method" do
+ method = MethodSpecs::InheritedMethods::C.new.method(:derp)
+ method.super_method.owner.should == MethodSpecs::InheritedMethods::A
+ end
+ end
+
+ ruby_version_is "3.2" do
+ it "returns the expected super_method" do
+ method = MethodSpecs::InheritedMethods::C.new.method(:derp)
+ method.super_method.owner.should == MethodSpecs::InheritedMethods::B
+ end
+ end
+ end
+
+ context "after aliasing an inherited method" do
+ it "returns the expected super_method" do
+ method = MethodSpecs::InheritedMethods::C.new.method(:meow)
+ method.super_method.owner.should == MethodSpecs::InheritedMethods::A
+ end
+ end
end
diff --git a/spec/ruby/core/module/const_defined_spec.rb b/spec/ruby/core/module/const_defined_spec.rb
index 75730395e8..0c15629c08 100644
--- a/spec/ruby/core/module/const_defined_spec.rb
+++ b/spec/ruby/core/module/const_defined_spec.rb
@@ -17,11 +17,16 @@ describe "Module#const_defined?" do
ConstantSpecs::ContainerA::ChildA.const_defined?(:CS_CONST4).should be_true
end
- it "returns true if the constant is defined in a mixed-in module of the receiver" do
+ it "returns true if the constant is defined in a mixed-in module of the receiver's parent" do
# CS_CONST10 is defined in a module included by ChildA
ConstantSpecs::ContainerA::ChildA.const_defined?(:CS_CONST10).should be_true
end
+ it "returns true if the constant is defined in a mixed-in module (with prepends) of the receiver" do
+ # CS_CONST11 is defined in the module included by ContainerPrepend
+ ConstantSpecs::ContainerPrepend.const_defined?(:CS_CONST11).should be_true
+ end
+
it "returns true if the constant is defined in Object and the receiver is a module" do
# CS_CONST1 is defined in Object
ConstantSpecs::ModuleA.const_defined?(:CS_CONST1).should be_true
diff --git a/spec/ruby/core/module/define_method_spec.rb b/spec/ruby/core/module/define_method_spec.rb
index c65b30de24..ce94436bfd 100644
--- a/spec/ruby/core/module/define_method_spec.rb
+++ b/spec/ruby/core/module/define_method_spec.rb
@@ -219,18 +219,55 @@ describe "Module#define_method" do
o.block_test2.should == o
end
+ it "raises TypeError if name cannot converted to String" do
+ -> {
+ Class.new { define_method(1001, -> {}) }
+ }.should raise_error(TypeError, /is not a symbol nor a string/)
+
+ -> {
+ Class.new { define_method([], -> {}) }
+ }.should raise_error(TypeError, /is not a symbol nor a string/)
+ end
+
+ it "converts non-String name to String with #to_str" do
+ obj = Object.new
+ def obj.to_str() "foo" end
+
+ new_class = Class.new { define_method(obj, -> { :called }) }
+ new_class.new.foo.should == :called
+ end
+
+ it "raises TypeError when #to_str called on non-String name returns non-String value" do
+ obj = Object.new
+ def obj.to_str() [] end
+
+ -> {
+ Class.new { define_method(obj, -> {}) }
+ }.should raise_error(TypeError, /can't convert Object to String/)
+ end
+
it "raises a TypeError when the given method is no Method/Proc" do
-> {
Class.new { define_method(:test, "self") }
- }.should raise_error(TypeError)
+ }.should raise_error(TypeError, "wrong argument type String (expected Proc/Method/UnboundMethod)")
-> {
Class.new { define_method(:test, 1234) }
- }.should raise_error(TypeError)
+ }.should raise_error(TypeError, "wrong argument type Integer (expected Proc/Method/UnboundMethod)")
-> {
Class.new { define_method(:test, nil) }
- }.should raise_error(TypeError)
+ }.should raise_error(TypeError, "wrong argument type NilClass (expected Proc/Method/UnboundMethod)")
+ end
+
+ it "uses provided Method/Proc even if block is specified" do
+ new_class = Class.new do
+ define_method(:test, -> { :method_is_called }) do
+ :block_is_called
+ end
+ end
+
+ new_class.new.test.should == :method_is_called
end
it "raises an ArgumentError when no block is given" do
diff --git a/spec/ruby/core/module/fixtures/classes.rb b/spec/ruby/core/module/fixtures/classes.rb
index a64f672b2f..2b47ff112e 100644
--- a/spec/ruby/core/module/fixtures/classes.rb
+++ b/spec/ruby/core/module/fixtures/classes.rb
@@ -42,6 +42,14 @@ module ModuleSpecs
class LookupChild < Lookup
end
+ module ModuleWithPrepend
+ prepend LookupMod
+ end
+
+ class WithPrependedModule
+ include ModuleWithPrepend
+ end
+
class Parent
# For private_class_method spec
def self.private_method; end
diff --git a/spec/ruby/core/module/included_modules_spec.rb b/spec/ruby/core/module/included_modules_spec.rb
index 40e20953f4..ce94ed1285 100644
--- a/spec/ruby/core/module/included_modules_spec.rb
+++ b/spec/ruby/core/module/included_modules_spec.rb
@@ -4,9 +4,11 @@ require_relative 'fixtures/classes'
describe "Module#included_modules" do
it "returns a list of modules included in self" do
ModuleSpecs.included_modules.should == []
+
ModuleSpecs::Child.included_modules.should include(ModuleSpecs::Super, ModuleSpecs::Basic, Kernel)
ModuleSpecs::Parent.included_modules.should include(Kernel)
ModuleSpecs::Basic.included_modules.should == []
ModuleSpecs::Super.included_modules.should include(ModuleSpecs::Basic)
+ ModuleSpecs::WithPrependedModule.included_modules.should include(ModuleSpecs::ModuleWithPrepend)
end
end
diff --git a/spec/ruby/core/module/instance_method_spec.rb b/spec/ruby/core/module/instance_method_spec.rb
index b4d6a0d8c8..30e27bb180 100644
--- a/spec/ruby/core/module/instance_method_spec.rb
+++ b/spec/ruby/core/module/instance_method_spec.rb
@@ -51,14 +51,36 @@ describe "Module#instance_method" do
@mod_um.inspect.should =~ /\bModuleSpecs::InstanceMethChild\b/
end
- it "raises a TypeError if not passed a symbol" do
- -> { Object.instance_method([]) }.should raise_error(TypeError)
- -> { Object.instance_method(0) }.should raise_error(TypeError)
+ it "raises a TypeError if the given name is not a String/Symbol" do
+ -> { Object.instance_method([]) }.should raise_error(TypeError, /is not a symbol nor a string/)
+ -> { Object.instance_method(0) }.should raise_error(TypeError, /is not a symbol nor a string/)
+ -> { Object.instance_method(nil) }.should raise_error(TypeError, /is not a symbol nor a string/)
+ -> { Object.instance_method(mock('x')) }.should raise_error(TypeError, /is not a symbol nor a string/)
end
- it "raises a TypeError if the given name is not a string/symbol" do
- -> { Object.instance_method(nil) }.should raise_error(TypeError)
- -> { Object.instance_method(mock('x')) }.should raise_error(TypeError)
+ it "accepts String name argument" do
+ method = ModuleSpecs::InstanceMeth.instance_method(:foo)
+ method.should be_kind_of(UnboundMethod)
+ end
+
+ it "accepts Symbol name argument" do
+ method = ModuleSpecs::InstanceMeth.instance_method("foo")
+ method.should be_kind_of(UnboundMethod)
+ end
+
+ it "converts non-String name by calling #to_str method" do
+ obj = Object.new
+ def obj.to_str() "foo" end
+
+ method = ModuleSpecs::InstanceMeth.instance_method(obj)
+ method.should be_kind_of(UnboundMethod)
+ end
+
+ it "raises TypeError when passed non-String name and #to_str returns non-String value" do
+ obj = Object.new
+ def obj.to_str() [] end
+
+ -> { ModuleSpecs::InstanceMeth.instance_method(obj) }.should raise_error(TypeError, /can't convert Object to String/)
end
it "raises a NameError if the method has been undefined" do
diff --git a/spec/ruby/core/module/shared/class_eval.rb b/spec/ruby/core/module/shared/class_eval.rb
index 224078ae54..9ef7b5be44 100644
--- a/spec/ruby/core/module/shared/class_eval.rb
+++ b/spec/ruby/core/module/shared/class_eval.rb
@@ -55,40 +55,49 @@ describe :module_class_eval, shared: true do
it "converts a non-string filename to a string using to_str" do
(file = mock(__FILE__)).should_receive(:to_str).and_return(__FILE__)
ModuleSpecs.send(@method, "1+1", file)
+
+ (file = mock(__FILE__)).should_receive(:to_str).and_return(__FILE__)
+ ModuleSpecs.send(@method, "1+1", file, 15)
end
it "raises a TypeError when the given filename can't be converted to string using to_str" do
(file = mock('123')).should_receive(:to_str).and_return(123)
- -> { ModuleSpecs.send(@method, "1+1", file) }.should raise_error(TypeError)
+ -> { ModuleSpecs.send(@method, "1+1", file) }.should raise_error(TypeError, /can't convert MockObject to String/)
end
it "converts non string eval-string to string using to_str" do
(o = mock('1 + 1')).should_receive(:to_str).and_return("1 + 1")
ModuleSpecs.send(@method, o).should == 2
+
+ (o = mock('1 + 1')).should_receive(:to_str).and_return("1 + 1")
+ ModuleSpecs.send(@method, o, "file.rb").should == 2
+
+ (o = mock('1 + 1')).should_receive(:to_str).and_return("1 + 1")
+ ModuleSpecs.send(@method, o, "file.rb", 15).should == 2
end
it "raises a TypeError when the given eval-string can't be converted to string using to_str" do
o = mock('x')
- -> { ModuleSpecs.send(@method, o) }.should raise_error(TypeError)
+ -> { ModuleSpecs.send(@method, o) }.should raise_error(TypeError, "no implicit conversion of MockObject into String")
(o = mock('123')).should_receive(:to_str).and_return(123)
- -> { ModuleSpecs.send(@method, o) }.should raise_error(TypeError)
+ -> { ModuleSpecs.send(@method, o) }.should raise_error(TypeError, /can't convert MockObject to String/)
end
it "raises an ArgumentError when no arguments and no block are given" do
- -> { ModuleSpecs.send(@method) }.should raise_error(ArgumentError)
+ -> { ModuleSpecs.send(@method) }.should raise_error(ArgumentError, "wrong number of arguments (given 0, expected 1..3)")
end
it "raises an ArgumentError when more than 3 arguments are given" do
-> {
ModuleSpecs.send(@method, "1 + 1", "some file", 0, "bogus")
- }.should raise_error(ArgumentError)
+ }.should raise_error(ArgumentError, "wrong number of arguments (given 4, expected 1..3)")
end
it "raises an ArgumentError when a block and normal arguments are given" do
-> {
ModuleSpecs.send(@method, "1 + 1") { 1 + 1 }
- }.should raise_error(ArgumentError)
+ }.should raise_error(ArgumentError, "wrong number of arguments (given 1, expected 0)")
end
# This case was found because Rubinius was caching the compiled
diff --git a/spec/ruby/core/string/split_spec.rb b/spec/ruby/core/string/split_spec.rb
index b57f660816..0417486692 100644
--- a/spec/ruby/core/string/split_spec.rb
+++ b/spec/ruby/core/string/split_spec.rb
@@ -29,9 +29,35 @@ describe "String#split with String" do
"1,2,,3,4,,".split(',').should == ["1", "2", "", "3", "4"]
"1,2,,3,4,,".split(',', 0).should == ["1", "2", "", "3", "4"]
" a b c\nd ".split(" ").should == ["", "a", "b", "c\nd"]
+ " a あ c\nd ".split(" ").should == ["", "a", "あ", "c\nd"]
"hai".split("hai").should == []
",".split(",").should == []
",".split(",", 0).should == []
+ "あ".split("あ").should == []
+ "あ".split("あ", 0).should == []
+ end
+
+ it "does not suppress trailing empty fields when a positive limit is given" do
+ " 1 2 ".split(" ", 2).should == ["1", "2 "]
+ " 1 2 ".split(" ", 3).should == ["1", "2", ""]
+ " 1 2 ".split(" ", 4).should == ["1", "2", ""]
+ " 1 あ ".split(" ", 2).should == ["1", "あ "]
+ " 1 あ ".split(" ", 3).should == ["1", "あ", ""]
+ " 1 あ ".split(" ", 4).should == ["1", "あ", ""]
+
+ "1,2,".split(',', 2).should == ["1", "2,"]
+ "1,2,".split(',', 3).should == ["1", "2", ""]
+ "1,2,".split(',', 4).should == ["1", "2", ""]
+ "1,あ,".split(',', 2).should == ["1", "あ,"]
+ "1,あ,".split(',', 3).should == ["1", "あ", ""]
+ "1,あ,".split(',', 4).should == ["1", "あ", ""]
+
+ "1 2 ".split(/ /, 2).should == ["1", "2 "]
+ "1 2 ".split(/ /, 3).should == ["1", "2", ""]
+ "1 2 ".split(/ /, 4).should == ["1", "2", ""]
+ "1 あ ".split(/ /, 2).should == ["1", "あ "]
+ "1 あ ".split(/ /, 3).should == ["1", "あ", ""]
+ "1 あ ".split(/ /, 4).should == ["1", "あ", ""]
end
it "returns an array with one entry if limit is 1: the original string" do
diff --git a/spec/ruby/core/thread/backtrace/location/absolute_path_spec.rb b/spec/ruby/core/thread/backtrace/location/absolute_path_spec.rb
index 4136f09348..e35e1fc0b4 100644
--- a/spec/ruby/core/thread/backtrace/location/absolute_path_spec.rb
+++ b/spec/ruby/core/thread/backtrace/location/absolute_path_spec.rb
@@ -17,6 +17,15 @@ describe 'Thread::Backtrace::Location#absolute_path' do
end
end
+ it 'returns the correct absolute path when using a relative main script path and changing CWD' do
+ script = fixture(__FILE__, 'subdir/absolute_path_main_chdir.rb')
+ sibling = fixture(__FILE__, 'subdir/sibling.rb')
+ subdir = File.dirname script
+ Dir.chdir(fixture(__FILE__)) do
+ ruby_exe('subdir/absolute_path_main_chdir.rb').should == "subdir/absolute_path_main_chdir.rb\n#{subdir}\n#{subdir}\n#{script}\n#{sibling}\n"
+ end
+ end
+
context "when used in eval with a given filename" do
code = "caller_locations(0)[0].absolute_path"
diff --git a/spec/ruby/core/thread/backtrace/location/fixtures/subdir/absolute_path_main_chdir.rb b/spec/ruby/core/thread/backtrace/location/fixtures/subdir/absolute_path_main_chdir.rb
new file mode 100644
index 0000000000..33c8fb36ef
--- /dev/null
+++ b/spec/ruby/core/thread/backtrace/location/fixtures/subdir/absolute_path_main_chdir.rb
@@ -0,0 +1,11 @@
+puts __FILE__
+puts __dir__
+Dir.chdir __dir__
+
+# Check __dir__ is still correct after chdir
+puts __dir__
+
+puts caller_locations(0)[0].absolute_path
+
+# require_relative also needs to know the absolute path of the current file so we test it here too
+require_relative 'sibling'
diff --git a/spec/ruby/core/thread/backtrace/location/fixtures/subdir/sibling.rb b/spec/ruby/core/thread/backtrace/location/fixtures/subdir/sibling.rb
new file mode 100644
index 0000000000..2a854ddccd
--- /dev/null
+++ b/spec/ruby/core/thread/backtrace/location/fixtures/subdir/sibling.rb
@@ -0,0 +1 @@
+puts __FILE__
diff --git a/spec/ruby/core/unboundmethod/fixtures/classes.rb b/spec/ruby/core/unboundmethod/fixtures/classes.rb
index 46b1c51669..1f466e39d8 100644
--- a/spec/ruby/core/unboundmethod/fixtures/classes.rb
+++ b/spec/ruby/core/unboundmethod/fixtures/classes.rb
@@ -84,4 +84,14 @@ module UnboundMethodSpecs
class C < B
def overridden; end
end
+
+ module HashSpecs
+ class SuperClass
+ def foo
+ end
+ end
+
+ class SubClass < SuperClass
+ end
+ end
end
diff --git a/spec/ruby/core/unboundmethod/hash_spec.rb b/spec/ruby/core/unboundmethod/hash_spec.rb
index 12dce0020f..6888675bc1 100644
--- a/spec/ruby/core/unboundmethod/hash_spec.rb
+++ b/spec/ruby/core/unboundmethod/hash_spec.rb
@@ -12,4 +12,11 @@ describe "UnboundMethod#hash" do
to_s, inspect = Array.instance_method(:to_s), Array.instance_method(:inspect)
to_s.hash.should == inspect.hash
end
+
+ it "equals a hash of the same method in the superclass" do
+ foo_in_superclass = UnboundMethodSpecs::HashSpecs::SuperClass.instance_method(:foo)
+ foo = UnboundMethodSpecs::HashSpecs::SubClass.instance_method(:foo)
+
+ foo.hash.should == foo_in_superclass.hash
+ end
end
diff --git a/spec/ruby/core/unboundmethod/super_method_spec.rb b/spec/ruby/core/unboundmethod/super_method_spec.rb
index c9fa1ec533..5cf96e6fa9 100644
--- a/spec/ruby/core/unboundmethod/super_method_spec.rb
+++ b/spec/ruby/core/unboundmethod/super_method_spec.rb
@@ -1,5 +1,6 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+require_relative '../method/fixtures/classes'
describe "UnboundMethod#super_method" do
it "returns the method that would be called by super in the method" do
@@ -25,4 +26,28 @@ describe "UnboundMethod#super_method" do
method.super_method.should == nil
end
+
+ # https://github.com/jruby/jruby/issues/7240
+ context "after changing an inherited methods visibility" do
+ ruby_version_is ""..."3.2" do
+ it "returns the expected super_method" do
+ method = MethodSpecs::InheritedMethods::C.instance_method(:derp)
+ method.super_method.owner.should == MethodSpecs::InheritedMethods::A
+ end
+ end
+
+ ruby_version_is "3.2" do
+ it "returns the expected super_method" do
+ method = MethodSpecs::InheritedMethods::C.instance_method(:derp)
+ method.super_method.owner.should == MethodSpecs::InheritedMethods::B
+ end
+ end
+ end
+
+ context "after aliasing an inherited method" do
+ it "returns the expected super_method" do
+ method = MethodSpecs::InheritedMethods::C.instance_method(:meow)
+ method.super_method.owner.should == MethodSpecs::InheritedMethods::A
+ end
+ end
end