This commit is contained in:
Benoit Daloze 2022-09-28 18:37:17 +02:00
Родитель 5a1ab740fc
Коммит 31cf1bb525
51 изменённых файлов: 1141 добавлений и 258 удалений

Просмотреть файл

@ -161,6 +161,9 @@ Lint/Debugger:
Lint/Loop:
Enabled: false
Style/BlockComments:
Enabled: true
Style/Lambda:
Enabled: true
EnforcedStyle: literal

Просмотреть файл

@ -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

Просмотреть файл

@ -22,10 +22,23 @@ describe 'Enumerable#sum' do
@enum.sum.should == 5/3r
end
it 'takes a block to transform the elements' do
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
# https://github.com/ruby/ruby/blob/master/doc/ChangeLog-2.4.0#L6208-L6214
it "uses Kahan's compensated summation algorithm for precise sum of float numbers" do

Просмотреть файл

@ -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

Просмотреть файл

@ -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
suppress_warning {
touch(@name) { |f| f.print(o, o2) }
IO.read(@name).should == "#{o.to_s}#{o2.to_s}#{$\}"
}
IO.read(@name).should == "#{o.to_s}#{$,}#{o2.to_s}#{$\}"
end
it "raises IOError on closed stream" do

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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"

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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/)

Просмотреть файл

@ -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("")

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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"

Просмотреть файл

@ -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'

Просмотреть файл

@ -0,0 +1 @@
puts __FILE__

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -75,6 +75,13 @@ module ConstantSpecs
CS_CONST10 = :const10_8
end
# Included in ContainerA
module ModuleIncludePrepended
prepend ModuleD
CS_CONST11 = :const11_8
end
# The following classes/modules have all the constants set "statically".
# Contrast with the classes below where the constants are set as the specs
# are run.
@ -169,6 +176,10 @@ module ConstantSpecs
def const10; CS_CONST10; end
end
class ContainerPrepend
include ModuleIncludePrepended
end
class ContainerA::ChildA
def self.const23; CS_CONST23; end
end

Просмотреть файл

@ -14,46 +14,44 @@ require_relative 'fixtures/precedence'
# the level below (as well as showing associativity within
# the precedence level).
=begin
Excerpted from 'Programming Ruby: The Pragmatic Programmer's Guide'
Second Edition by Dave Thomas, Chad Fowler, and Andy Hunt, page 324
Table 22.4. Ruby operators (high to low precedence)
Method Operator Description
-----------------------------------------------------------------------
:: .
x* [ ] [ ]= Element reference, element set
x ** Exponentiation
x ! ~ + - Not, complement, unary plus and minus
(method names for the last two are +@ and -@)
x * / % Multiply, divide, and modulo
x + - Plus and minus
x >> << Right and left shift
x & And (bitwise for integers)
x ^ | Exclusive or and regular or (bitwise for integers)
x <= < > >= Comparison operators
x <=> == === != =~ !~ Equality and pattern match operators (!=
and !~ may not be defined as methods)
&& Logical and
|| Logical or
.. ... Range (inclusive and exclusive)
? : Ternary if-then-else
= %= /= -= += |= &= Assignment
>>= <<= *= &&= ||= **=
defined? Check if symbol defined
not Logical negation
or and Logical composition
if unless while until Expression modifiers
begin/end Block expression
-----------------------------------------------------------------------
* Operators marked with 'x' in the Method column are implemented as methods
and can be overridden (except != and !~ as noted). (But see the specs
below for implementations that define != and !~ as methods.)
** These are not included in the excerpted table but are shown here for
completeness.
=end
# Excerpted from 'Programming Ruby: The Pragmatic Programmer's Guide'
# Second Edition by Dave Thomas, Chad Fowler, and Andy Hunt, page 324
#
# Table 22.4. Ruby operators (high to low precedence)
# Method Operator Description
# -----------------------------------------------------------------------
# :: .
# x* [ ] [ ]= Element reference, element set
# x ** Exponentiation
# x ! ~ + - Not, complement, unary plus and minus
# (method names for the last two are +@ and -@)
# x * / % Multiply, divide, and modulo
# x + - Plus and minus
# x >> << Right and left shift
# x & “And” (bitwise for integers)
# x ^ | Exclusive “or” and regular “or” (bitwise for integers)
# x <= < > >= Comparison operators
# x <=> == === != =~ !~ Equality and pattern match operators (!=
# and !~ may not be defined as methods)
# && Logical “and”
# || Logical “or”
# .. ... Range (inclusive and exclusive)
# ? : Ternary if-then-else
# = %= /= -= += |= &= Assignment
# >>= <<= *= &&= ||= **=
# defined? Check if symbol defined
# not Logical negation
# or and Logical composition
# if unless while until Expression modifiers
# begin/end Block expression
# -----------------------------------------------------------------------
#
# * Operators marked with 'x' in the Method column are implemented as methods
# and can be overridden (except != and !~ as noted). (But see the specs
# below for implementations that define != and !~ as methods.)
#
# ** These are not included in the excerpted table but are shown here for
# completeness.
# -----------------------------------------------------------------------
# It seems that this table is not correct anymore

Просмотреть файл

@ -7,37 +7,33 @@ require 'stringio'
# Entries marked [r/o] are read-only and an error will be raised of the program attempts to
# modify them. Entries marked [thread] are thread local.
=begin
Exception Information
---------------------------------------------------------------------------------------------------
# Exception Information
# ---------------------------------------------------------------------------------------------------
#
# $! Exception The exception object passed to raise. [thread]
# $@ Array The stack backtrace generated by the last exception. [thread]
$! Exception The exception object passed to raise. [thread]
$@ Array The stack backtrace generated by the last exception. [thread]
=end
=begin
Pattern Matching Variables
---------------------------------------------------------------------------------------------------
These variables are set to nil after an unsuccessful pattern match.
$& String The string matched (following a successful pattern match). This variable is
local to the current scope. [r/o, thread]
$+ String The contents of the highest-numbered group matched following a successful
pattern match. Thus, in "cat" =~/(c|a)(t|z)/, $+ will be set to t. This
variable is local to the current scope. [r/o, thread]
$` String The string preceding the match in a successful pattern match. This variable
is local to the current scope. [r/o, thread]
$' String The string following the match in a successful pattern match. This variable
is local to the current scope. [r/o, thread]
$1 to $<N> String The contents of successive groups matched in a successful pattern match. In
"cat" =~/(c|a)(t|z)/, $1 will be set to a and $2 to t. This variable
is local to the current scope. [r/o, thread]
$~ MatchData An object that encapsulates the results of a successful pattern match. The
variables $&, $`, $', and $1 to $<N> are all derived from $~. Assigning to $~
changes the values of these derived variables. This variable is local to the
current scope. [thread]
=end
# Pattern Matching Variables
# ---------------------------------------------------------------------------------------------------
#
# These variables are set to nil after an unsuccessful pattern match.
#
# $& String The string matched (following a successful pattern match). This variable is
# local to the current scope. [r/o, thread]
# $+ String The contents of the highest-numbered group matched following a successful
# pattern match. Thus, in "cat" =~/(c|a)(t|z)/, $+ will be set to “t”. This
# variable is local to the current scope. [r/o, thread]
# $` String The string preceding the match in a successful pattern match. This variable
# is local to the current scope. [r/o, thread]
# $' String The string following the match in a successful pattern match. This variable
# is local to the current scope. [r/o, thread]
# $1 to $<N> String The contents of successive groups matched in a successful pattern match. In
# "cat" =~/(c|a)(t|z)/, $1 will be set to “a” and $2 to “t”. This variable
# is local to the current scope. [r/o, thread]
# $~ MatchData An object that encapsulates the results of a successful pattern match. The
# variables $&, $`, $', and $1 to $<N> are all derived from $~. Assigning to $~
# changes the values of these derived variables. This variable is local to the
# current scope. [thread]
describe "Predefined global $~" do
@ -506,41 +502,39 @@ describe "Predefined global $!" do
end
end
=begin
Input/Output Variables
---------------------------------------------------------------------------------------------------
$/ String The input record separator (newline by default). This is the value that rou-
tines such as Kernel#gets use to determine record boundaries. If set to
nil, gets will read the entire file.
$-0 String Synonym for $/.
$\ String The string appended to the output of every call to methods such as
Kernel#print and IO#write. The default value is nil.
$, String The separator string output between the parameters to methods such as
Kernel#print and Array#join. Defaults to nil, which adds no text.
$. Integer The number of the last line read from the current input file.
$; String The default separator pattern used by String#split. May be set from the
command line using the -F flag.
$< Object An object that provides access to the concatenation of the contents of all
the files given as command-line arguments or $stdin (in the case where
there are no arguments). $< supports methods similar to a File object:
binmode, close, closed?, each, each_byte, each_line, eof, eof?,
file, filename, fileno, getc, gets, lineno, lineno=, path, pos, pos=,
read, readchar, readline, readlines, rewind, seek, skip, tell, to_a,
to_i, to_io, to_s, along with the methods in Enumerable. The method
file returns a File object for the file currently being read. This may change
as $< reads through the files on the command line. [r/o]
$> IO The destination of output for Kernel#print and Kernel#printf. The
default value is $stdout.
$_ String The last line read by Kernel#gets or Kernel#readline. Many string-
related functions in the Kernel module operate on $_ by default. The vari-
able is local to the current scope. [thread]
$-F String Synonym for $;.
$stderr IO The current standard error output.
$stdin IO The current standard input.
$stdout IO The current standard output. Assignment to $stdout is deprecated: use
$stdout.reopen instead.
=end
# Input/Output Variables
# ---------------------------------------------------------------------------------------------------
#
# $/ String The input record separator (newline by default). This is the value that rou-
# tines such as Kernel#gets use to determine record boundaries. If set to
# nil, gets will read the entire file.
# $-0 String Synonym for $/.
# $\ String The string appended to the output of every call to methods such as
# Kernel#print and IO#write. The default value is nil.
# $, String The separator string output between the parameters to methods such as
# Kernel#print and Array#join. Defaults to nil, which adds no text.
# $. Integer The number of the last line read from the current input file.
# $; String The default separator pattern used by String#split. May be set from the
# command line using the -F flag.
# $< Object An object that provides access to the concatenation of the contents of all
# the files given as command-line arguments or $stdin (in the case where
# there are no arguments). $< supports methods similar to a File object:
# binmode, close, closed?, each, each_byte, each_line, eof, eof?,
# file, filename, fileno, getc, gets, lineno, lineno=, path, pos, pos=,
# read, readchar, readline, readlines, rewind, seek, skip, tell, to_a,
# to_i, to_io, to_s, along with the methods in Enumerable. The method
# file returns a File object for the file currently being read. This may change
# as $< reads through the files on the command line. [r/o]
# $> IO The destination of output for Kernel#print and Kernel#printf. The
# default value is $stdout.
# $_ String The last line read by Kernel#gets or Kernel#readline. Many string-
# related functions in the Kernel module operate on $_ by default. The vari-
# able is local to the current scope. [thread]
# $-F String Synonym for $;.
# $stderr IO The current standard error output.
# $stdin IO The current standard input.
# $stdout IO The current standard output. Assignment to $stdout is deprecated: use
# $stdout.reopen instead.
describe "Predefined global $/" do
before :each do
@ -803,54 +797,52 @@ describe "Predefined global $_" do
end
end
=begin
Execution Environment Variables
---------------------------------------------------------------------------------------------------
$0 String The name of the top-level Ruby program being executed. Typically this will
be the programs filename. On some operating systems, assigning to this
variable will change the name of the process reported (for example) by the
ps(1) command.
$* Array An array of strings containing the command-line options from the invoca-
tion of the program. Options used by the Ruby interpreter will have been
removed. [r/o]
$" Array An array containing the filenames of modules loaded by require. [r/o]
$$ Integer The process number of the program being executed. [r/o]
$? Process::Status The exit status of the last child process to terminate. [r/o, thread]
$: Array An array of strings, where each string specifies a directory to be searched for
Ruby scripts and binary extensions used by the load and require methods.
The initial value is the value of the arguments passed via the -I command-
line option, followed by an installation-defined standard library location, fol-
lowed by the current directory (.). This variable may be set from within a
program to alter the default search path; typically, programs use $: << dir
to append dir to the path. [r/o]
$-a Object True if the -a option is specified on the command line. [r/o]
$-d Object Synonym for $DEBUG.
$DEBUG Object Set to true if the -d command-line option is specified.
__FILE__ String The name of the current source file. [r/o]
$F Array The array that receives the split input line if the -a command-line option is
used.
$FILENAME String The name of the current input file. Equivalent to $<.filename. [r/o]
$-i String If in-place edit mode is enabled (perhaps using the -i command-line
option), $-i holds the extension used when creating the backup file. If you
set a value into $-i, enables in-place edit mode.
$-I Array Synonym for $:. [r/o]
$-K String Sets the multibyte coding system for strings and regular expressions. Equiv-
alent to the -K command-line option.
$-l Object Set to true if the -l option (which enables line-end processing) is present
on the command line. [r/o]
__LINE__ String The current line number in the source file. [r/o]
$LOAD_PATH Array A synonym for $:. [r/o]
$-p Object Set to true if the -p option (which puts an implicit while gets . . . end
loop around your program) is present on the command line. [r/o]
$VERBOSE Object Set to true if the -v, --version, -W, or -w option is specified on the com-
mand line. Set to false if no option, or -W1 is given. Set to nil if -W0
was specified. Setting this option to true causes the interpreter and some
library routines to report additional information. Setting to nil suppresses
all warnings (including the output of Kernel.warn).
$-v Object Synonym for $VERBOSE.
$-w Object Synonym for $VERBOSE.
=end
# Execution Environment Variables
# ---------------------------------------------------------------------------------------------------
#
# $0 String The name of the top-level Ruby program being executed. Typically this will
# be the programs filename. On some operating systems, assigning to this
# variable will change the name of the process reported (for example) by the
# ps(1) command.
# $* Array An array of strings containing the command-line options from the invoca-
# tion of the program. Options used by the Ruby interpreter will have been
# removed. [r/o]
# $" Array An array containing the filenames of modules loaded by require. [r/o]
# $$ Integer The process number of the program being executed. [r/o]
# $? Process::Status The exit status of the last child process to terminate. [r/o, thread]
# $: Array An array of strings, where each string specifies a directory to be searched for
# Ruby scripts and binary extensions used by the load and require methods.
# The initial value is the value of the arguments passed via the -I command-
# line option, followed by an installation-defined standard library location, fol-
# lowed by the current directory (“.”). This variable may be set from within a
# program to alter the default search path; typically, programs use $: << dir
# to append dir to the path. [r/o]
# $-a Object True if the -a option is specified on the command line. [r/o]
# $-d Object Synonym for $DEBUG.
# $DEBUG Object Set to true if the -d command-line option is specified.
# __FILE__ String The name of the current source file. [r/o]
# $F Array The array that receives the split input line if the -a command-line option is
# used.
# $FILENAME String The name of the current input file. Equivalent to $<.filename. [r/o]
# $-i String If in-place edit mode is enabled (perhaps using the -i command-line
# option), $-i holds the extension used when creating the backup file. If you
# set a value into $-i, enables in-place edit mode.
# $-I Array Synonym for $:. [r/o]
# $-K String Sets the multibyte coding system for strings and regular expressions. Equiv-
# alent to the -K command-line option.
# $-l Object Set to true if the -l option (which enables line-end processing) is present
# on the command line. [r/o]
# __LINE__ String The current line number in the source file. [r/o]
# $LOAD_PATH Array A synonym for $:. [r/o]
# $-p Object Set to true if the -p option (which puts an implicit while gets . . . end
# loop around your program) is present on the command line. [r/o]
# $VERBOSE Object Set to true if the -v, --version, -W, or -w option is specified on the com-
# mand line. Set to false if no option, or -W1 is given. Set to nil if -W0
# was specified. Setting this option to true causes the interpreter and some
# library routines to report additional information. Setting to nil suppresses
# all warnings (including the output of Kernel.warn).
# $-v Object Synonym for $VERBOSE.
# $-w Object Synonym for $VERBOSE.
describe "Execution variable $:" do
it "is initialized to an array of strings" do
$:.is_a?(Array).should == true
@ -1068,22 +1060,20 @@ describe "Global variable $0" do
end
end
=begin
Standard Objects
---------------------------------------------------------------------------------------------------
ARGF Object A synonym for $<.
ARGV Array A synonym for $*.
ENV Object A hash-like object containing the programs environment variables. An
instance of class Object, ENV implements the full set of Hash methods. Used
to query and set the value of an environment variable, as in ENV["PATH"]
and ENV["term"]="ansi".
false FalseClass Singleton instance of class FalseClass. [r/o]
nil NilClass The singleton instance of class NilClass. The value of uninitialized
instance and global variables. [r/o]
self Object The receiver (object) of the current method. [r/o]
true TrueClass Singleton instance of class TrueClass. [r/o]
=end
# Standard Objects
# ---------------------------------------------------------------------------------------------------
#
# ARGF Object A synonym for $<.
# ARGV Array A synonym for $*.
# ENV Object A hash-like object containing the programs environment variables. An
# instance of class Object, ENV implements the full set of Hash methods. Used
# to query and set the value of an environment variable, as in ENV["PATH"]
# and ENV["term"]="ansi".
# false FalseClass Singleton instance of class FalseClass. [r/o]
# nil NilClass The singleton instance of class NilClass. The value of uninitialized
# instance and global variables. [r/o]
# self Object The receiver (object) of the current method. [r/o]
# true TrueClass Singleton instance of class TrueClass. [r/o]
describe "The predefined standard objects" do
it "includes ARGF" do
@ -1136,36 +1126,34 @@ describe "The self pseudo-variable" do
end
end
=begin
Global Constants
---------------------------------------------------------------------------------------------------
The following constants are defined by the Ruby interpreter.
DATA IO If the main program file contains the directive __END__, then
the constant DATA will be initialized so that reading from it will
return lines following __END__ from the source file.
FALSE FalseClass Synonym for false (deprecated, removed in Ruby 3).
NIL NilClass Synonym for nil (deprecated, removed in Ruby 3).
RUBY_PLATFORM String The identifier of the platform running this program. This string
is in the same form as the platform identifier used by the GNU
configure utility (which is not a coincidence).
RUBY_RELEASE_DATE String The date of this release.
RUBY_VERSION String The version number of the interpreter.
STDERR IO The actual standard error stream for the program. The initial
value of $stderr.
STDIN IO The actual standard input stream for the program. The initial
value of $stdin.
STDOUT IO The actual standard output stream for the program. The initial
value of $stdout.
SCRIPT_LINES__ Hash If a constant SCRIPT_LINES__ is defined and references a Hash,
Ruby will store an entry containing the contents of each file it
parses, with the files name as the key and an array of strings as
the value.
TOPLEVEL_BINDING Binding A Binding object representing the binding at Rubys top level
the level where programs are initially executed.
TRUE TrueClass Synonym for true (deprecated, removed in Ruby 3).
=end
# Global Constants
# ---------------------------------------------------------------------------------------------------
#
# The following constants are defined by the Ruby interpreter.
#
# DATA IO If the main program file contains the directive __END__, then
# the constant DATA will be initialized so that reading from it will
# return lines following __END__ from the source file.
# FALSE FalseClass Synonym for false (deprecated, removed in Ruby 3).
# NIL NilClass Synonym for nil (deprecated, removed in Ruby 3).
# RUBY_PLATFORM String The identifier of the platform running this program. This string
# is in the same form as the platform identifier used by the GNU
# configure utility (which is not a coincidence).
# RUBY_RELEASE_DATE String The date of this release.
# RUBY_VERSION String The version number of the interpreter.
# STDERR IO The actual standard error stream for the program. The initial
# value of $stderr.
# STDIN IO The actual standard input stream for the program. The initial
# value of $stdin.
# STDOUT IO The actual standard output stream for the program. The initial
# value of $stdout.
# SCRIPT_LINES__ Hash If a constant SCRIPT_LINES__ is defined and references a Hash,
# Ruby will store an entry containing the contents of each file it
# parses, with the files name as the key and an array of strings as
# the value.
# TOPLEVEL_BINDING Binding A Binding object representing the binding at Rubys top level—
# the level where programs are initially executed.
# TRUE TrueClass Synonym for true (deprecated, removed in Ruby 3).
describe "The predefined global constants" do
describe "TRUE" do

Просмотреть файл

@ -18,17 +18,6 @@ describe "BigDecimal#exponent" do
BigDecimal("1234567E10").exponent.should == 17
end
# commenting this spec out after discussion with Defiler, since it seems to be an MRI bug, not a real feature
=begin
platform_is wordsize: 32 do
# TODO: write specs for both 32 and 64 bit
it "returns 0 if exponent can't be represented as Integer" do
BigDecimal("2E1000000000000000").exponent.should == 0
BigDecimal("-5E-999999999999999").exponent.should == 0
end
end
=end
it "returns 0 if self is 0" do
BigDecimal("0").exponent.should == 0
BigDecimal("+0").exponent.should == 0

Просмотреть файл

@ -0,0 +1,10 @@
require_relative '../../../spec_helper'
require 'fiddle'
describe "Fiddle::Handle#initialize" do
it "raises Fiddle::DLError if the library cannot be found" do
-> {
Fiddle::Handle.new("doesnotexist.doesnotexist")
}.should raise_error(Fiddle::DLError)
end
end

Просмотреть файл

@ -0,0 +1,25 @@
require_relative '../../spec_helper'
require 'io/wait'
describe "IO#wait_readable" do
before :each do
@io = File.new(__FILE__ )
end
after :each do
@io.close
end
it "waits for the IO to become readable with no timeout" do
@io.wait_readable.should == @io
end
it "waits for the IO to become readable with the given timeout" do
@io.wait_readable(1).should == @io
end
it "waits for the IO to become readable with the given large timeout" do
@io.wait_readable(365 * 24 * 60 * 60).should == @io
end
end

Просмотреть файл

@ -0,0 +1,18 @@
require_relative '../../spec_helper'
require 'io/wait'
describe "IO#wait_writable" do
it "waits for the IO to become writable with no timeout" do
STDOUT.wait_writable.should == STDOUT
end
it "waits for the IO to become writable with the given timeout" do
STDOUT.wait_writable(1).should == STDOUT
end
it "waits for the IO to become writable with the given large timeout" do
# Represents one year and is larger than a 32-bit int
STDOUT.wait_writable(365 * 24 * 60 * 60).should == STDOUT
end
end

Просмотреть файл

@ -91,7 +91,7 @@ describe "Addrinfo#initialize" do
@addrinfo.afamily.should == Socket::AF_INET6
end
it "returns the 0 socket type" do
it "returns the specified socket type" do
@addrinfo.socktype.should == Socket::SOCK_STREAM
end

Просмотреть файл

@ -19,6 +19,11 @@ describe :socket_pack_sockaddr_in, shared: true do
Socket.unpack_sockaddr_in(sockaddr_in).should == [0, '127.0.0.1']
end
it 'resolves the service name to a port' do
sockaddr_in = Socket.public_send(@method, 'http', '127.0.0.1')
Socket.unpack_sockaddr_in(sockaddr_in).should == [80, '127.0.0.1']
end
describe 'using an IPv4 address' do
it 'returns a String of 16 bytes' do
str = Socket.public_send(@method, 80, '127.0.0.1')

Просмотреть файл

@ -204,6 +204,10 @@ describe "C-API Class function" do
it "returns a string for an anonymous class" do
@s.rb_class2name(Class.new).should be_kind_of(String)
end
it "returns a string beginning with # for an anonymous class" do
@s.rb_class2name(Struct.new(:x, :y).new(1, 2).class).should.start_with?('#')
end
end
describe "rb_class_path" do

Просмотреть файл

@ -112,6 +112,10 @@ VALUE kernel_spec_rb_eval_string(VALUE self, VALUE str) {
return rb_eval_string(RSTRING_PTR(str));
}
VALUE kernel_spec_rb_eval_cmd_kw(VALUE self, VALUE cmd, VALUE args, VALUE kw_splat) {
return rb_eval_cmd_kw(cmd, args, NUM2INT(kw_splat));
}
VALUE kernel_spec_rb_raise(VALUE self, VALUE hash) {
rb_hash_aset(hash, ID2SYM(rb_intern("stage")), ID2SYM(rb_intern("before")));
if (self != Qundef)
@ -361,6 +365,7 @@ void Init_kernel_spec(void) {
rb_define_method(cls, "rb_frame_this_func_test_again", kernel_spec_rb_frame_this_func, 0);
rb_define_method(cls, "rb_ensure", kernel_spec_rb_ensure, 4);
rb_define_method(cls, "rb_eval_string", kernel_spec_rb_eval_string, 1);
rb_define_method(cls, "rb_eval_cmd_kw", kernel_spec_rb_eval_cmd_kw, 3);
rb_define_method(cls, "rb_raise", kernel_spec_rb_raise, 1);
rb_define_method(cls, "rb_throw", kernel_spec_rb_throw, 1);
rb_define_method(cls, "rb_throw_obj", kernel_spec_rb_throw_obj, 2);

Просмотреть файл

@ -393,6 +393,18 @@ static VALUE object_spec_rb_class_inherited_p(VALUE self, VALUE mod, VALUE arg)
return rb_class_inherited_p(mod, arg);
}
static int foreach_f(ID key, VALUE val, VALUE ary) {
rb_ary_push(ary, ID2SYM(key));
rb_ary_push(ary, val);
return ST_CONTINUE;
}
static VALUE object_spec_rb_ivar_foreach(VALUE self, VALUE obj) {
VALUE ary = rb_ary_new();
rb_ivar_foreach(obj, foreach_f, ary);
return ary;
}
static VALUE speced_allocator(VALUE klass) {
VALUE flags = 0;
VALUE instance;
@ -508,6 +520,7 @@ void Init_object_spec(void) {
rb_define_method(cls, "speced_allocator?", speced_allocator_p, 1);
rb_define_method(cls, "custom_alloc_func?", custom_alloc_func_p, 1);
rb_define_method(cls, "not_implemented_method", rb_f_notimplement, -1);
rb_define_method(cls, "rb_ivar_foreach", object_spec_rb_ivar_foreach, 1);
}
#ifdef __cplusplus

Просмотреть файл

@ -0,0 +1,29 @@
class CApiObjectSpecs
class IVars
def initialize
@a = 3
@b = 7
@c = 4
end
def self.set_class_variables
@@foo = :a
@@bar = :b
@@baz = :c
end
end
module MVars
@@mvar = :foo
@@mvar2 = :bar
@ivar = :baz
end
module CVars
@@cvar = :foo
@@cvar2 = :bar
@ivar = :baz
end
end

Просмотреть файл

@ -504,6 +504,25 @@ describe "C-API Kernel function" do
end
end
describe "rb_eval_cmd_kw" do
it "evaluates a string of ruby code" do
@s.rb_eval_cmd_kw("1+1", [], 0).should == 2
end
it "calls a proc with the supplied arguments" do
@s.rb_eval_cmd_kw(-> *x { x.map { |i| i + 1 } }, [1, 3, 7], 0).should == [2, 4, 8]
end
it "calls a proc with keyword arguments if kw_splat is non zero" do
a_proc = -> *x, **y {
res = x.map { |i| i + 1 }
y.each { |k, v| res << k; res << v }
res
}
@s.rb_eval_cmd_kw(a_proc, [1, 3, 7, {a: 1, b: 2, c: 3}], 1).should == [2, 4, 8, :a, 1, :b, 2, :c, 3]
end
end
describe "rb_block_proc" do
it "converts the implicit block into a proc" do
proc = @s.rb_block_proc { 1+1 }

Просмотреть файл

@ -1,4 +1,5 @@
require_relative 'spec_helper'
require_relative 'fixtures/object'
load_extension("object")
@ -983,5 +984,24 @@ describe "CApiObject" do
@o.speced_allocator?(parent).should == true
end
end
describe "rb_ivar_foreach" do
it "calls the callback function for each instance variable on an object" do
o = CApiObjectSpecs::IVars.new
ary = @o.rb_ivar_foreach(o)
ary.should == [:@a, 3, :@b, 7, :@c, 4]
end
it "calls the callback function for each cvar and ivar on a class" do
ary = @o.rb_ivar_foreach(CApiObjectSpecs::CVars)
ary.should == [:__classpath__, 'CApiObjectSpecs::CVars', :@@cvar, :foo, :@@cvar2, :bar, :@ivar, :baz]
end
it "calls the callback function for each cvar and ivar on a module" do
ary = @o.rb_ivar_foreach(CApiObjectSpecs::MVars)
ary.should == [:__classpath__, 'CApiObjectSpecs::MVars', :@@mvar, :foo, :@@mvar2, :bar, :@ivar, :baz]
end
end
end
end

Просмотреть файл

@ -8,9 +8,16 @@ describe :rbasic, shared: true do
it "reports the appropriate FREEZE flag for the object when reading" do
obj, _ = @data.call
(@specs.get_flags(obj) & @freeze).should == 0
initial = @specs.get_flags(obj)
obj.freeze
(@specs.get_flags(obj) & @freeze).should == @freeze
@specs.get_flags(obj).should == @freeze | initial
end
it "supports setting the FREEZE flag" do
obj, _ = @data.call
initial = @specs.get_flags(obj)
@specs.set_flags(obj, @freeze | initial).should == @freeze | initial
obj.should.frozen?
end
it "supports retrieving the (meta)class" do

Просмотреть файл

@ -27,7 +27,8 @@ unless ENV['MSPEC_RUNNER'] # Running directly with ruby some_spec.rb
end
end
ruby_version_is ""..."2.7" do
# Compare with SpecVersion directly here so it works even with --unguarded
if VersionGuard::FULL_RUBY_VERSION < SpecVersion.new('2.7')
abort "This version of ruby/spec requires Ruby 2.7+"
end