This commit is contained in:
Benoit Daloze 2023-01-05 19:05:29 +01:00
parent cd5e6cc0ea
commit bbf54ec334
113 changed files with 1956 additions and 238 deletions

View File

@ -1,3 +1,4 @@
require_relative '../../spec_helper'
require_relative 'shared/keep_if' require_relative 'shared/keep_if'
describe "Array#keep_if" do describe "Array#keep_if" do

View File

@ -45,9 +45,19 @@ describe :array_pack_8bit, shared: true do
[1, 2, 3, 4, 5].pack(pack_format('*')).should == "\x01\x02\x03\x04\x05" [1, 2, 3, 4, 5].pack(pack_format('*')).should == "\x01\x02\x03\x04\x05"
end end
ruby_version_is ""..."3.3" do
it "ignores NULL bytes between directives" do it "ignores NULL bytes between directives" do
[1, 2, 3].pack(pack_format("\000", 2)).should == "\x01\x02" [1, 2, 3].pack(pack_format("\000", 2)).should == "\x01\x02"
end end
end
ruby_version_is "3.3" do
it "raise ArgumentError for NULL bytes between directives" do
-> {
[1, 2, 3].pack(pack_format("\000", 2))
}.should raise_error(ArgumentError, /unknown pack directive/)
end
end
it "ignores spaces between directives" do it "ignores spaces between directives" do
[1, 2, 3].pack(pack_format(' ', 2)).should == "\x01\x02" [1, 2, 3].pack(pack_format(' ', 2)).should == "\x01\x02"

View File

@ -27,6 +27,42 @@ describe :array_pack_basic_non_float, shared: true do
[@obj, @obj].pack("a \t\n\v\f\r"+pack_format).should be_an_instance_of(String) [@obj, @obj].pack("a \t\n\v\f\r"+pack_format).should be_an_instance_of(String)
end end
it "ignores comments in the format string" do
# 2 additional directives ('a') are required for the X directive
[@obj, @obj, @obj, @obj].pack("aa #{pack_format} # some comment \n#{pack_format}").should be_an_instance_of(String)
end
ruby_version_is ""..."3.2" do
it "warns in verbose mode that a directive is unknown" do
# additional directive ('a') is required for the X directive
-> { [@obj, @obj].pack("a R" + pack_format) }.should complain(/unknown pack directive 'R'/, verbose: true)
-> { [@obj, @obj].pack("a 0" + pack_format) }.should complain(/unknown pack directive '0'/, verbose: true)
-> { [@obj, @obj].pack("a :" + pack_format) }.should complain(/unknown pack directive ':'/, verbose: true)
end
end
ruby_version_is "3.2"..."3.3" do
# https://bugs.ruby-lang.org/issues/19150
# NOTE: it's just a plan of the Ruby core team
it "warns that a directive is unknown" do
# additional directive ('a') is required for the X directive
-> { [@obj, @obj].pack("a R" + pack_format) }.should complain(/unknown pack directive 'R'/)
-> { [@obj, @obj].pack("a 0" + pack_format) }.should complain(/unknown pack directive '0'/)
-> { [@obj, @obj].pack("a :" + pack_format) }.should complain(/unknown pack directive ':'/)
end
end
ruby_version_is "3.3" do
# https://bugs.ruby-lang.org/issues/19150
# NOTE: Added this case just to not forget about the decision in the ticket
it "raise ArgumentError when a directive is unknown" do
# additional directive ('a') is required for the X directive
-> { [@obj, @obj].pack("a R" + pack_format) }.should raise_error(ArgumentError)
-> { [@obj, @obj].pack("a 0" + pack_format) }.should raise_error(ArgumentError)
-> { [@obj, @obj].pack("a :" + pack_format) }.should raise_error(ArgumentError)
end
end
it "calls #to_str to coerce the directives string" do it "calls #to_str to coerce the directives string" do
d = mock("pack directive") d = mock("pack directive")
d.should_receive(:to_str).and_return("x"+pack_format) d.should_receive(:to_str).and_return("x"+pack_format)
@ -39,6 +75,10 @@ describe :array_pack_basic_float, shared: true do
[9.3, 4.7].pack(" \t\n\v\f\r"+pack_format).should be_an_instance_of(String) [9.3, 4.7].pack(" \t\n\v\f\r"+pack_format).should be_an_instance_of(String)
end end
it "ignores comments in the format string" do
[9.3, 4.7].pack(pack_format + "# some comment \n" + pack_format).should be_an_instance_of(String)
end
it "calls #to_str to coerce the directives string" do it "calls #to_str to coerce the directives string" do
d = mock("pack directive") d = mock("pack directive")
d.should_receive(:to_str).and_return("x"+pack_format) d.should_receive(:to_str).and_return("x"+pack_format)

View File

@ -25,9 +25,19 @@ describe :array_pack_float_le, shared: true do
[2.9, 1.4, 8.2].pack(pack_format("*")).should == "\x9a\x999@33\xb3?33\x03A" [2.9, 1.4, 8.2].pack(pack_format("*")).should == "\x9a\x999@33\xb3?33\x03A"
end end
ruby_version_is ""..."3.3" do
it "ignores NULL bytes between directives" do it "ignores NULL bytes between directives" do
[5.3, 9.2].pack(pack_format("\000", 2)).should == "\x9a\x99\xa9@33\x13A" [5.3, 9.2].pack(pack_format("\000", 2)).should == "\x9a\x99\xa9@33\x13A"
end end
end
ruby_version_is "3.3" do
it "raise ArgumentError for NULL bytes between directives" do
-> {
[5.3, 9.2].pack(pack_format("\000", 2))
}.should raise_error(ArgumentError, /unknown pack directive/)
end
end
it "ignores spaces between directives" do it "ignores spaces between directives" do
[5.3, 9.2].pack(pack_format(" ", 2)).should == "\x9a\x99\xa9@33\x13A" [5.3, 9.2].pack(pack_format(" ", 2)).should == "\x9a\x99\xa9@33\x13A"
@ -74,6 +84,11 @@ describe :array_pack_float_be, shared: true do
it "converts an Integer to a Float" do it "converts an Integer to a Float" do
[8].pack(pack_format).should == "A\x00\x00\x00" [8].pack(pack_format).should == "A\x00\x00\x00"
[bignum_value].pack(pack_format).should == "_\x80\x00\x00"
end
it "converts a Rational to a Float" do
[Rational(8)].pack(pack_format).should == "A\x00\x00\x00"
end end
it "raises a TypeError if passed a String representation of a floating point number" do it "raises a TypeError if passed a String representation of a floating point number" do
@ -88,9 +103,19 @@ describe :array_pack_float_be, shared: true do
[2.9, 1.4, 8.2].pack(pack_format("*")).should == "@9\x99\x9a?\xb333A\x0333" [2.9, 1.4, 8.2].pack(pack_format("*")).should == "@9\x99\x9a?\xb333A\x0333"
end end
ruby_version_is ""..."3.3" do
it "ignores NULL bytes between directives" do it "ignores NULL bytes between directives" do
[5.3, 9.2].pack(pack_format("\000", 2)).should == "@\xa9\x99\x9aA\x1333" [5.3, 9.2].pack(pack_format("\000", 2)).should == "@\xa9\x99\x9aA\x1333"
end end
end
ruby_version_is "3.3" do
it "raise ArgumentError for NULL bytes between directives" do
-> {
[5.3, 9.2].pack(pack_format("\000", 2))
}.should raise_error(ArgumentError, /unknown pack directive/)
end
end
it "ignores spaces between directives" do it "ignores spaces between directives" do
[5.3, 9.2].pack(pack_format(" ", 2)).should == "@\xa9\x99\x9aA\x1333" [5.3, 9.2].pack(pack_format(" ", 2)).should == "@\xa9\x99\x9aA\x1333"
@ -129,6 +154,11 @@ describe :array_pack_double_le, shared: true do
it "converts an Integer to a Float" do it "converts an Integer to a Float" do
[8].pack(pack_format).should == "\x00\x00\x00\x00\x00\x00\x20@" [8].pack(pack_format).should == "\x00\x00\x00\x00\x00\x00\x20@"
[bignum_value].pack(pack_format).should == "\x00\x00\x00\x00\x00\x00\xF0C"
end
it "converts a Rational to a Float" do
[Rational(8)].pack(pack_format).should == "\x00\x00\x00\x00\x00\x00 @"
end end
it "raises a TypeError if passed a String representation of a floating point number" do it "raises a TypeError if passed a String representation of a floating point number" do
@ -143,9 +173,19 @@ describe :array_pack_double_le, shared: true do
[2.9, 1.4, 8.2].pack(pack_format("*")).should == "333333\x07@ffffff\xf6?ffffff\x20@" [2.9, 1.4, 8.2].pack(pack_format("*")).should == "333333\x07@ffffff\xf6?ffffff\x20@"
end end
ruby_version_is ""..."3.3" do
it "ignores NULL bytes between directives" do it "ignores NULL bytes between directives" do
[5.3, 9.2].pack(pack_format("\000", 2)).should == "333333\x15@ffffff\x22@" [5.3, 9.2].pack(pack_format("\000", 2)).should == "333333\x15@ffffff\x22@"
end end
end
ruby_version_is "3.3" do
it "raise ArgumentError for NULL bytes between directives" do
-> {
[5.3, 9.2].pack(pack_format("\000", 2))
}.should raise_error(ArgumentError, /unknown pack directive/)
end
end
it "ignores spaces between directives" do it "ignores spaces between directives" do
[5.3, 9.2].pack(pack_format(" ", 2)).should == "333333\x15@ffffff\x22@" [5.3, 9.2].pack(pack_format(" ", 2)).should == "333333\x15@ffffff\x22@"
@ -202,9 +242,19 @@ describe :array_pack_double_be, shared: true do
[2.9, 1.4, 8.2].pack(pack_format("*")).should == "@\x07333333?\xf6ffffff@\x20ffffff" [2.9, 1.4, 8.2].pack(pack_format("*")).should == "@\x07333333?\xf6ffffff@\x20ffffff"
end end
ruby_version_is ""..."3.3" do
it "ignores NULL bytes between directives" do it "ignores NULL bytes between directives" do
[5.3, 9.2].pack(pack_format("\000", 2)).should == "@\x15333333@\x22ffffff" [5.3, 9.2].pack(pack_format("\000", 2)).should == "@\x15333333@\x22ffffff"
end end
end
ruby_version_is "3.3" do
it "raise ArgumentError for NULL bytes between directives" do
-> {
[5.3, 9.2].pack(pack_format("\000", 2))
}.should raise_error(ArgumentError, /unknown pack directive/)
end
end
it "ignores spaces between directives" do it "ignores spaces between directives" do
[5.3, 9.2].pack(pack_format(" ", 2)).should == "@\x15333333@\x22ffffff" [5.3, 9.2].pack(pack_format(" ", 2)).should == "@\x15333333@\x22ffffff"

View File

@ -41,10 +41,20 @@ describe :array_pack_16bit_le, shared: true do
str.should == "\x78\x65\xcd\xab\x21\x43" str.should == "\x78\x65\xcd\xab\x21\x43"
end end
ruby_version_is ""..."3.3" do
it "ignores NULL bytes between directives" do it "ignores NULL bytes between directives" do
str = [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2)) str = [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2))
str.should == "\x78\x65\xcd\xab" str.should == "\x78\x65\xcd\xab"
end end
end
ruby_version_is "3.3" do
it "raise ArgumentError for NULL bytes between directives" do
-> {
[0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2))
}.should raise_error(ArgumentError, /unknown pack directive/)
end
end
it "ignores spaces between directives" do it "ignores spaces between directives" do
str = [0x1243_6578, 0xdef0_abcd].pack(pack_format(' ', 2)) str = [0x1243_6578, 0xdef0_abcd].pack(pack_format(' ', 2))
@ -93,10 +103,20 @@ describe :array_pack_16bit_be, shared: true do
str.should == "\x65\x78\xab\xcd\x43\x21" str.should == "\x65\x78\xab\xcd\x43\x21"
end end
ruby_version_is ""..."3.3" do
it "ignores NULL bytes between directives" do it "ignores NULL bytes between directives" do
str = [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2)) str = [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2))
str.should == "\x65\x78\xab\xcd" str.should == "\x65\x78\xab\xcd"
end end
end
ruby_version_is "3.3" do
it "raise ArgumentError for NULL bytes between directives" do
-> {
[0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2))
}.should raise_error(ArgumentError, /unknown pack directive/)
end
end
it "ignores spaces between directives" do it "ignores spaces between directives" do
str = [0x1243_6578, 0xdef0_abcd].pack(pack_format(' ', 2)) str = [0x1243_6578, 0xdef0_abcd].pack(pack_format(' ', 2))
@ -145,10 +165,20 @@ describe :array_pack_32bit_le, shared: true do
str.should == "\x78\x65\x43\x12\xcd\xab\xf0\xde\x21\x43\x65\x78" str.should == "\x78\x65\x43\x12\xcd\xab\xf0\xde\x21\x43\x65\x78"
end end
ruby_version_is ""..."3.3" do
it "ignores NULL bytes between directives" do it "ignores NULL bytes between directives" do
str = [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2)) str = [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2))
str.should == "\x78\x65\x43\x12\xcd\xab\xf0\xde" str.should == "\x78\x65\x43\x12\xcd\xab\xf0\xde"
end end
end
ruby_version_is "3.3" do
it "raise ArgumentError for NULL bytes between directives" do
-> {
[0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2))
}.should raise_error(ArgumentError, /unknown pack directive/)
end
end
it "ignores spaces between directives" do it "ignores spaces between directives" do
str = [0x1243_6578, 0xdef0_abcd].pack(pack_format(' ', 2)) str = [0x1243_6578, 0xdef0_abcd].pack(pack_format(' ', 2))
@ -197,10 +227,20 @@ describe :array_pack_32bit_be, shared: true do
str.should == "\x12\x43\x65\x78\xde\xf0\xab\xcd\x78\x65\x43\x21" str.should == "\x12\x43\x65\x78\xde\xf0\xab\xcd\x78\x65\x43\x21"
end end
ruby_version_is ""..."3.3" do
it "ignores NULL bytes between directives" do it "ignores NULL bytes between directives" do
str = [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2)) str = [0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2))
str.should == "\x12\x43\x65\x78\xde\xf0\xab\xcd" str.should == "\x12\x43\x65\x78\xde\xf0\xab\xcd"
end end
end
ruby_version_is "3.3" do
it "raise ArgumentError for NULL bytes between directives" do
-> {
[0x1243_6578, 0xdef0_abcd].pack(pack_format("\000", 2))
}.should raise_error(ArgumentError, /unknown pack directive/)
end
end
it "ignores spaces between directives" do it "ignores spaces between directives" do
str = [0x1243_6578, 0xdef0_abcd].pack(pack_format(' ', 2)) str = [0x1243_6578, 0xdef0_abcd].pack(pack_format(' ', 2))
@ -309,10 +349,20 @@ describe :array_pack_64bit_le, shared: true do
str.should == "\x56\x78\x12\x34\xcd\xab\xf0\xde\xf0\xde\xba\xdc\x21\x43\x65\x78" str.should == "\x56\x78\x12\x34\xcd\xab\xf0\xde\xf0\xde\xba\xdc\x21\x43\x65\x78"
end end
ruby_version_is ""..."3.3" do
it "ignores NULL bytes between directives" do it "ignores NULL bytes between directives" do
str = [0xdef0_abcd_3412_7856, 0x7865_4321_dcba_def0].pack(pack_format("\000", 2)) str = [0xdef0_abcd_3412_7856, 0x7865_4321_dcba_def0].pack(pack_format("\000", 2))
str.should == "\x56\x78\x12\x34\xcd\xab\xf0\xde\xf0\xde\xba\xdc\x21\x43\x65\x78" str.should == "\x56\x78\x12\x34\xcd\xab\xf0\xde\xf0\xde\xba\xdc\x21\x43\x65\x78"
end end
end
ruby_version_is "3.3" do
it "raise ArgumentError for NULL bytes between directives" do
-> {
[0xdef0_abcd_3412_7856, 0x7865_4321_dcba_def0].pack(pack_format("\000", 2))
}.should raise_error(ArgumentError, /unknown pack directive/)
end
end
it "ignores spaces between directives" do it "ignores spaces between directives" do
str = [0xdef0_abcd_3412_7856, 0x7865_4321_dcba_def0].pack(pack_format(' ', 2)) str = [0xdef0_abcd_3412_7856, 0x7865_4321_dcba_def0].pack(pack_format(' ', 2))
@ -369,10 +419,20 @@ describe :array_pack_64bit_be, shared: true do
str.should == "\xde\xf0\xab\xcd\x34\x12\x78\x56\x78\x65\x43\x21\xdc\xba\xde\xf0" str.should == "\xde\xf0\xab\xcd\x34\x12\x78\x56\x78\x65\x43\x21\xdc\xba\xde\xf0"
end end
ruby_version_is ""..."3.3" do
it "ignores NULL bytes between directives" do it "ignores NULL bytes between directives" do
str = [0xdef0_abcd_3412_7856, 0x7865_4321_dcba_def0].pack(pack_format("\000", 2)) str = [0xdef0_abcd_3412_7856, 0x7865_4321_dcba_def0].pack(pack_format("\000", 2))
str.should == "\xde\xf0\xab\xcd\x34\x12\x78\x56\x78\x65\x43\x21\xdc\xba\xde\xf0" str.should == "\xde\xf0\xab\xcd\x34\x12\x78\x56\x78\x65\x43\x21\xdc\xba\xde\xf0"
end end
end
ruby_version_is "3.3" do
it "raise ArgumentError for NULL bytes between directives" do
-> {
[0xdef0_abcd_3412_7856, 0x7865_4321_dcba_def0].pack(pack_format("\000", 2))
}.should raise_error(ArgumentError, /unknown pack directive/)
end
end
it "ignores spaces between directives" do it "ignores spaces between directives" do
str = [0xdef0_abcd_3412_7856, 0x7865_4321_dcba_def0].pack(pack_format(' ', 2)) str = [0xdef0_abcd_3412_7856, 0x7865_4321_dcba_def0].pack(pack_format(' ', 2))

View File

@ -37,8 +37,14 @@ describe :array_pack_float, shared: true do
-> { ["a"].pack(pack_format) }.should raise_error(TypeError) -> { ["a"].pack(pack_format) }.should raise_error(TypeError)
end end
it "raises a TypeError when the object does not respond to #to_f" do it "raises a TypeError when the object is not Numeric" do
obj = mock('not an float') obj = Object.new
-> { [obj].pack(pack_format) }.should raise_error(TypeError, /can't convert Object into Float/)
end
it "raises a TypeError when the Numeric object does not respond to #to_f" do
klass = Class.new(Numeric)
obj = klass.new
-> { [obj].pack(pack_format) }.should raise_error(TypeError) -> { [obj].pack(pack_format) }.should raise_error(TypeError)
end end
end end

View File

@ -67,9 +67,19 @@ describe :array_pack_unicode, shared: true do
-> { [obj].pack("U") }.should raise_error(TypeError) -> { [obj].pack("U") }.should raise_error(TypeError)
end end
ruby_version_is ""..."3.3" do
it "ignores NULL bytes between directives" do it "ignores NULL bytes between directives" do
[1, 2, 3].pack("U\x00U").should == "\x01\x02" [1, 2, 3].pack("U\x00U").should == "\x01\x02"
end end
end
ruby_version_is "3.3" do
it "raise ArgumentError for NULL bytes between directives" do
-> {
[1, 2, 3].pack("U\x00U")
}.should raise_error(ArgumentError, /unknown pack directive/)
end
end
it "ignores spaces between directives" do it "ignores spaces between directives" do
[1, 2, 3].pack("U U").should == "\x01\x02" [1, 2, 3].pack("U U").should == "\x01\x02"

View File

@ -24,9 +24,19 @@ describe "Array#pack with format 'w'" do
[obj].pack("w").should == "\x05" [obj].pack("w").should == "\x05"
end end
ruby_version_is ""..."3.3" do
it "ignores NULL bytes between directives" do it "ignores NULL bytes between directives" do
[1, 2, 3].pack("w\x00w").should == "\x01\x02" [1, 2, 3].pack("w\x00w").should == "\x01\x02"
end end
end
ruby_version_is "3.3" do
it "raise ArgumentError for NULL bytes between directives" do
-> {
[1, 2, 3].pack("w\x00w")
}.should raise_error(ArgumentError, /unknown pack directive/)
end
end
it "ignores spaces between directives" do it "ignores spaces between directives" do
[1, 2, 3].pack("w w").should == "\x01\x02" [1, 2, 3].pack("w w").should == "\x01\x02"

View File

@ -22,6 +22,11 @@ describe :array_unshift, shared: true do
a.should == [3, 4] a.should == [3, 4]
end end
it "returns self" do
a = [1, 2, 3]
a.send(@method, "a").should.equal?(a)
end
it "quietly ignores unshifting nothing" do it "quietly ignores unshifting nothing" do
[].send(@method).should == [] [].send(@method).should == []
end end
@ -43,4 +48,17 @@ describe :array_unshift, shared: true do
it "raises a FrozenError on a frozen array when the array would not be modified" do it "raises a FrozenError on a frozen array when the array would not be modified" do
-> { ArraySpecs.frozen_array.send(@method) }.should raise_error(FrozenError) -> { ArraySpecs.frozen_array.send(@method) }.should raise_error(FrozenError)
end end
# https://github.com/oracle/truffleruby/issues/2772
it "doesn't rely on Array#[]= so it can be overridden" do
subclass = Class.new(Array) do
def []=(*)
raise "[]= is called"
end
end
array = subclass.new
array.send(@method, 1)
array.should == [1]
end
end end

View File

@ -1,6 +1,7 @@
require_relative '../../spec_helper' require_relative '../../spec_helper'
require_relative 'fixtures/classes' require_relative 'fixtures/classes'
# Should be synchronized with core/struct/values_at_spec.rb
describe "Array#values_at" do describe "Array#values_at" do
it "returns an array of elements at the indexes when passed indexes" do it "returns an array of elements at the indexes when passed indexes" do
[1, 2, 3, 4, 5].values_at().should == [] [1, 2, 3, 4, 5].values_at().should == []

View File

@ -62,4 +62,10 @@ describe "Array#zip" do
it "does not return subclass instance on Array subclasses" do it "does not return subclass instance on Array subclasses" do
ArraySpecs::MyArray[1, 2, 3].zip(["a", "b"]).should be_an_instance_of(Array) ArraySpecs::MyArray[1, 2, 3].zip(["a", "b"]).should be_an_instance_of(Array)
end end
it "raises TypeError when some argument isn't Array and doesn't respond to #to_ary and #to_enum" do
-> { [1, 2, 3].zip(Object.new) }.should raise_error(TypeError, "wrong argument type Object (must respond to :each)")
-> { [1, 2, 3].zip(1) }.should raise_error(TypeError, "wrong argument type Integer (must respond to :each)")
-> { [1, 2, 3].zip(true) }.should raise_error(TypeError, "wrong argument type TrueClass (must respond to :each)")
end
end end

View File

@ -31,6 +31,28 @@ ruby_version_is '3.1' do
ModuleSpecs::Parent.subclasses.should == ModuleSpecs::Parent.subclasses.uniq ModuleSpecs::Parent.subclasses.should == ModuleSpecs::Parent.subclasses.uniq
end end
it "works when creating subclasses concurrently" do
t = 16
n = 1000
go = false
superclass = Class.new
threads = t.times.map do
Thread.new do
Thread.pass until go
n.times.map do
Class.new(superclass)
end
end
end
go = true
classes = threads.map(&:value)
superclass.subclasses.size.should == t * n
superclass.subclasses.each { |c| c.should be_kind_of(Class) }
end
def assert_subclasses(mod,subclasses) def assert_subclasses(mod,subclasses)
mod.subclasses.sort_by(&:inspect).should == subclasses.sort_by(&:inspect) mod.subclasses.sort_by(&:inspect).should == subclasses.sort_by(&:inspect)
end end

View File

@ -20,6 +20,18 @@ describe "Dir.home" do
Dir.home.should_not.frozen? Dir.home.should_not.frozen?
end end
it "returns a string with the filesystem encoding" do
Dir.home.encoding.should == Encoding.find("filesystem")
end
platform_is_not :windows do
it "works even if HOME is unset" do
ENV.delete('HOME')
Dir.home.should.start_with?('/')
Dir.home.encoding.should == Encoding.find("filesystem")
end
end
platform_is :windows do platform_is :windows do
ruby_version_is "3.0" do ruby_version_is "3.0" do
it "returns the home directory with forward slashs and as UTF-8" do it "returns the home directory with forward slashs and as UTF-8" do
@ -29,10 +41,7 @@ describe "Dir.home" do
home.encoding.should == Encoding::UTF_8 home.encoding.should == Encoding::UTF_8
end end
end end
end
end
platform_is :windows do
it "retrieves the directory from HOME, USERPROFILE, HOMEDRIVE/HOMEPATH and the WinAPI in that order" do it "retrieves the directory from HOME, USERPROFILE, HOMEDRIVE/HOMEPATH and the WinAPI in that order" do
old_dirs = [ENV.delete('HOME'), ENV.delete('USERPROFILE'), ENV.delete('HOMEDRIVE'), ENV.delete('HOMEPATH')] old_dirs = [ENV.delete('HOME'), ENV.delete('USERPROFILE'), ENV.delete('HOMEDRIVE'), ENV.delete('HOMEPATH')]
@ -48,6 +57,7 @@ describe "Dir.home" do
ENV['HOME'], ENV['USERPROFILE'], ENV['HOMEDRIVE'], ENV['HOMEPATH'] = *old_dirs ENV['HOME'], ENV['USERPROFILE'], ENV['HOMEDRIVE'], ENV['HOMEPATH'] = *old_dirs
end end
end end
end
describe "when called with the current user name" do describe "when called with the current user name" do
platform_is :solaris do platform_is :solaris do
@ -65,6 +75,10 @@ describe "Dir.home" do
it "returns a non-frozen string" do it "returns a non-frozen string" do
Dir.home(ENV['USER']).should_not.frozen? Dir.home(ENV['USER']).should_not.frozen?
end end
it "returns a string with the filesystem encoding" do
Dir.home(ENV['USER']).encoding.should == Encoding.find("filesystem")
end
end end
it "raises an ArgumentError if the named user doesn't exist" do it "raises an ArgumentError if the named user doesn't exist" do

View File

@ -46,7 +46,7 @@ describe "Dir.mkdir" do
end end
end end
it "calls #to_path on non-String arguments" do it "calls #to_path on non-String path arguments" do
DirSpecs.clear_dirs DirSpecs.clear_dirs
p = mock('path') p = mock('path')
p.should_receive(:to_path).and_return(DirSpecs.mock_dir('nonexisting')) p.should_receive(:to_path).and_return(DirSpecs.mock_dir('nonexisting'))
@ -54,6 +54,22 @@ describe "Dir.mkdir" do
DirSpecs.clear_dirs DirSpecs.clear_dirs
end end
it "calls #to_int on non-Integer permissions argument" do
DirSpecs.clear_dirs
path = DirSpecs.mock_dir('nonexisting')
permissions = mock('permissions')
permissions.should_receive(:to_int).and_return(0666)
Dir.mkdir(path, permissions)
DirSpecs.clear_dirs
end
it "raises TypeError if non-Integer permissions argument does not have #to_int method" do
path = DirSpecs.mock_dir('nonexisting')
permissions = Object.new
-> { Dir.mkdir(path, permissions) }.should raise_error(TypeError, 'no implicit conversion of Object into Integer')
end
it "raises a SystemCallError if any of the directories in the path before the last does not exist" do it "raises a SystemCallError if any of the directories in the path before the last does not exist" do
-> { Dir.mkdir "#{DirSpecs.nonexistent}/subdir" }.should raise_error(SystemCallError) -> { Dir.mkdir "#{DirSpecs.nonexistent}/subdir" }.should raise_error(SystemCallError)
end end

View File

@ -38,4 +38,9 @@ describe "Enumerable#zip" do
multi.zip(multi).should == [[[1, 2], [1, 2]], [[3, 4, 5], [3, 4, 5]], [[6, 7, 8, 9], [6, 7, 8, 9]]] multi.zip(multi).should == [[[1, 2], [1, 2]], [[3, 4, 5], [3, 4, 5]], [[6, 7, 8, 9], [6, 7, 8, 9]]]
end end
it "raises TypeError when some argument isn't Array and doesn't respond to #to_ary and #to_enum" do
-> { EnumerableSpecs::Numerous.new(1,2,3).zip(Object.new) }.should raise_error(TypeError, "wrong argument type Object (must respond to :each)")
-> { EnumerableSpecs::Numerous.new(1,2,3).zip(1) }.should raise_error(TypeError, "wrong argument type Integer (must respond to :each)")
-> { EnumerableSpecs::Numerous.new(1,2,3).zip(true) }.should raise_error(TypeError, "wrong argument type TrueClass (must respond to :each)")
end
end end

View File

@ -7,9 +7,25 @@ describe "Float#<=>" do
((bignum_value*1.1) <=> bignum_value).should == 1 ((bignum_value*1.1) <=> bignum_value).should == 1
end end
it "returns nil when either argument is NaN" do it "returns nil if one side is NaN" do
(nan_value <=> 71.2).should be_nil [1.0, 42, bignum_value].each { |n|
(1771.176 <=> nan_value).should be_nil (nan_value <=> n).should == nil
(n <=> nan_value).should == nil
}
end
it "handles positive infinity" do
[1.0, 42, bignum_value].each { |n|
(infinity_value <=> n).should == 1
(n <=> infinity_value).should == -1
}
end
it "handles negative infinity" do
[1.0, 42, bignum_value].each { |n|
(-infinity_value <=> n).should == -1
(n <=> -infinity_value).should == 1
}
end end
it "returns nil when the given argument is not a Float" do it "returns nil when the given argument is not a Float" do
@ -49,21 +65,10 @@ describe "Float#<=>" do
}.should raise_error(TypeError, "coerce must return [x, y]") }.should raise_error(TypeError, "coerce must return [x, y]")
end end
# The 4 tests below are taken from matz's revision 23730 for Ruby trunk it "returns the correct result when one side is infinite" do
#
it "returns 1 when self is Infinity and other is an Integer" do
(infinity_value <=> Float::MAX.to_i*2).should == 1 (infinity_value <=> Float::MAX.to_i*2).should == 1
end
it "returns -1 when self is negative and other is Infinity" do
(-Float::MAX.to_i*2 <=> infinity_value).should == -1 (-Float::MAX.to_i*2 <=> infinity_value).should == -1
end
it "returns -1 when self is -Infinity and other is negative" do
(-infinity_value <=> -Float::MAX.to_i*2).should == -1 (-infinity_value <=> -Float::MAX.to_i*2).should == -1
end
it "returns 1 when self is negative and other is -Infinity" do
(-Float::MAX.to_i*2 <=> -infinity_value).should == 1 (-Float::MAX.to_i*2 <=> -infinity_value).should == 1
end end

View File

@ -23,7 +23,7 @@ describe "Float#divmod" do
# Behaviour established as correct in r23953 # Behaviour established as correct in r23953
it "raises a FloatDomainError if other is NaN" do it "raises a FloatDomainError if other is NaN" do
-> { 1.divmod(nan_value) }.should raise_error(FloatDomainError) -> { 1.0.divmod(nan_value) }.should raise_error(FloatDomainError)
end end
# Behaviour established as correct in r23953 # Behaviour established as correct in r23953

View File

@ -14,4 +14,25 @@ describe "Float#>" do
-> { 5.0 > "4" }.should raise_error(ArgumentError) -> { 5.0 > "4" }.should raise_error(ArgumentError)
-> { 5.0 > mock('x') }.should raise_error(ArgumentError) -> { 5.0 > mock('x') }.should raise_error(ArgumentError)
end end
it "returns false if one side is NaN" do
[1.0, 42, bignum_value].each { |n|
(nan_value > n).should == false
(n > nan_value).should == false
}
end
it "handles positive infinity" do
[1.0, 42, bignum_value].each { |n|
(infinity_value > n).should == true
(n > infinity_value).should == false
}
end
it "handles negative infinity" do
[1.0, 42, bignum_value].each { |n|
(-infinity_value > n).should == false
(n > -infinity_value).should == true
}
end
end end

View File

@ -14,4 +14,25 @@ describe "Float#>=" do
-> { 5.0 >= "4" }.should raise_error(ArgumentError) -> { 5.0 >= "4" }.should raise_error(ArgumentError)
-> { 5.0 >= mock('x') }.should raise_error(ArgumentError) -> { 5.0 >= mock('x') }.should raise_error(ArgumentError)
end end
it "returns false if one side is NaN" do
[1.0, 42, bignum_value].each { |n|
(nan_value >= n).should == false
(n >= nan_value).should == false
}
end
it "handles positive infinity" do
[1.0, 42, bignum_value].each { |n|
(infinity_value >= n).should == true
(n >= infinity_value).should == false
}
end
it "handles negative infinity" do
[1.0, 42, bignum_value].each { |n|
(-infinity_value >= n).should == false
(n >= -infinity_value).should == true
}
end
end end

View File

@ -14,4 +14,25 @@ describe "Float#<" do
-> { 5.0 < "4" }.should raise_error(ArgumentError) -> { 5.0 < "4" }.should raise_error(ArgumentError)
-> { 5.0 < mock('x') }.should raise_error(ArgumentError) -> { 5.0 < mock('x') }.should raise_error(ArgumentError)
end end
it "returns false if one side is NaN" do
[1.0, 42, bignum_value].each { |n|
(nan_value < n).should == false
(n < nan_value).should == false
}
end
it "handles positive infinity" do
[1.0, 42, bignum_value].each { |n|
(infinity_value < n).should == false
(n < infinity_value).should == true
}
end
it "handles negative infinity" do
[1.0, 42, bignum_value].each { |n|
(-infinity_value < n).should == true
(n < -infinity_value).should == false
}
end
end end

View File

@ -15,4 +15,25 @@ describe "Float#<=" do
-> { 5.0 <= "4" }.should raise_error(ArgumentError) -> { 5.0 <= "4" }.should raise_error(ArgumentError)
-> { 5.0 <= mock('x') }.should raise_error(ArgumentError) -> { 5.0 <= mock('x') }.should raise_error(ArgumentError)
end end
it "returns false if one side is NaN" do
[1.0, 42, bignum_value].each { |n|
(nan_value <= n).should == false
(n <= nan_value).should == false
}
end
it "handles positive infinity" do
[1.0, 42, bignum_value].each { |n|
(infinity_value <= n).should == false
(n <= infinity_value).should == true
}
end
it "handles negative infinity" do
[1.0, 42, bignum_value].each { |n|
(-infinity_value <= n).should == true
(n <= -infinity_value).should == false
}
end
end end

View File

@ -14,4 +14,25 @@ describe :float_equal, shared: true do
1.0.send(@method, x).should == false 1.0.send(@method, x).should == false
2.0.send(@method, x).should == true 2.0.send(@method, x).should == true
end end
it "returns false if one side is NaN" do
[1.0, 42, bignum_value].each { |n|
(nan_value.send(@method, n)).should == false
(n.send(@method, nan_value)).should == false
}
end
it "handles positive infinity" do
[1.0, 42, bignum_value].each { |n|
(infinity_value.send(@method, n)).should == false
(n.send(@method, infinity_value)).should == false
}
end
it "handles negative infinity" do
[1.0, 42, bignum_value].each { |n|
((-infinity_value).send(@method, n)).should == false
(n.send(@method, -infinity_value)).should == false
}
end
end end

View File

@ -216,6 +216,10 @@ describe "IO#gets" do
@io.gets(nil, 0).should == "" @io.gets(nil, 0).should == ""
@io.gets("", 0).should == "" @io.gets("", 0).should == ""
end end
it "does not accept limit that doesn't fit in a C off_t" do
-> { @io.gets(2**128) }.should raise_error(RangeError)
end
end end
describe "IO#gets" do describe "IO#gets" do

View File

@ -92,8 +92,13 @@ describe "IO#lineno=" do
@io.lineno.should == 92233 @io.lineno.should == 92233
end end
it "raises TypeError on nil argument" do it "raises TypeError if cannot convert argument to Integer implicitly" do
-> { @io.lineno = nil }.should raise_error(TypeError) -> { @io.lineno = "1" }.should raise_error(TypeError, 'no implicit conversion of String into Integer')
-> { @io.lineno = nil }.should raise_error(TypeError, 'no implicit conversion from nil to integer')
end
it "does not accept Integers that don't fit in a C int" do
-> { @io.lineno = 2**32 }.should raise_error(RangeError)
end end
it "sets the current line number to the given value" do it "sets the current line number to the given value" do

View File

@ -1,6 +1,8 @@
require_relative '../../spec_helper' require_relative '../../spec_helper'
require_relative 'shared/new' require_relative 'shared/new'
# NOTE: should be syncronized with library/stringio/initialize_spec.rb
describe "IO.new" do describe "IO.new" do
it_behaves_like :io_new, :new it_behaves_like :io_new, :new
end end

View File

@ -51,6 +51,10 @@ describe "IO#readline" do
it "returns an empty string when passed 0 as a limit" do it "returns an empty string when passed 0 as a limit" do
@io.readline(0).should == "" @io.readline(0).should == ""
end end
it "does not accept Integers that don't fit in a C off_t" do
-> { @io.readline(2**128) }.should raise_error(RangeError)
end
end end
describe "when passed separator and limit" do describe "when passed separator and limit" do

View File

@ -106,6 +106,10 @@ describe "IO#readlines" do
it "raises ArgumentError when passed 0 as a limit" do it "raises ArgumentError when passed 0 as a limit" do
-> { @io.readlines(0) }.should raise_error(ArgumentError) -> { @io.readlines(0) }.should raise_error(ArgumentError)
end end
it "does not accept Integers that don't fit in a C off_t" do
-> { @io.readlines(2**128) }.should raise_error(RangeError)
end
end end
describe "when passed chomp" do describe "when passed chomp" do

View File

@ -77,6 +77,10 @@ describe :io_each, shared: true do
-> { @io.send(@method, 0){} }.should raise_error(ArgumentError) -> { @io.send(@method, 0){} }.should raise_error(ArgumentError)
end end
end end
it "does not accept Integers that don't fit in a C off_t" do
-> { @io.send(@method, 2**128){} }.should raise_error(RangeError)
end
end end
describe "when passed a String containing one space as a separator" do describe "when passed a String containing one space as a separator" do

View File

@ -1,5 +1,7 @@
require_relative '../fixtures/classes' require_relative '../fixtures/classes'
# NOTE: should be syncronized with library/stringio/initialize_spec.rb
# This group of specs may ONLY contain specs that do successfully create # This group of specs may ONLY contain specs that do successfully create
# an IO instance from the file descriptor returned by #new_fd helper. # an IO instance from the file descriptor returned by #new_fd helper.
describe :io_new, shared: true do describe :io_new, shared: true do

View File

@ -60,7 +60,13 @@ describe :io_set_pos, shared: true do
end end
end end
it "does not accept Integers that don't fit in a C long" do it "raises TypeError when cannot convert implicitly argument to Integer" do
File.open @fname do |io|
-> { io.send @method, Object.new }.should raise_error(TypeError, "no implicit conversion of Object into Integer")
end
end
it "does not accept Integers that don't fit in a C off_t" do
File.open @fname do |io| File.open @fname do |io|
-> { io.send @method, 2**128 }.should raise_error(RangeError) -> { io.send @method, 2**128 }.should raise_error(RangeError)
end end

View File

@ -79,6 +79,10 @@ describe :io_readlines_options_19, shared: true do
(result ? result : ScratchPad.recorded).should == IOSpecs.lines (result ? result : ScratchPad.recorded).should == IOSpecs.lines
end end
it "does not accept Integers that don't fit in a C off_t" do
-> { IO.send(@method, @name, 2**128, &@object) }.should raise_error(RangeError)
end
ruby_bug "#18767", ""..."3.3" do ruby_bug "#18767", ""..."3.3" do
describe "when passed limit" do describe "when passed limit" do
it "raises ArgumentError when passed 0 as a limit" do it "raises ArgumentError when passed 0 as a limit" do

View File

@ -4,7 +4,7 @@ require_relative 'fixtures/classes'
require_relative 'shared/pos' require_relative 'shared/pos'
describe "IO#sysseek" do describe "IO#sysseek" do
it_behaves_like :io_set_pos, :seek it_behaves_like :io_set_pos, :sysseek
end end
describe "IO#sysseek" do describe "IO#sysseek" do

View File

@ -88,12 +88,12 @@ describe :kernel_load, shared: true do
describe "when passed true for 'wrap'" do describe "when passed true for 'wrap'" do
it "loads from an existing path" do it "loads from an existing path" do
path = File.expand_path "wrap_fixture.rb", CODE_LOADING_DIR path = File.expand_path "load_wrap_fixture.rb", CODE_LOADING_DIR
@object.load(path, true).should be_true @object.load(path, true).should be_true
end end
it "sets the enclosing scope to an anonymous module" do it "sets the enclosing scope to an anonymous module" do
path = File.expand_path "wrap_fixture.rb", CODE_LOADING_DIR path = File.expand_path "load_wrap_fixture.rb", CODE_LOADING_DIR
@object.load(path, true) @object.load(path, true)
Object.const_defined?(:LoadSpecWrap).should be_false Object.const_defined?(:LoadSpecWrap).should be_false
@ -103,14 +103,14 @@ describe :kernel_load, shared: true do
end end
it "allows referencing outside namespaces" do it "allows referencing outside namespaces" do
path = File.expand_path "wrap_fixture.rb", CODE_LOADING_DIR path = File.expand_path "load_wrap_fixture.rb", CODE_LOADING_DIR
@object.load(path, true) @object.load(path, true)
ScratchPad.recorded[0].should equal(String) ScratchPad.recorded[0].should equal(String)
end end
it "sets self as a copy of the top-level main" do it "sets self as a copy of the top-level main" do
path = File.expand_path "wrap_fixture.rb", CODE_LOADING_DIR path = File.expand_path "load_wrap_fixture.rb", CODE_LOADING_DIR
@object.load(path, true) @object.load(path, true)
top_level = ScratchPad.recorded[2] top_level = ScratchPad.recorded[2]
@ -127,7 +127,7 @@ describe :kernel_load, shared: true do
main_ancestors = main.singleton_class.ancestors[1..-1] main_ancestors = main.singleton_class.ancestors[1..-1]
main_ancestors.first.should == mod main_ancestors.first.should == mod
path = File.expand_path "wrap_fixture.rb", CODE_LOADING_DIR path = File.expand_path "load_wrap_fixture.rb", CODE_LOADING_DIR
@object.load(path, true) @object.load(path, true)
top_level = ScratchPad.recorded[2] top_level = ScratchPad.recorded[2]
@ -157,7 +157,7 @@ describe :kernel_load, shared: true do
describe "when passed a module for 'wrap'" do describe "when passed a module for 'wrap'" do
ruby_version_is "3.1" do ruby_version_is "3.1" do
it "sets the enclosing scope to the supplied module" do it "sets the enclosing scope to the supplied module" do
path = File.expand_path "wrap_fixture.rb", CODE_LOADING_DIR path = File.expand_path "load_wrap_fixture.rb", CODE_LOADING_DIR
mod = Module.new mod = Module.new
@object.load(path, mod) @object.load(path, mod)
@ -167,6 +167,25 @@ describe :kernel_load, shared: true do
wrap_module = ScratchPad.recorded[1] wrap_module = ScratchPad.recorded[1]
wrap_module.should == mod wrap_module.should == mod
end end
it "makes constants and instance methods in the source file reachable with the supplied module" do
path = File.expand_path "load_wrap_fixture.rb", CODE_LOADING_DIR
mod = Module.new
@object.load(path, mod)
mod::LOAD_WRAP_SPECS_TOP_LEVEL_CONSTANT.should == 1
obj = Object.new
obj.extend(mod)
obj.send(:load_wrap_specs_top_level_method).should == :load_wrap_specs_top_level_method
end
it "makes instance methods in the source file private" do
path = File.expand_path "load_wrap_fixture.rb", CODE_LOADING_DIR
mod = Module.new
@object.load(path, mod)
mod.private_instance_methods.include?(:load_wrap_specs_top_level_method).should == true
end
end end
end end

View File

@ -1,3 +1,5 @@
require_relative '../../spec_helper'
describe "Kernel#singleton_class" do describe "Kernel#singleton_class" do
it "returns class extended from an object" do it "returns class extended from an object" do
x = Object.new x = Object.new

View File

@ -1,5 +1,6 @@
# -*- encoding: binary -*- # -*- encoding: binary -*-
require_relative '../../spec_helper' require_relative '../../spec_helper'
require_relative 'fixtures/classes'
require_relative 'fixtures/marshal_data' require_relative 'fixtures/marshal_data'
describe "Marshal.dump" do describe "Marshal.dump" do
@ -106,7 +107,7 @@ describe "Marshal.dump" do
end end
describe "with an object responding to #_dump" do describe "with an object responding to #_dump" do
it "dumps the object returned by #marshal_dump" do it "dumps the object returned by #_dump" do
Marshal.dump(UserDefined.new).should == "\004\bu:\020UserDefined\022\004\b[\a:\nstuff;\000" Marshal.dump(UserDefined.new).should == "\004\bu:\020UserDefined\022\004\b[\a:\nstuff;\000"
end end
@ -122,6 +123,34 @@ describe "Marshal.dump" do
m.should_not_receive(:_dump) m.should_not_receive(:_dump)
Marshal.dump(m) Marshal.dump(m)
end end
it "indexes instance variables of a String returned by #_dump at first and then indexes the object itself" do
class MarshalSpec::M1::A
def _dump(level)
s = "<dump>"
s.instance_variable_set(:@foo, "bar")
s
end
end
a = MarshalSpec::M1::A.new
# 0-based index of the object a = 2, that is encoded as \x07 and printed as "\a" character.
# Objects are serialized in the following order: Array, a, "bar".
# But they are indexed in different order: Array (index=0), "bar" (index=1), a (index=2)
# So the second occurenc of the object a is encoded as an index 2.
reference = "@\a"
Marshal.dump([a, a]).should == "\x04\b[\aIu:\x17MarshalSpec::M1::A\v<dump>\x06:\t@foo\"\bbar#{reference}"
end
describe "Core library classes with #_dump returning a String with instance variables" do
it "indexes instance variables and then a Time object itself" do
t = Time.utc(2022)
reference = "@\a"
Marshal.dump([t, t]).should == "\x04\b[\aIu:\tTime\r \x80\x1E\xC0\x00\x00\x00\x00\x06:\tzoneI\"\bUTC\x06:\x06EF#{reference}"
end
end
end end
describe "with a Class" do describe "with a Class" do
@ -185,6 +214,20 @@ describe "Marshal.dump" do
[Marshal, -2**64, "\004\bl-\n\000\000\000\000\000\000\000\000\001\000"], [Marshal, -2**64, "\004\bl-\n\000\000\000\000\000\000\000\000\001\000"],
].should be_computed_by(:dump) ].should be_computed_by(:dump)
end end
it "increases the object links counter" do
obj = Object.new
object_1_link = "\x06" # representing of (0-based) index=1 (by adding 5 for small Integers)
object_2_link = "\x07" # representing of index=2
# objects: Array, Object, Object
Marshal.dump([obj, obj]).should == "\x04\b[\ao:\vObject\x00@#{object_1_link}"
# objects: Array, Bignum, Object, Object
Marshal.dump([2**64, obj, obj]).should == "\x04\b[\bl+\n\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00o:\vObject\x00@#{object_2_link}"
Marshal.dump([2**48, obj, obj]).should == "\x04\b[\bl+\t\x00\x00\x00\x00\x00\x00\x01\x00o:\vObject\x00@#{object_2_link}"
Marshal.dump([2**32, obj, obj]).should == "\x04\b[\bl+\b\x00\x00\x00\x00\x01\x00o:\vObject\x00@#{object_2_link}"
end
end end
describe "with a String" do describe "with a String" do

View File

@ -0,0 +1,4 @@
module MarshalSpec
# empty modules
module M1 end
end

View File

@ -1,21 +1,76 @@
require_relative '../../spec_helper' require_relative '../../spec_helper'
describe "MatchData#values_at" do describe "Struct#values_at" do
it "returns an array of the matching value" do # Should be synchronized with core/array/values_at_spec.rb and core/struct/values_at_spec.rb
#
# /(.)(.)(\d+)(\d)/.match("THX1138: The Movie").to_a # => ["HX1138", "H", "X", "113", "8"]
context "when passed a list of Integers" do
it "returns an array containing each value given by one of integers" do
/(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(0, 2, -2).should == ["HX1138", "X", "113"] /(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(0, 2, -2).should == ["HX1138", "X", "113"]
end end
describe "when passed a Range" do it "returns nil value for any integer that is out of range" do
it "returns an array of the matching value" do /(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(5).should == [nil]
/(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(2..4, 0..1).should == ["X", "113", "8", "HX1138", "H"] /(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(-6).should == [nil]
end end
end end
context "when passed an integer Range" do
it "returns an array containing each value given by the elements of the range" do
/(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(0..2).should == ["HX1138", "H", "X"]
end
it "fills with nil values for range elements larger than the captured values number" do
/(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(0..5).should == ["HX1138", "H", "X", "113", "8", nil]
end
it "raises RangeError if any element of the range is negative and out of range" do
-> { /(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(-6..3) }.should raise_error(RangeError, "-6..3 out of range")
end
it "supports endless Range" do
/(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(0..).should == ["HX1138", "H", "X", "113", "8"]
end
it "supports beginningless Range" do
/(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(0..2).should == ["HX1138", "H", "X"]
end
it "returns an empty Array when Range is empty" do
/(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(2..0).should == []
end
end
context "when passed names" do
it 'slices captures with the given names' do it 'slices captures with the given names' do
/(?<a>.)(?<b>.)(?<c>.)/.match('012').values_at(:c, :a).should == ['2', '0'] /(?<a>.)(?<b>.)(?<c>.)/.match('012').values_at(:c, :a).should == ['2', '0']
end end
it 'takes names and indices' do it 'slices captures with the given String names' do
/(?<a>.)(?<b>.)(?<c>.)/.match('012').values_at('c', 'a').should == ['2', '0']
end
end
it "supports multiple integer Ranges" do
/(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(1..2, 2..3).should == ["H", "X", "X", "113"]
end
it "supports mixing integer Ranges and Integers" do
/(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(1..2, 4).should == ["H", "X", "8"]
end
it 'supports mixing of names and indices' do
/\A(?<a>.)(?<b>.)\z/.match('01').values_at(0, 1, 2, :a, :b).should == ['01', '0', '1', '0', '1'] /\A(?<a>.)(?<b>.)\z/.match('01').values_at(0, 1, 2, :a, :b).should == ['01', '0', '1', '0', '1']
end end
it "returns a new empty Array if no arguments given" do
/(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at().should == []
end
it "fails when passed arguments of unsupported types" do
-> {
/(.)(.)(\d+)(\d)/.match("THX1138: The Movie").values_at(Object.new)
}.should raise_error(TypeError, "no implicit conversion of Object into Integer")
end
end end

View File

@ -388,6 +388,7 @@ module ModuleSpecs
# empty modules # empty modules
module M1; end module M1; end
module M2; end module M2; end
module M3; end
module Autoload module Autoload
def self.use_ex1 def self.use_ex1

View File

@ -106,7 +106,7 @@ describe "Module#include" do
all = [A, B, M] all = [A, B, M]
(B.ancestors & all).should == [B, A, M] (B.ancestors.filter { |a| all.include?(a) }).should == [B, A, M]
end end
end end

View File

@ -611,6 +611,18 @@ describe "Module#prepend" do
ScratchPad.recorded.should == [[:prepend_features, c], [:prepended, c]] ScratchPad.recorded.should == [[:prepend_features, c], [:prepended, c]]
end end
it "prepends a module if it is included in a super class" do
module ModuleSpecs::M3
module M; end
class A; include M; end
class B < A; prepend M; end
all = [A, B, M]
(B.ancestors.filter { |a| all.include?(a) }).should == [M, B, A, M]
end
end
it "detects cyclic prepends" do it "detects cyclic prepends" do
-> { -> {
module ModuleSpecs::P module ModuleSpecs::P

View File

@ -169,4 +169,26 @@ describe "ObjectSpace.define_finalizer" do
ruby_exe(code).lines.sort.should == ["finalized1\n", "finalized2\n"] ruby_exe(code).lines.sort.should == ["finalized1\n", "finalized2\n"]
end end
ruby_version_is "3.1" do
describe "when $VERBOSE is not nil" do
it "warns if an exception is raised in finalizer" do
code = <<-RUBY
ObjectSpace.define_finalizer(Object.new) { raise "finalizing" }
RUBY
ruby_exe(code, args: "2>&1").should include("warning: Exception in finalizer", "finalizing")
end
end
describe "when $VERBOSE is nil" do
it "does not warn even if an exception is raised in finalizer" do
code = <<-RUBY
ObjectSpace.define_finalizer(Object.new) { raise "finalizing" }
RUBY
ruby_exe(code, args: "2>&1", options: "-W0").should == ""
end
end
end
end end

View File

@ -1,3 +1,4 @@
require_relative '../../spec_helper'
describe "Process::Constants" do describe "Process::Constants" do
platform_is :darwin, :netbsd, :freebsd do platform_is :darwin, :netbsd, :freebsd do

View File

@ -42,5 +42,34 @@ describe "Process.detach" do
thr.pid.should == pid thr.pid.should == pid
end end
it "tolerates not existing child process pid" do
# ensure there is no child process with this hardcoded pid
# `kill 0 pid` for existing process returns "1" and raises Errno::ESRCH if process doesn't exist
-> { Process.kill(0, 100500) }.should raise_error(Errno::ESRCH)
thr = Process.detach(100500)
thr.join
thr.should be_kind_of(Thread)
end
it "calls #to_int to implicitly convert non-Integer pid to Integer" do
pid = MockObject.new('mock-enumerable')
pid.should_receive(:to_int).and_return(100500)
Process.detach(pid).join
end
it "raises TypeError when pid argument does not have #to_int method" do
-> { Process.detach(Object.new) }.should raise_error(TypeError, "no implicit conversion of Object into Integer")
end
it "raises TypeError when #to_int returns non-Integer value" do
pid = MockObject.new('mock-enumerable')
pid.should_receive(:to_int).and_return(:symbol)
-> { Process.detach(pid) }.should raise_error(TypeError, "can't convert MockObject to Integer (MockObject#to_int gives Symbol)")
end
end end
end end

View File

@ -477,6 +477,16 @@ describe "Process.spawn" do
# redirection # redirection
it 'redirects to the wrapped IO using wrapped_io.to_io if out: wrapped_io' do
File.open(@name, 'w') do |file|
-> do
wrapped_io = mock('wrapped IO')
wrapped_io.should_receive(:to_io).and_return(file)
Process.wait Process.spawn('echo "Hello World"', out: wrapped_io)
end.should output_to_fd("Hello World\n", file)
end
end
it "redirects STDOUT to the given file descriptor if out: Integer" do it "redirects STDOUT to the given file descriptor if out: Integer" do
File.open(@name, 'w') do |file| File.open(@name, 'w') do |file|
-> do -> do

View File

@ -7,7 +7,7 @@ describe "Process.times" do
# TODO: Intel C Compiler does not work this example # TODO: Intel C Compiler does not work this example
# http://rubyci.s3.amazonaws.com/icc-x64/ruby-master/log/20221013T030005Z.fail.html.gz # http://rubyci.s3.amazonaws.com/icc-x64/ruby-master/log/20221013T030005Z.fail.html.gz
unless RbConfig::CONFIG['CC'].include?("icx") unless RbConfig::CONFIG['CC']&.include?("icx")
it "returns current cpu times" do it "returns current cpu times" do
t = Process.times t = Process.times
user = t.utime user = t.utime

View File

@ -7,6 +7,10 @@ describe "Queue#initialize" do
q.should.empty? q.should.empty?
end end
it "is a private method" do
Queue.private_instance_methods.include?(:initialize).should == true
end
ruby_version_is '3.1' do ruby_version_is '3.1' do
it "adds all elements of the passed Enumerable to self" do it "adds all elements of the passed Enumerable to self" do
q = Queue.new([1, 2, 3]) q = Queue.new([1, 2, 3])
@ -30,9 +34,16 @@ describe "Queue#initialize" do
q.should.empty? q.should.empty?
end end
it "raises if the provided Enumerable does not respond to #to_a" do it "raises TypeError if the provided Enumerable does not respond to #to_a" do
enumerable = MockObject.new('mock-enumerable') enumerable = MockObject.new('mock-enumerable')
-> { Queue.new(enumerable) }.should raise_error(TypeError, "can't convert MockObject into Array") -> { Queue.new(enumerable) }.should raise_error(TypeError, "can't convert MockObject into Array")
end end
it "raises TypeError if #to_a does not return Array" do
enumerable = MockObject.new('mock-enumerable')
enumerable.should_receive(:to_a).and_return("string")
-> { Queue.new(enumerable) }.should raise_error(TypeError, "can't convert MockObject to Array (MockObject#to_a gives String)")
end
end end
end end

View File

@ -0,0 +1,34 @@
require_relative '../../spec_helper'
describe "Refinement#import_methods" do
ruby_version_is "3.1" do
context "when methods are defined in Ruby code" do
it "imports methods" do
str_utils = Module.new do
def indent(level)
" " * level + self
end
end
Module.new do
refine String do
import_methods str_utils
"foo".indent(3).should == " foo"
end
end
end
end
context "when methods are not defined in Ruby code" do
it "raises ArgumentError" do
Module.new do
refine String do
-> {
import_methods Kernel
}.should raise_error(ArgumentError)
end
end
end
end
end
end

View File

@ -0,0 +1,27 @@
require_relative '../../spec_helper'
describe "Refinement#include" do
ruby_version_is "3.1"..."3.2" do
it "warns about deprecation" do
Module.new do
refine String do
-> {
include Module.new
}.should complain(/warning: Refinement#include is deprecated and will be removed in Ruby 3.2/)
end
end
end
end
ruby_version_is "3.2" do
it "raises a TypeError" do
Module.new do
refine String do
-> {
include Module.new
}.should raise_error(TypeError, "Refinement#include has been removed")
end
end
end
end
end

View File

@ -0,0 +1,27 @@
require_relative '../../spec_helper'
describe "Refinement#prepend" do
ruby_version_is "3.1"..."3.2" do
it "warns about deprecation" do
Module.new do
refine String do
-> {
prepend Module.new
}.should complain(/warning: Refinement#prepend is deprecated and will be removed in Ruby 3.2/)
end
end
end
end
ruby_version_is "3.2" do
it "raises a TypeError" do
Module.new do
refine String do
-> {
prepend Module.new
}.should raise_error(TypeError, "Refinement#prepend has been removed")
end
end
end
end
end

View File

@ -2,7 +2,7 @@ require_relative '../../spec_helper'
describe "Regexp#initialize" do describe "Regexp#initialize" do
it "is a private method" do it "is a private method" do
Regexp.should have_private_method(:initialize) Regexp.should have_private_instance_method(:initialize)
end end
ruby_version_is ""..."3.0" do ruby_version_is ""..."3.0" do

View File

@ -221,6 +221,18 @@ describe "Signal.trap" do
Signal.trap(:HUP, @saved_trap).should equal(@proc) Signal.trap(:HUP, @saved_trap).should equal(@proc)
end end
it "raises ArgumentError when passed unknown signal" do
-> { Signal.trap(300) { } }.should raise_error(ArgumentError, "invalid signal number (300)")
-> { Signal.trap("USR10") { } }.should raise_error(ArgumentError, "unsupported signal `SIGUSR10'")
-> { Signal.trap("SIGUSR10") { } }.should raise_error(ArgumentError, "unsupported signal `SIGUSR10'")
end
it "raises ArgumentError when passed signal is not Integer, String or Symbol" do
-> { Signal.trap(nil) { } }.should raise_error(ArgumentError, "bad signal type NilClass")
-> { Signal.trap(100.0) { } }.should raise_error(ArgumentError, "bad signal type Float")
-> { Signal.trap(Rational(100)) { } }.should raise_error(ArgumentError, "bad signal type Rational")
end
# See man 2 signal # See man 2 signal
%w[KILL STOP].each do |signal| %w[KILL STOP].each do |signal|
it "raises ArgumentError or Errno::EINVAL for SIG#{signal}" do it "raises ArgumentError or Errno::EINVAL for SIG#{signal}" do

View File

@ -24,4 +24,10 @@ describe "String#byteslice on on non ASCII strings" do
"\u3042".byteslice(1..2).should == "\x81\x82".force_encoding("UTF-8") "\u3042".byteslice(1..2).should == "\x81\x82".force_encoding("UTF-8")
"\u3042".byteslice(-1).should == "\x82".force_encoding("UTF-8") "\u3042".byteslice(-1).should == "\x82".force_encoding("UTF-8")
end end
it "returns a String in the same encoding as self" do
"ruby".encode("UTF-8").slice(0).encoding.should == Encoding::UTF_8
"ruby".encode("US-ASCII").slice(0).encoding.should == Encoding::US_ASCII
"ruby".encode("Windows-1251").slice(0).encoding.should == Encoding::Windows_1251
end
end end

View File

@ -91,6 +91,10 @@ describe "String#capitalize" do
StringSpecs::MyString.new("Hello").capitalize.should be_an_instance_of(String) StringSpecs::MyString.new("Hello").capitalize.should be_an_instance_of(String)
end end
end end
it "returns a String in the same encoding as self" do
"h".encode("US-ASCII").capitalize.encoding.should == Encoding::US_ASCII
end
end end
describe "String#capitalize!" do describe "String#capitalize!" do

View File

@ -1,5 +1,4 @@
require_relative 'shared/chars' require_relative 'shared/chars'
require_relative 'shared/each_char_without_block'
describe "String#chars" do describe "String#chars" do
it_behaves_like :string_chars, :chars it_behaves_like :string_chars, :chars
@ -7,4 +6,10 @@ describe "String#chars" do
it "returns an array when no block given" do it "returns an array when no block given" do
"hello".chars.should == ['h', 'e', 'l', 'l', 'o'] "hello".chars.should == ['h', 'e', 'l', 'l', 'o']
end end
it "returns Strings in the same encoding as self" do
"hello".encode("US-ASCII").chars.each do |c|
c.encoding.should == Encoding::US_ASCII
end
end
end end

View File

@ -40,6 +40,10 @@ describe "String#chomp" do
"".chomp.should == "" "".chomp.should == ""
end end
it "returns a String in the same encoding as self" do
"abc\n\n".encode("US-ASCII").chomp.encoding.should == Encoding::US_ASCII
end
ruby_version_is ''...'3.0' do ruby_version_is ''...'3.0' do
it "returns subclass instances when called on a subclass" do it "returns subclass instances when called on a subclass" do
str = StringSpecs::MyString.new("hello\n").chomp str = StringSpecs::MyString.new("hello\n").chomp

View File

@ -60,6 +60,10 @@ describe "String#chop" do
StringSpecs::MyString.new("hello\n").chop.should be_an_instance_of(String) StringSpecs::MyString.new("hello\n").chop.should be_an_instance_of(String)
end end
end end
it "returns a String in the same encoding as self" do
"abc\n\n".encode("US-ASCII").chop.encoding.should == Encoding::US_ASCII
end
end end
describe "String#chop!" do describe "String#chop!" do

View File

@ -54,4 +54,8 @@ describe "String#clone" do
orig.should == "xtring" orig.should == "xtring"
clone.should == "string" clone.should == "string"
end end
it "returns a String in the same encoding as self" do
"a".encode("US-ASCII").clone.encoding.should == Encoding::US_ASCII
end
end end

View File

@ -51,6 +51,10 @@ describe "String#delete_prefix" do
s.delete_prefix('hell').should be_an_instance_of(String) s.delete_prefix('hell').should be_an_instance_of(String)
end end
end end
it "returns a String in the same encoding as self" do
'hello'.encode("US-ASCII").delete_prefix('hell').encoding.should == Encoding::US_ASCII
end
end end
describe "String#delete_prefix!" do describe "String#delete_prefix!" do

View File

@ -95,6 +95,10 @@ describe "String#delete" do
StringSpecs::MyString.new("oh no!!!").delete("!").should be_an_instance_of(String) StringSpecs::MyString.new("oh no!!!").delete("!").should be_an_instance_of(String)
end end
end end
it "returns a String in the same encoding as self" do
"hello".encode("US-ASCII").delete("lo").encoding.should == Encoding::US_ASCII
end
end end
describe "String#delete!" do describe "String#delete!" do

View File

@ -51,6 +51,10 @@ describe "String#delete_suffix" do
s.delete_suffix('ello').should be_an_instance_of(String) s.delete_suffix('ello').should be_an_instance_of(String)
end end
end end
it "returns a String in the same encoding as self" do
"hello".encode("US-ASCII").delete_suffix("ello").encoding.should == Encoding::US_ASCII
end
end end
describe "String#delete_suffix!" do describe "String#delete_suffix!" do

View File

@ -8,6 +8,10 @@ describe "String#downcase" do
"hello".downcase.should == "hello" "hello".downcase.should == "hello"
end end
it "returns a String in the same encoding as self" do
"hELLO".encode("US-ASCII").downcase.encoding.should == Encoding::US_ASCII
end
describe "full Unicode case mapping" do describe "full Unicode case mapping" do
it "works for all of Unicode with no option" do it "works for all of Unicode with no option" do
"ÄÖÜ".downcase.should == "äöü" "ÄÖÜ".downcase.should == "äöü"

View File

@ -350,7 +350,7 @@ describe "String#dump" do
].should be_computed_by(:dump) ].should be_computed_by(:dump)
end end
it "returns a string with multi-byte UTF-8 characters replaced by \\u{} notation with upper-case hex digits" do it "returns a string with multi-byte UTF-8 characters less than or equal 0xFFFF replaced by \\uXXXX notation with upper-case hex digits" do
[ [0200.chr('utf-8'), '"\u0080"'], [ [0200.chr('utf-8'), '"\u0080"'],
[0201.chr('utf-8'), '"\u0081"'], [0201.chr('utf-8'), '"\u0081"'],
[0202.chr('utf-8'), '"\u0082"'], [0202.chr('utf-8'), '"\u0082"'],
@ -382,15 +382,21 @@ describe "String#dump" do
[0235.chr('utf-8'), '"\u009D"'], [0235.chr('utf-8'), '"\u009D"'],
[0236.chr('utf-8'), '"\u009E"'], [0236.chr('utf-8'), '"\u009E"'],
[0237.chr('utf-8'), '"\u009F"'], [0237.chr('utf-8'), '"\u009F"'],
[0177777.chr('utf-8'), '"\uFFFF"'],
].should be_computed_by(:dump) ].should be_computed_by(:dump)
end end
it "returns a string with multi-byte UTF-8 characters greater than 0xFFFF replaced by \\u{XXXXXX} notation with upper-case hex digits" do
0x10000.chr('utf-8').dump.should == '"\u{10000}"'
0x10FFFF.chr('utf-8').dump.should == '"\u{10FFFF}"'
end
it "includes .force_encoding(name) if the encoding isn't ASCII compatible" do it "includes .force_encoding(name) if the encoding isn't ASCII compatible" do
"\u{876}".encode('utf-16be').dump.should.end_with?(".force_encoding(\"UTF-16BE\")") "\u{876}".encode('utf-16be').dump.should.end_with?(".force_encoding(\"UTF-16BE\")")
"\u{876}".encode('utf-16le').dump.should.end_with?(".force_encoding(\"UTF-16LE\")") "\u{876}".encode('utf-16le').dump.should.end_with?(".force_encoding(\"UTF-16LE\")")
end end
it "keeps origin encoding" do it "returns a String in the same encoding as self" do
"foo".encode("ISO-8859-1").dump.encoding.should == Encoding::ISO_8859_1 "foo".encode("ISO-8859-1").dump.encoding.should == Encoding::ISO_8859_1
"foo".encode('windows-1251').dump.encoding.should == Encoding::Windows_1251 "foo".encode('windows-1251').dump.encoding.should == Encoding::Windows_1251
1.chr.dump.encoding.should == Encoding::US_ASCII 1.chr.dump.encoding.should == Encoding::US_ASCII

View File

@ -58,4 +58,8 @@ describe "String#dup" do
orig.should == "c" orig.should == "c"
copy.should == "b" copy.should == "b"
end end
it "returns a String in the same encoding as self" do
"hello".encode("US-ASCII").dup.encoding.should == Encoding::US_ASCII
end
end end

View File

@ -1,7 +1,6 @@
require_relative '../../spec_helper' require_relative '../../spec_helper'
require_relative 'fixtures/classes' require_relative 'fixtures/classes'
require_relative 'shared/each_line' require_relative 'shared/each_line'
require_relative 'shared/each_line_without_block'
describe "String#lines" do describe "String#lines" do
it_behaves_like :string_each_line, :lines it_behaves_like :string_each_line, :lines

View File

@ -37,6 +37,10 @@ describe "String#reverse" do
str.reverse.should == "體黑正\xDE\xDF軟微" str.reverse.should == "體黑正\xDE\xDF軟微"
end end
it "returns a String in the same encoding as self" do
"stressed".encode("US-ASCII").reverse.encoding.should == Encoding::US_ASCII
end
end end
describe "String#reverse!" do describe "String#reverse!" do

View File

@ -69,6 +69,12 @@ describe "String#scan" do
it "does not raise any errors when passed a multi-byte string" do it "does not raise any errors when passed a multi-byte string" do
"あああaaaあああ".scan("あああ").should == ["あああ", "あああ"] "あああaaaあああ".scan("あああ").should == ["あああ", "あああ"]
end end
it "returns Strings in the same encoding as self" do
"cruel world".encode("US-ASCII").scan(/\w+/).each do |s|
s.encoding.should == Encoding::US_ASCII
end
end
end end
describe "String#scan with pattern and block" do describe "String#scan with pattern and block" do

View File

@ -31,6 +31,11 @@ describe "String#scrub with a default replacement" do
input.scrub.should == "abc?????" input.scrub.should == "abc?????"
end end
it "returns a String in the same encoding as self" do
x81 = [0x81].pack('C').force_encoding('utf-8')
"abc\u3042#{x81}".scrub.encoding.should == Encoding::UTF_8
end
ruby_version_is '3.0' do ruby_version_is '3.0' do
it "returns String instances when called on a subclass" do it "returns String instances when called on a subclass" do
StringSpecs::MyString.new("foo").scrub.should be_an_instance_of(String) StringSpecs::MyString.new("foo").scrub.should be_an_instance_of(String)
@ -80,6 +85,11 @@ describe "String#scrub with a custom replacement" do
block.should raise_error(ArgumentError) block.should raise_error(ArgumentError)
end end
it "returns a String in the same encoding as self" do
x81 = [0x81].pack('C').force_encoding('utf-8')
"abc\u3042#{x81}".scrub("*").encoding.should == Encoding::UTF_8
end
it "raises TypeError when a non String replacement is given" do it "raises TypeError when a non String replacement is given" do
x81 = [0x81].pack('C').force_encoding('utf-8') x81 = [0x81].pack('C').force_encoding('utf-8')
block = -> { "foo#{x81}".scrub(1) } block = -> { "foo#{x81}".scrub(1) }

View File

@ -122,6 +122,12 @@ describe :string_each_line, shared: true do
out.should == ["hello\n", "world."] out.should == ["hello\n", "world."]
end end
it "returns Strings in the same encoding as self" do
"one\ntwo\r\nthree".encode("US-ASCII").send(@method) do |s|
s.encoding.should == Encoding::US_ASCII
end
end
it "raises a TypeError when the separator can't be converted to a string" do it "raises a TypeError when the separator can't be converted to a string" do
-> { "hello world".send(@method, false) {} }.should raise_error(TypeError) -> { "hello world".send(@method, false) {} }.should raise_error(TypeError)
-> { "hello world".send(@method, mock('x')) {} }.should raise_error(TypeError) -> { "hello world".send(@method, mock('x')) {} }.should raise_error(TypeError)

View File

@ -33,4 +33,19 @@ describe :string_partition, shared: true do
end end
end end
end end
it "returns before- and after- parts in the same encoding as self" do
strings = "hello".encode("US-ASCII").send(@method, "ello")
strings[0].encoding.should == Encoding::US_ASCII
strings[2].encoding.should == Encoding::US_ASCII
strings = "hello".encode("US-ASCII").send(@method, /ello/)
strings[0].encoding.should == Encoding::US_ASCII
strings[2].encoding.should == Encoding::US_ASCII
end
it "returns the matching part in the separator's encoding" do
strings = "hello".encode("US-ASCII").send(@method, "ello")
strings[1].encoding.should == Encoding::UTF_8
end
end end

View File

@ -80,7 +80,7 @@ describe :string_slice_index_length, shared: true do
"hello there".send(@method, -3,2).should == "er" "hello there".send(@method, -3,2).should == "er"
end end
it "returns a string with the same encoding" do it "returns a string with the same encoding as self" do
s = "hello there" s = "hello there"
s.send(@method, 1, 9).encoding.should == s.encoding s.send(@method, 1, 9).encoding.should == s.encoding
@ -206,6 +206,10 @@ describe :string_slice_range, shared: true do
"x".send(@method, 1..-1).should == "" "x".send(@method, 1..-1).should == ""
end end
it "returns a String in the same encoding as self" do
"hello there".encode("US-ASCII").send(@method, 1..1).encoding.should == Encoding::US_ASCII
end
it "returns nil if the beginning of the range falls outside of self" do it "returns nil if the beginning of the range falls outside of self" do
"hello there".send(@method, 12..-1).should == nil "hello there".send(@method, 12..-1).should == nil
"hello there".send(@method, 20..25).should == nil "hello there".send(@method, 20..25).should == nil
@ -328,7 +332,8 @@ describe :string_slice_regexp, shared: true do
"hello there".send(@method, /xyz/).should == nil "hello there".send(@method, /xyz/).should == nil
end end
not_supported_on :opal do it "returns a String in the same encoding as self" do
"hello there".encode("US-ASCII").send(@method, /[aeiou](.)\1/).encoding.should == Encoding::US_ASCII
end end
ruby_version_is ''...'3.0' do ruby_version_is ''...'3.0' do
@ -391,6 +396,10 @@ describe :string_slice_regexp_index, shared: true do
$~[1].should == nil $~[1].should == nil
end end
it "returns a String in the same encoding as self" do
"hello there".encode("US-ASCII").send(@method, /[aeiou](.)\1/, 0).encoding.should == Encoding::US_ASCII
end
it "calls to_int on the given index" do it "calls to_int on the given index" do
obj = mock('2') obj = mock('2')
obj.should_receive(:to_int).and_return(2) obj.should_receive(:to_int).and_return(2)

View File

@ -2,6 +2,10 @@ require_relative '../../../spec_helper'
require_relative '../fixtures/classes' require_relative '../fixtures/classes'
describe :string_strip, shared: true do describe :string_strip, shared: true do
it "returns a String in the same encoding as self" do
" hello ".encode("US-ASCII").send(@method).encoding.should == Encoding::US_ASCII
end
ruby_version_is '3.0' do ruby_version_is '3.0' do
it "returns String instances when called on a subclass" do it "returns String instances when called on a subclass" do
StringSpecs::MyString.new(" hello ").send(@method).should be_an_instance_of(String) StringSpecs::MyString.new(" hello ").send(@method).should be_an_instance_of(String)

View File

@ -74,6 +74,10 @@ describe :string_succ, shared: true do
StringSpecs::MyString.new("z").send(@method).should be_an_instance_of(String) StringSpecs::MyString.new("z").send(@method).should be_an_instance_of(String)
end end
end end
it "returns a String in the same encoding as self" do
"z".encode("US-ASCII").send(@method).encoding.should == Encoding::US_ASCII
end
end end
describe :string_succ_bang, shared: true do describe :string_succ_bang, shared: true do

View File

@ -246,6 +246,13 @@ describe "String#split with String" do
it "doesn't split on non-ascii whitespace" do it "doesn't split on non-ascii whitespace" do
"a\u{2008}b".split(" ").should == ["a\u{2008}b"] "a\u{2008}b".split(" ").should == ["a\u{2008}b"]
end end
it "returns Strings in the same encoding as self" do
strings = "hello world".encode("US-ASCII").split(" ")
strings[0].encoding.should == Encoding::US_ASCII
strings[1].encoding.should == Encoding::US_ASCII
end
end end
describe "String#split with Regexp" do describe "String#split with Regexp" do
@ -443,13 +450,12 @@ describe "String#split with Regexp" do
end end
end end
it "retains the encoding of the source string" do it "returns Strings in the same encoding as self" do
ary = "а б в".split ary = "а б в".split
encodings = ary.map { |s| s.encoding } encodings = ary.map { |s| s.encoding }
encodings.should == [Encoding::UTF_8, Encoding::UTF_8, Encoding::UTF_8] encodings.should == [Encoding::UTF_8, Encoding::UTF_8, Encoding::UTF_8]
end end
it "splits a string on each character for a multibyte encoding and empty split" do it "splits a string on each character for a multibyte encoding and empty split" do
"That's why efficiency could not be helped".split("").size.should == 39 "That's why efficiency could not be helped".split("").size.should == 39
end end
@ -598,4 +604,11 @@ describe "String#split with Regexp" do
-> { "hello".split(false) }.should raise_error(TypeError) -> { "hello".split(false) }.should raise_error(TypeError)
-> { "hello".split(Object.new) }.should raise_error(TypeError) -> { "hello".split(Object.new) }.should raise_error(TypeError)
end end
it "returns Strings in the same encoding as self" do
strings = "hello world".encode("US-ASCII").split(/ /)
strings[0].encoding.should == Encoding::US_ASCII
strings[1].encoding.should == Encoding::US_ASCII
end
end end

View File

@ -64,6 +64,11 @@ describe "String#squeeze" do
"hello room".squeeze(other_string, other_string2).should == "hello rom" "hello room".squeeze(other_string, other_string2).should == "hello rom"
end end
it "returns a String in the same encoding as self" do
"yellow moon".encode("US-ASCII").squeeze.encoding.should == Encoding::US_ASCII
"yellow moon".encode("US-ASCII").squeeze("a").encoding.should == Encoding::US_ASCII
end
it "raises a TypeError when one set arg can't be converted to a string" do it "raises a TypeError when one set arg can't be converted to a string" do
-> { "hello world".squeeze([]) }.should raise_error(TypeError) -> { "hello world".squeeze([]) }.should raise_error(TypeError)
-> { "hello world".squeeze(Object.new)}.should raise_error(TypeError) -> { "hello world".squeeze(Object.new)}.should raise_error(TypeError)

View File

@ -9,6 +9,10 @@ describe "String#swapcase" do
"+++---111222???".swapcase.should == "+++---111222???" "+++---111222???".swapcase.should == "+++---111222???"
end end
it "returns a String in the same encoding as self" do
"Hello".encode("US-ASCII").swapcase.encoding.should == Encoding::US_ASCII
end
describe "full Unicode case mapping" do describe "full Unicode case mapping" do
it "works for all of Unicode with no option" do it "works for all of Unicode with no option" do
"äÖü".swapcase.should == "ÄöÜ" "äÖü".swapcase.should == "ÄöÜ"

View File

@ -389,7 +389,7 @@ describe "String#undump" do
'"\\bv".force_encoding("UTF-16BE")'.undump.should == "\u0876".encode('utf-16be') '"\\bv".force_encoding("UTF-16BE")'.undump.should == "\u0876".encode('utf-16be')
end end
it "keeps origin encoding" do it "returns a String in the same encoding as self" do
'"foo"'.encode("ISO-8859-1").undump.encoding.should == Encoding::ISO_8859_1 '"foo"'.encode("ISO-8859-1").undump.encoding.should == Encoding::ISO_8859_1
'"foo"'.encode('windows-1251').undump.encoding.should == Encoding::Windows_1251 '"foo"'.encode('windows-1251').undump.encoding.should == Encoding::Windows_1251
end end

View File

@ -86,9 +86,19 @@ describe "String#unpack with format 'B'" do
].should be_computed_by(:unpack, "BBB") ].should be_computed_by(:unpack, "BBB")
end end
ruby_version_is ""..."3.3" do
it "ignores NULL bytes between directives" do it "ignores NULL bytes between directives" do
"\x80\x00".unpack("B\x00B").should == ["1", "0"] "\x80\x00".unpack("B\x00B").should == ["1", "0"]
end end
end
ruby_version_is "3.3" do
it "raise ArgumentError for NULL bytes between directives" do
-> {
"\x80\x00".unpack("B\x00B")
}.should raise_error(ArgumentError, /unknown unpack directive/)
end
end
it "ignores spaces between directives" do it "ignores spaces between directives" do
"\x80\x00".unpack("B B").should == ["1", "0"] "\x80\x00".unpack("B B").should == ["1", "0"]
@ -182,9 +192,19 @@ describe "String#unpack with format 'b'" do
].should be_computed_by(:unpack, "bbb") ].should be_computed_by(:unpack, "bbb")
end end
ruby_version_is ""..."3.3" do
it "ignores NULL bytes between directives" do it "ignores NULL bytes between directives" do
"\x01\x00".unpack("b\x00b").should == ["1", "0"] "\x01\x00".unpack("b\x00b").should == ["1", "0"]
end end
end
ruby_version_is "3.3" do
it "raise ArgumentError for NULL bytes between directives" do
-> {
"\x01\x00".unpack("b\x00b")
}.should raise_error(ArgumentError, /unknown unpack directive/)
end
end
it "ignores spaces between directives" do it "ignores spaces between directives" do
"\x01\x00".unpack("b b").should == ["1", "0"] "\x01\x00".unpack("b b").should == ["1", "0"]

View File

@ -35,9 +35,19 @@ describe :string_unpack_8bit, shared: true do
].should be_computed_by(:unpack, unpack_format(3)) ].should be_computed_by(:unpack, unpack_format(3))
end end
ruby_version_is ""..."3.3" do
it "ignores NULL bytes between directives" do it "ignores NULL bytes between directives" do
"abc".unpack(unpack_format("\000", 2)).should == [97, 98] "abc".unpack(unpack_format("\000", 2)).should == [97, 98]
end end
end
ruby_version_is "3.3" do
it "raise ArgumentError for NULL bytes between directives" do
-> {
"abc".unpack(unpack_format("\000", 2))
}.should raise_error(ArgumentError, /unknown unpack directive/)
end
end
it "ignores spaces between directives" do it "ignores spaces between directives" do
"abc".unpack(unpack_format(' ', 2)).should == [97, 98] "abc".unpack(unpack_format(' ', 2)).should == [97, 98]

View File

@ -56,9 +56,19 @@ describe "String#unpack with format 'H'" do
].should be_computed_by(:unpack, "HHH") ].should be_computed_by(:unpack, "HHH")
end end
ruby_version_is ""..."3.3" do
it "ignores NULL bytes between directives" do it "ignores NULL bytes between directives" do
"\x01\x10".unpack("H\x00H").should == ["0", "1"] "\x01\x10".unpack("H\x00H").should == ["0", "1"]
end end
end
ruby_version_is "3.3" do
it "raise ArgumentError for NULL bytes between directives" do
-> {
"\x01\x10".unpack("H\x00H")
}.should raise_error(ArgumentError, /unknown unpack directive/)
end
end
it "ignores spaces between directives" do it "ignores spaces between directives" do
"\x01\x10".unpack("H H").should == ["0", "1"] "\x01\x10".unpack("H H").should == ["0", "1"]
@ -121,9 +131,19 @@ describe "String#unpack with format 'h'" do
].should be_computed_by(:unpack, "hhh") ].should be_computed_by(:unpack, "hhh")
end end
ruby_version_is ""..."3.3" do
it "ignores NULL bytes between directives" do it "ignores NULL bytes between directives" do
"\x01\x10".unpack("h\x00h").should == ["1", "0"] "\x01\x10".unpack("h\x00h").should == ["1", "0"]
end end
end
ruby_version_is "3.3" do
it "raise ArgumentError for NULL bytes between directives" do
-> {
"\x01\x10".unpack("h\x00h")
}.should raise_error(ArgumentError, /unknown unpack directive/)
end
end
it "ignores spaces between directives" do it "ignores spaces between directives" do
"\x01\x10".unpack("h h").should == ["1", "0"] "\x01\x10".unpack("h h").should == ["1", "0"]

View File

@ -8,20 +8,6 @@ describe :string_unpack_basic, shared: true do
d.should_receive(:to_str).and_return("a"+unpack_format) d.should_receive(:to_str).and_return("a"+unpack_format)
"abc".unpack(d).should be_an_instance_of(Array) "abc".unpack(d).should be_an_instance_of(Array)
end end
it "raises a TypeError when passed nil" do
-> { "abc".unpack(nil) }.should raise_error(TypeError)
end
it "raises a TypeError when passed an Integer" do
-> { "abc".unpack(1) }.should raise_error(TypeError)
end
ruby_version_is "3.1" do
it "starts unpacking from the given offset" do
"abc".unpack("CC", offset: 1).should == [98, 99]
end
end
end end
describe :string_unpack_no_platform, shared: true do describe :string_unpack_no_platform, shared: true do
@ -32,18 +18,4 @@ describe :string_unpack_no_platform, shared: true do
it "raises an ArgumentError when the format modifier is '!'" do it "raises an ArgumentError when the format modifier is '!'" do
-> { "abcdefgh".unpack(unpack_format("!")) }.should raise_error(ArgumentError) -> { "abcdefgh".unpack(unpack_format("!")) }.should raise_error(ArgumentError)
end end
ruby_version_is "3.1" do
it "raises an ArgumentError when the offset is negative" do
-> { "a".unpack("C", offset: -1) }.should raise_error(ArgumentError)
end
it "returns nil if the offset is at the end of the string" do
"a".unpack("C", offset: 1).should == [nil]
end
it "raises an ArgumentError when the offset is larget than the string" do
-> { "a".unpack("C", offset: 2) }.should raise_error(ArgumentError)
end
end
end end

View File

@ -56,10 +56,20 @@ describe :string_unpack_float_le, shared: true do
[nan_value].pack(unpack_format).unpack(unpack_format).first.nan?.should be_true [nan_value].pack(unpack_format).unpack(unpack_format).first.nan?.should be_true
end end
ruby_version_is ""..."3.3" do
it "ignores NULL bytes between directives" do it "ignores NULL bytes between directives" do
array = "\x9a\x999@33\xb3?".unpack(unpack_format("\000", 2)) array = "\x9a\x999@33\xb3?".unpack(unpack_format("\000", 2))
array.should == [2.9000000953674316, 1.399999976158142] array.should == [2.9000000953674316, 1.399999976158142]
end end
end
ruby_version_is "3.3" do
it "raise ArgumentError for NULL bytes between directives" do
-> {
"\x9a\x999@33\xb3?".unpack(unpack_format("\000", 2))
}.should raise_error(ArgumentError, /unknown unpack directive/)
end
end
it "ignores spaces between directives" do it "ignores spaces between directives" do
array = "\x9a\x999@33\xb3?".unpack(unpack_format(' ', 2)) array = "\x9a\x999@33\xb3?".unpack(unpack_format(' ', 2))
@ -123,10 +133,20 @@ describe :string_unpack_float_be, shared: true do
[nan_value].pack(unpack_format).unpack(unpack_format).first.nan?.should be_true [nan_value].pack(unpack_format).unpack(unpack_format).first.nan?.should be_true
end end
ruby_version_is ""..."3.3" do
it "ignores NULL bytes between directives" do it "ignores NULL bytes between directives" do
array = "@9\x99\x9a?\xb333".unpack(unpack_format("\000", 2)) array = "@9\x99\x9a?\xb333".unpack(unpack_format("\000", 2))
array.should == [2.9000000953674316, 1.399999976158142] array.should == [2.9000000953674316, 1.399999976158142]
end end
end
ruby_version_is "3.3" do
it "raise ArgumentError for NULL bytes between directives" do
-> {
"@9\x99\x9a?\xb333".unpack(unpack_format("\000", 2))
}.should raise_error(ArgumentError, /unknown unpack directive/)
end
end
it "ignores spaces between directives" do it "ignores spaces between directives" do
array = "@9\x99\x9a?\xb333".unpack(unpack_format(' ', 2)) array = "@9\x99\x9a?\xb333".unpack(unpack_format(' ', 2))
@ -193,9 +213,19 @@ describe :string_unpack_double_le, shared: true do
[nan_value].pack(unpack_format).unpack(unpack_format).first.nan?.should be_true [nan_value].pack(unpack_format).unpack(unpack_format).first.nan?.should be_true
end end
ruby_version_is ""..."3.3" do
it "ignores NULL bytes between directives" do it "ignores NULL bytes between directives" do
"333333\x07@ffffff\xf6?".unpack(unpack_format("\000", 2)).should == [2.9, 1.4] "333333\x07@ffffff\xf6?".unpack(unpack_format("\000", 2)).should == [2.9, 1.4]
end end
end
ruby_version_is "3.3" do
it "raise ArgumentError for NULL bytes between directives" do
-> {
"333333\x07@ffffff\xf6?".unpack(unpack_format("\000", 2))
}.should raise_error(ArgumentError, /unknown unpack directive/)
end
end
it "ignores spaces between directives" do it "ignores spaces between directives" do
"333333\x07@ffffff\xf6?".unpack(unpack_format(' ', 2)).should == [2.9, 1.4] "333333\x07@ffffff\xf6?".unpack(unpack_format(' ', 2)).should == [2.9, 1.4]
@ -261,9 +291,19 @@ describe :string_unpack_double_be, shared: true do
[nan_value].pack(unpack_format).unpack(unpack_format).first.nan?.should be_true [nan_value].pack(unpack_format).unpack(unpack_format).first.nan?.should be_true
end end
ruby_version_is ""..."3.3" do
it "ignores NULL bytes between directives" do it "ignores NULL bytes between directives" do
"@\x07333333?\xf6ffffff".unpack(unpack_format("\000", 2)).should == [2.9, 1.4] "@\x07333333?\xf6ffffff".unpack(unpack_format("\000", 2)).should == [2.9, 1.4]
end end
end
ruby_version_is "3.3" do
it "raise ArgumentError for NULL bytes between directives" do
-> {
"@\x07333333?\xf6ffffff".unpack(unpack_format("\000", 2))
}.should raise_error(ArgumentError, /unknown unpack directive/)
end
end
it "ignores spaces between directives" do it "ignores spaces between directives" do
"@\x07333333?\xf6ffffff".unpack(unpack_format(' ', 2)).should == [2.9, 1.4] "@\x07333333?\xf6ffffff".unpack(unpack_format(' ', 2)).should == [2.9, 1.4]

View File

@ -32,9 +32,19 @@ describe :string_unpack_16bit_le, shared: true do
].should be_computed_by(:unpack, unpack_format(3)) ].should be_computed_by(:unpack, unpack_format(3))
end end
ruby_version_is ""..."3.3" do
it "ignores NULL bytes between directives" do it "ignores NULL bytes between directives" do
"abcd".unpack(unpack_format("\000", 2)).should == [25185, 25699] "abcd".unpack(unpack_format("\000", 2)).should == [25185, 25699]
end end
end
ruby_version_is "3.3" do
it "raise ArgumentError for NULL bytes between directives" do
-> {
"abcd".unpack(unpack_format("\000", 2))
}.should raise_error(ArgumentError, /unknown unpack directive/)
end
end
it "ignores spaces between directives" do it "ignores spaces between directives" do
"abcd".unpack(unpack_format(' ', 2)).should == [25185, 25699] "abcd".unpack(unpack_format(' ', 2)).should == [25185, 25699]
@ -85,9 +95,19 @@ describe :string_unpack_16bit_be, shared: true do
].should be_computed_by(:unpack, unpack_format(3)) ].should be_computed_by(:unpack, unpack_format(3))
end end
ruby_version_is ""..."3.3" do
it "ignores NULL bytes between directives" do it "ignores NULL bytes between directives" do
"badc".unpack(unpack_format("\000", 2)).should == [25185, 25699] "badc".unpack(unpack_format("\000", 2)).should == [25185, 25699]
end end
end
ruby_version_is "3.3" do
it "raise ArgumentError for NULL bytes between directives" do
-> {
"badc".unpack(unpack_format("\000", 2))
}.should raise_error(ArgumentError, /unknown unpack directive/)
end
end
it "ignores spaces between directives" do it "ignores spaces between directives" do
"badc".unpack(unpack_format(' ', 2)).should == [25185, 25699] "badc".unpack(unpack_format(' ', 2)).should == [25185, 25699]
@ -139,9 +159,19 @@ describe :string_unpack_32bit_le, shared: true do
].should be_computed_by(:unpack, unpack_format(3)) ].should be_computed_by(:unpack, unpack_format(3))
end end
ruby_version_is ""..."3.3" do
it "ignores NULL bytes between directives" do it "ignores NULL bytes between directives" do
"abcdefgh".unpack(unpack_format("\000", 2)).should == [1684234849, 1751606885] "abcdefgh".unpack(unpack_format("\000", 2)).should == [1684234849, 1751606885]
end end
end
ruby_version_is "3.3" do
it "raise ArgumentError for NULL bytes between directives" do
-> {
"abcdefgh".unpack(unpack_format("\000", 2))
}.should raise_error(ArgumentError, /unknown unpack directive/)
end
end
it "ignores spaces between directives" do it "ignores spaces between directives" do
"abcdefgh".unpack(unpack_format(' ', 2)).should == [1684234849, 1751606885] "abcdefgh".unpack(unpack_format(' ', 2)).should == [1684234849, 1751606885]
@ -193,9 +223,19 @@ describe :string_unpack_32bit_be, shared: true do
].should be_computed_by(:unpack, unpack_format(3)) ].should be_computed_by(:unpack, unpack_format(3))
end end
ruby_version_is ""..."3.3" do
it "ignores NULL bytes between directives" do it "ignores NULL bytes between directives" do
"dcbahgfe".unpack(unpack_format("\000", 2)).should == [1684234849, 1751606885] "dcbahgfe".unpack(unpack_format("\000", 2)).should == [1684234849, 1751606885]
end end
end
ruby_version_is "3.3" do
it "raise ArgumentError for NULL bytes between directives" do
-> {
"dcbahgfe".unpack(unpack_format("\000", 2))
}.should raise_error(ArgumentError, /unknown unpack directive/)
end
end
it "ignores spaces between directives" do it "ignores spaces between directives" do
"dcbahgfe".unpack(unpack_format(' ', 2)).should == [1684234849, 1751606885] "dcbahgfe".unpack(unpack_format(' ', 2)).should == [1684234849, 1751606885]
@ -243,10 +283,20 @@ describe :string_unpack_64bit_le, shared: true do
"abc".unpack(unpack_format('*')).should == [] "abc".unpack(unpack_format('*')).should == []
end end
ruby_version_is ""..."3.3" do
it "ignores NULL bytes between directives" do it "ignores NULL bytes between directives" do
array = "abcdefghabghefcd".unpack(unpack_format("\000", 2)) array = "abcdefghabghefcd".unpack(unpack_format("\000", 2))
array.should == [7523094288207667809, 7233738012216484449] array.should == [7523094288207667809, 7233738012216484449]
end end
end
ruby_version_is "3.3" do
it "raise ArgumentError for NULL bytes between directives" do
-> {
"badc".unpack(unpack_format("\000", 2))
}.should raise_error(ArgumentError, /unknown unpack directive/)
end
end
it "ignores spaces between directives" do it "ignores spaces between directives" do
array = "abcdefghabghefcd".unpack(unpack_format(' ', 2)) array = "abcdefghabghefcd".unpack(unpack_format(' ', 2))
@ -305,10 +355,20 @@ describe :string_unpack_64bit_be, shared: true do
"abc".unpack(unpack_format('*')).should == [] "abc".unpack(unpack_format('*')).should == []
end end
ruby_version_is ""..."3.3" do
it "ignores NULL bytes between directives" do it "ignores NULL bytes between directives" do
array = "hgfedcbadcfehgba".unpack(unpack_format("\000", 2)) array = "hgfedcbadcfehgba".unpack(unpack_format("\000", 2))
array.should == [7523094288207667809, 7233738012216484449] array.should == [7523094288207667809, 7233738012216484449]
end end
end
ruby_version_is "3.3" do
it "raise ArgumentError for NULL bytes between directives" do
-> {
"hgfedcbadcfehgba".unpack(unpack_format("\000", 2))
}.should raise_error(ArgumentError, /unknown unpack directive/)
end
end
it "ignores spaces between directives" do it "ignores spaces between directives" do
array = "hgfedcbadcfehgba".unpack(unpack_format(' ', 2)) array = "hgfedcbadcfehgba".unpack(unpack_format(' ', 2))

View File

@ -50,9 +50,19 @@ describe :string_unpack_unicode, shared: true do
"\xc2\x80".unpack("UUUU").should == [0x80] "\xc2\x80".unpack("UUUU").should == [0x80]
end end
ruby_version_is ""..."3.3" do
it "ignores NULL bytes between directives" do it "ignores NULL bytes between directives" do
"\x01\x02".unpack("U\x00U").should == [1, 2] "\x01\x02".unpack("U\x00U").should == [1, 2]
end end
end
ruby_version_is "3.3" do
it "raise ArgumentError for NULL bytes between directives" do
-> {
"\x01\x02".unpack("U\x00U")
}.should raise_error(ArgumentError, /unknown unpack directive/)
end
end
it "ignores spaces between directives" do it "ignores spaces between directives" do
"\x01\x02".unpack("U U").should == [1, 2] "\x01\x02".unpack("U U").should == [1, 2]

View File

@ -15,9 +15,19 @@ describe "String#unpack with directive 'w'" do
].should be_computed_by(:unpack, "w") ].should be_computed_by(:unpack, "w")
end end
ruby_version_is ""..."3.3" do
it "ignores NULL bytes between directives" do it "ignores NULL bytes between directives" do
"\x01\x02\x03".unpack("w\x00w").should == [1, 2] "\x01\x02\x03".unpack("w\x00w").should == [1, 2]
end end
end
ruby_version_is "3.3" do
it "raise ArgumentError for NULL bytes between directives" do
-> {
"\x01\x02\x03".unpack("w\x00w")
}.should raise_error(ArgumentError, /unknown unpack directive/)
end
end
it "ignores spaces between directives" do it "ignores spaces between directives" do
"\x01\x02\x03".unpack("w w").should == [1, 2] "\x01\x02\x03".unpack("w w").should == [1, 2]

View File

@ -15,16 +15,22 @@ describe "String#unpack1" do
"ZA".unpack1("B*", offset: 1).should == "01000001" "ZA".unpack1("B*", offset: 1).should == "01000001"
end end
it "traits offset as a bytes offset" do
"؈".unpack("CC").should == [216, 136]
"؈".unpack1("C").should == 216
"؈".unpack1("C", offset: 1).should == 136
end
it "raises an ArgumentError when the offset is negative" do it "raises an ArgumentError when the offset is negative" do
-> { "a".unpack1("C", offset: -1) }.should raise_error(ArgumentError) -> { "a".unpack1("C", offset: -1) }.should raise_error(ArgumentError, "offset can't be negative")
end end
it "returns nil if the offset is at the end of the string" do it "returns nil if the offset is at the end of the string" do
"a".unpack1("C", offset: 1).should == nil "a".unpack1("C", offset: 1).should == nil
end end
it "raises an ArgumentError when the offset is larget than the string" do it "raises an ArgumentError when the offset is larger than the string bytesize" do
-> { "a".unpack1("C", offset: 2) }.should raise_error(ArgumentError) -> { "a".unpack1("C", offset: 2) }.should raise_error(ArgumentError, "offset outside of string")
end end
end end
end end

View File

@ -0,0 +1,34 @@
require_relative '../../spec_helper'
describe "String#unpack" do
it "raises a TypeError when passed nil" do
-> { "abc".unpack(nil) }.should raise_error(TypeError)
end
it "raises a TypeError when passed an Integer" do
-> { "abc".unpack(1) }.should raise_error(TypeError)
end
ruby_version_is "3.1" do
it "starts unpacking from the given offset" do
"abc".unpack("CC", offset: 1).should == [98, 99]
end
it "traits offset as a bytes offset" do
"؈".unpack("CC").should == [216, 136]
"؈".unpack("CC", offset: 1).should == [136, nil]
end
it "raises an ArgumentError when the offset is negative" do
-> { "a".unpack("C", offset: -1) }.should raise_error(ArgumentError, "offset can't be negative")
end
it "returns nil if the offset is at the end of the string" do
"a".unpack("C", offset: 1).should == [nil]
end
it "raises an ArgumentError when the offset is larget than the string" do
-> { "a".unpack("C", offset: 2) }.should raise_error(ArgumentError, "offset outside of string")
end
end
end

View File

@ -8,6 +8,10 @@ describe "String#upcase" do
"hello".upcase.should == "HELLO" "hello".upcase.should == "HELLO"
end end
it "returns a String in the same encoding as self" do
"hello".encode("US-ASCII").upcase.encoding.should == Encoding::US_ASCII
end
describe "full Unicode case mapping" do describe "full Unicode case mapping" do
it "works for all of Unicode with no option" do it "works for all of Unicode with no option" do
"äöü".upcase.should == "ÄÖÜ" "äöü".upcase.should == "ÄÖÜ"

View File

@ -0,0 +1,214 @@
# -*- encoding: utf-8 -*-
require_relative '../../../spec_helper'
describe "String#valid_encoding? and UTF-8" do
def utf8(bytes)
bytes.pack("C*").force_encoding("UTF-8")
end
describe "1-byte character" do
it "is valid if is in format 0xxxxxxx" do
utf8([0b00000000]).valid_encoding?.should == true
utf8([0b01111111]).valid_encoding?.should == true
end
it "is not valid if is not in format 0xxxxxxx" do
utf8([0b10000000]).valid_encoding?.should == false
utf8([0b11111111]).valid_encoding?.should == false
end
end
describe "2-bytes character" do
it "is valid if in format [110xxxxx 10xxxxx]" do
utf8([0b11000010, 0b10000000]).valid_encoding?.should == true
utf8([0b11000010, 0b10111111]).valid_encoding?.should == true
utf8([0b11011111, 0b10000000]).valid_encoding?.should == true
utf8([0b11011111, 0b10111111]).valid_encoding?.should == true
end
it "is not valid if the first byte is not in format 110xxxxx" do
utf8([0b00000010, 0b10000000]).valid_encoding?.should == false
utf8([0b00100010, 0b10000000]).valid_encoding?.should == false
utf8([0b01000010, 0b10000000]).valid_encoding?.should == false
utf8([0b01100010, 0b10000000]).valid_encoding?.should == false
utf8([0b10000010, 0b10000000]).valid_encoding?.should == false
utf8([0b10100010, 0b10000000]).valid_encoding?.should == false
utf8([0b11000010, 0b10000000]).valid_encoding?.should == true # correct bytes
utf8([0b11100010, 0b10000000]).valid_encoding?.should == false
end
it "is not valid if the second byte is not in format 10xxxxxx" do
utf8([0b11000010, 0b00000000]).valid_encoding?.should == false
utf8([0b11000010, 0b01000000]).valid_encoding?.should == false
utf8([0b11000010, 0b11000000]).valid_encoding?.should == false
end
it "is not valid if is smaller than [xxxxxx10 xx000000] (codepoints < U+007F, that are encoded with the 1-byte format)" do
utf8([0b11000000, 0b10111111]).valid_encoding?.should == false
utf8([0b11000001, 0b10111111]).valid_encoding?.should == false
end
it "is not valid if the first byte is missing" do
bytes = [0b11000010, 0b10000000]
utf8(bytes[1..1]).valid_encoding?.should == false
end
it "is not valid if the second byte is missing" do
bytes = [0b11000010, 0b10000000]
utf8(bytes[0..0]).valid_encoding?.should == false
end
end
describe "3-bytes character" do
it "is valid if in format [1110xxxx 10xxxxxx 10xxxxxx]" do
utf8([0b11100000, 0b10100000, 0b10000000]).valid_encoding?.should == true
utf8([0b11100000, 0b10100000, 0b10111111]).valid_encoding?.should == true
utf8([0b11100000, 0b10111111, 0b10111111]).valid_encoding?.should == true
utf8([0b11101111, 0b10111111, 0b10111111]).valid_encoding?.should == true
end
it "is not valid if the first byte is not in format 1110xxxx" do
utf8([0b00000000, 0b10100000, 0b10000000]).valid_encoding?.should == false
utf8([0b00010000, 0b10100000, 0b10000000]).valid_encoding?.should == false
utf8([0b00100000, 0b10100000, 0b10000000]).valid_encoding?.should == false
utf8([0b00110000, 0b10100000, 0b10000000]).valid_encoding?.should == false
utf8([0b01000000, 0b10100000, 0b10000000]).valid_encoding?.should == false
utf8([0b01010000, 0b10100000, 0b10000000]).valid_encoding?.should == false
utf8([0b01100000, 0b10100000, 0b10000000]).valid_encoding?.should == false
utf8([0b01110000, 0b10100000, 0b10000000]).valid_encoding?.should == false
utf8([0b10000000, 0b10100000, 0b10000000]).valid_encoding?.should == false
utf8([0b10010000, 0b10100000, 0b10000000]).valid_encoding?.should == false
utf8([0b10100000, 0b10100000, 0b10000000]).valid_encoding?.should == false
utf8([0b10110000, 0b10100000, 0b10000000]).valid_encoding?.should == false
utf8([0b11000000, 0b10100000, 0b10000000]).valid_encoding?.should == false
utf8([0b11010000, 0b10100000, 0b10000000]).valid_encoding?.should == false
utf8([0b11100000, 0b10100000, 0b10000000]).valid_encoding?.should == true # correct bytes
utf8([0b11110000, 0b10100000, 0b10000000]).valid_encoding?.should == false
end
it "is not valid if the second byte is not in format 10xxxxxx" do
utf8([0b11100000, 0b00100000, 0b10000000]).valid_encoding?.should == false
utf8([0b11100000, 0b01100000, 0b10000000]).valid_encoding?.should == false
utf8([0b11100000, 0b11100000, 0b10000000]).valid_encoding?.should == false
end
it "is not valid if the third byte is not in format 10xxxxxx" do
utf8([0b11100000, 0b10100000, 0b00000000]).valid_encoding?.should == false
utf8([0b11100000, 0b10100000, 0b01000000]).valid_encoding?.should == false
utf8([0b11100000, 0b10100000, 0b01000000]).valid_encoding?.should == false
end
it "is not valid if is smaller than [xxxx0000 xx100000 xx000000] (codepoints < U+07FF that are encoded with the 2-byte format)" do
utf8([0b11100000, 0b10010000, 0b10000000]).valid_encoding?.should == false
utf8([0b11100000, 0b10001000, 0b10000000]).valid_encoding?.should == false
utf8([0b11100000, 0b10000100, 0b10000000]).valid_encoding?.should == false
utf8([0b11100000, 0b10000010, 0b10000000]).valid_encoding?.should == false
utf8([0b11100000, 0b10000001, 0b10000000]).valid_encoding?.should == false
utf8([0b11100000, 0b10000000, 0b10000000]).valid_encoding?.should == false
end
it "is not valid if in range [xxxx1101 xx100000 xx000000] - [xxxx1101 xx111111 xx111111] (codepoints U+D800 - U+DFFF)" do
utf8([0b11101101, 0b10100000, 0b10000000]).valid_encoding?.should == false
utf8([0b11101101, 0b10100000, 0b10000001]).valid_encoding?.should == false
utf8([0b11101101, 0b10111111, 0b10111111]).valid_encoding?.should == false
utf8([0b11101101, 0b10011111, 0b10111111]).valid_encoding?.should == true # lower boundary - 1
utf8([0b11101110, 0b10000000, 0b10000000]).valid_encoding?.should == true # upper boundary + 1
end
it "is not valid if the first byte is missing" do
bytes = [0b11100000, 0b10100000, 0b10000000]
utf8(bytes[2..3]).valid_encoding?.should == false
end
it "is not valid if the second byte is missing" do
bytes = [0b11100000, 0b10100000, 0b10000000]
utf8([bytes[0], bytes[2]]).valid_encoding?.should == false
end
it "is not valid if the second and the third bytes are missing" do
bytes = [0b11100000, 0b10100000, 0b10000000]
utf8(bytes[0..0]).valid_encoding?.should == false
end
end
describe "4-bytes character" do
it "is valid if in format [11110xxx 10xxxxxx 10xxxxxx 10xxxxxx]" do
utf8([0b11110000, 0b10010000, 0b10000000, 0b10000000]).valid_encoding?.should == true
utf8([0b11110000, 0b10010000, 0b10000000, 0b10111111]).valid_encoding?.should == true
utf8([0b11110000, 0b10010000, 0b10111111, 0b10111111]).valid_encoding?.should == true
utf8([0b11110000, 0b10111111, 0b10111111, 0b10111111]).valid_encoding?.should == true
utf8([0b11110100, 0b10001111, 0b10111111, 0b10111111]).valid_encoding?.should == true
end
it "is not valid if the first byte is not in format 11110xxx" do
utf8([0b11100000, 0b10010000, 0b10000000, 0b10000000]).valid_encoding?.should == false
utf8([0b11010000, 0b10010000, 0b10000000, 0b10000000]).valid_encoding?.should == false
utf8([0b10110000, 0b10010000, 0b10000000, 0b10000000]).valid_encoding?.should == false
utf8([0b01110000, 0b10010000, 0b10000000, 0b10000000]).valid_encoding?.should == false
end
it "is not valid if the second byte is not in format 10xxxxxx" do
utf8([0b11110000, 0b00010000, 0b10000000, 0b10000000]).valid_encoding?.should == false
utf8([0b11110000, 0b01010000, 0b10000000, 0b10000000]).valid_encoding?.should == false
utf8([0b11110000, 0b10010000, 0b10000000, 0b10000000]).valid_encoding?.should == true # correct bytes
utf8([0b11110000, 0b11010000, 0b10000000, 0b10000000]).valid_encoding?.should == false
end
it "is not valid if the third byte is not in format 10xxxxxx" do
utf8([0b11110000, 0b10010000, 0b00000000, 0b10000000]).valid_encoding?.should == false
utf8([0b11110000, 0b10010000, 0b01000000, 0b10000000]).valid_encoding?.should == false
utf8([0b11110000, 0b10010000, 0b10000000, 0b10000000]).valid_encoding?.should == true # correct bytes
utf8([0b11110000, 0b10010000, 0b11000000, 0b10000000]).valid_encoding?.should == false
end
it "is not valid if the forth byte is not in format 10xxxxxx" do
utf8([0b11110000, 0b10010000, 0b10000000, 0b00000000]).valid_encoding?.should == false
utf8([0b11110000, 0b10010000, 0b10000000, 0b01000000]).valid_encoding?.should == false
utf8([0b11110000, 0b10010000, 0b10000000, 0b10000000]).valid_encoding?.should == true # correct bytes
utf8([0b11110000, 0b10010000, 0b10000000, 0b11000000]).valid_encoding?.should == false
end
it "is not valid if is smaller than [xxxxx000 xx001000 xx000000 xx000000] (codepoint < U+10000)" do
utf8([0b11110000, 0b10000111, 0b10000000, 0b10000000]).valid_encoding?.should == false
utf8([0b11110000, 0b10000110, 0b10000000, 0b10000000]).valid_encoding?.should == false
utf8([0b11110000, 0b10000101, 0b10000000, 0b10000000]).valid_encoding?.should == false
utf8([0b11110000, 0b10000100, 0b10000000, 0b10000000]).valid_encoding?.should == false
utf8([0b11110000, 0b10000011, 0b10000000, 0b10000000]).valid_encoding?.should == false
utf8([0b11110000, 0b10000010, 0b10000000, 0b10000000]).valid_encoding?.should == false
utf8([0b11110000, 0b10000001, 0b10000000, 0b10000000]).valid_encoding?.should == false
utf8([0b11110000, 0b10000000, 0b10000000, 0b10000000]).valid_encoding?.should == false
end
it "is not valid if is greater than [xxxxx100 xx001111 xx111111 xx111111] (codepoint > U+10FFFF)" do
utf8([0b11110100, 0b10010000, 0b10000000, 0b10000000]).valid_encoding?.should == false
utf8([0b11110100, 0b10100000, 0b10000000, 0b10000000]).valid_encoding?.should == false
utf8([0b11110100, 0b10110000, 0b10000000, 0b10000000]).valid_encoding?.should == false
utf8([0b11110101, 0b10001111, 0b10111111, 0b10111111]).valid_encoding?.should == false
utf8([0b11110110, 0b10001111, 0b10111111, 0b10111111]).valid_encoding?.should == false
utf8([0b11110111, 0b10001111, 0b10111111, 0b10111111]).valid_encoding?.should == false
end
it "is not valid if the first byte is missing" do
bytes = [0b11110000, 0b10010000, 0b10000000, 0b10000000]
utf8(bytes[1..3]).valid_encoding?.should == false
end
it "is not valid if the second byte is missing" do
bytes = [0b11110000, 0b10010000, 0b10000000, 0b10000000]
utf8([bytes[0], bytes[2], bytes[3]]).valid_encoding?.should == false
end
it "is not valid if the second and the third bytes are missing" do
bytes = [0b11110000, 0b10010000, 0b10000000, 0b10000000]
utf8([bytes[0], bytes[3]]).valid_encoding?.should == false
end
it "is not valid if the second, the third and the fourth bytes are missing" do
bytes = [0b11110000, 0b10010000, 0b10000000, 0b10000000]
utf8(bytes[0..0]).valid_encoding?.should == false
end
end
end

View File

@ -1,16 +1,59 @@
require_relative '../../spec_helper' require_relative '../../spec_helper'
require_relative 'fixtures/classes' require_relative 'fixtures/classes'
# Should be synchronized with core/array/values_at_spec.rb
describe "Struct#values_at" do describe "Struct#values_at" do
it "returns an array of values" do before do
clazz = Struct.new(:name, :director, :year) clazz = Struct.new(:name, :director, :year)
movie = clazz.new('Sympathy for Mr. Vengeance', 'Chan-wook Park', 2002) @movie = clazz.new('Sympathy for Mr. Vengeance', 'Chan-wook Park', 2002)
movie.values_at(0, 1).should == ['Sympathy for Mr. Vengeance', 'Chan-wook Park'] end
movie.values_at(0..2).should == ['Sympathy for Mr. Vengeance', 'Chan-wook Park', 2002]
context "when passed a list of Integers" do
it "returns an array containing each value given by one of integers" do
@movie.values_at(0, 1).should == ['Sympathy for Mr. Vengeance', 'Chan-wook Park']
end
it "raises IndexError if any of integers is out of range" do
-> { @movie.values_at(3) }.should raise_error(IndexError, "offset 3 too large for struct(size:3)")
-> { @movie.values_at(-4) }.should raise_error(IndexError, "offset -4 too small for struct(size:3)")
end
end
context "when passed an integer Range" do
it "returns an array containing each value given by the elements of the range" do
@movie.values_at(0..2).should == ['Sympathy for Mr. Vengeance', 'Chan-wook Park', 2002]
end
it "fills with nil values for range elements larger than the structure" do
@movie.values_at(0..3).should == ['Sympathy for Mr. Vengeance', 'Chan-wook Park', 2002, nil]
end
it "raises RangeError if any element of the range is negative and out of range" do
-> { @movie.values_at(-4..3) }.should raise_error(RangeError, "-4..3 out of range")
end
it "supports endless Range" do
@movie.values_at(0..).should == ["Sympathy for Mr. Vengeance", "Chan-wook Park", 2002]
end
it "supports beginningless Range" do
@movie.values_at(..2).should == ["Sympathy for Mr. Vengeance", "Chan-wook Park", 2002]
end
end
it "supports multiple integer Ranges" do
@movie.values_at(0..2, 1..2).should == ['Sympathy for Mr. Vengeance', 'Chan-wook Park', 2002, 'Chan-wook Park', 2002]
end
it "supports mixing integer Ranges and Integers" do
@movie.values_at(0..2, 2).should == ['Sympathy for Mr. Vengeance', 'Chan-wook Park', 2002, 2002]
end
it "returns a new empty Array if no arguments given" do
@movie.values_at().should == []
end end
it "fails when passed unsupported types" do it "fails when passed unsupported types" do
car = StructClasses::Car.new('Ford', 'Ranger') -> { @movie.values_at('make') }.should raise_error(TypeError, "no implicit conversion of String into Integer")
-> { car.values_at('make') }.should raise_error(TypeError)
end end
end end

View File

@ -6,4 +6,11 @@ describe :symbol_id2name, shared: true do
:@ruby.send(@method).should == "@ruby" :@ruby.send(@method).should == "@ruby"
:@@ruby.send(@method).should == "@@ruby" :@@ruby.send(@method).should == "@@ruby"
end end
it "returns a String in the same encoding as self" do
string = "ruby".encode("US-ASCII")
symbol = string.to_sym
symbol.send(@method).encoding.should == Encoding::US_ASCII
end
end end

View File

@ -251,6 +251,22 @@ describe "Time.at" do
time.to_i.should == @epoch_time time.to_i.should == @epoch_time
end end
it "could be UTC offset as a 'UTC' String" do
time = Time.at(@epoch_time, in: "UTC")
time.utc_offset.should == 0
time.zone.should == "UTC"
time.to_i.should == @epoch_time
end
it "could be UTC offset as a military zone A-Z" do
time = Time.at(@epoch_time, in: "B")
time.utc_offset.should == 3600 * 2
time.zone.should == nil
time.to_i.should == @epoch_time
end
it "could be a timezone object" do it "could be a timezone object" do
zone = TimeSpecs::TimezoneWithName.new(name: "Asia/Colombo") zone = TimeSpecs::TimezoneWithName.new(name: "Asia/Colombo")
time = Time.at(@epoch_time, in: zone) time = Time.at(@epoch_time, in: zone)

View File

@ -29,10 +29,10 @@ describe "Time#localtime" do
time.localtime.should equal(time) time.localtime.should equal(time)
end end
it "raises a RuntimeError if the time has a different time zone" do it "raises a FrozenError if the time has a different time zone" do
time = Time.gm(2007, 1, 9, 12, 0, 0) time = Time.gm(2007, 1, 9, 12, 0, 0)
time.freeze time.freeze
-> { time.localtime }.should raise_error(RuntimeError) -> { time.localtime }.should raise_error(FrozenError)
end end
end end
@ -79,6 +79,18 @@ describe "Time#localtime" do
t.utc_offset.should == -3600 t.utc_offset.should == -3600
end end
it "returns a Time with a UTC offset specified as UTC" do
t = Time.new(2007, 1, 9, 12, 0, 0, 3600)
t.localtime("UTC")
t.utc_offset.should == 0
end
it "returns a Time with a UTC offset specified as A-Z military zone" do
t = Time.new(2007, 1, 9, 12, 0, 0, 3600)
t.localtime("B")
t.utc_offset.should == 3600 * 2
end
platform_is_not :windows do platform_is_not :windows do
it "changes the timezone according to the set one" do it "changes the timezone according to the set one" do
t = Time.new(2005, 2, 27, 22, 50, 0, -3600) t = Time.new(2005, 2, 27, 22, 50, 0, -3600)

View File

@ -58,6 +58,32 @@ describe "Time.new with a utc_offset argument" do
Time.new(2000, 1, 1, 0, 0, 0, "-04:10:43").utc_offset.should == -15043 Time.new(2000, 1, 1, 0, 0, 0, "-04:10:43").utc_offset.should == -15043
end end
ruby_bug '#13669', '3.0'...'3.1' do
it "returns a Time with a UTC offset specified as +HH" do
Time.new(2000, 1, 1, 0, 0, 0, "+05").utc_offset.should == 3600 * 5
end
it "returns a Time with a UTC offset specified as -HH" do
Time.new(2000, 1, 1, 0, 0, 0, "-05").utc_offset.should == -3600 * 5
end
it "returns a Time with a UTC offset specified as +HHMM" do
Time.new(2000, 1, 1, 0, 0, 0, "+0530").utc_offset.should == 19800
end
it "returns a Time with a UTC offset specified as -HHMM" do
Time.new(2000, 1, 1, 0, 0, 0, "-0530").utc_offset.should == -19800
end
it "returns a Time with a UTC offset specified as +HHMMSS" do
Time.new(2000, 1, 1, 0, 0, 0, "+053037").utc_offset.should == 19837
end
it "returns a Time with a UTC offset specified as -HHMMSS" do
Time.new(2000, 1, 1, 0, 0, 0, "-053037").utc_offset.should == -19837
end
end
describe "with an argument that responds to #to_str" do describe "with an argument that responds to #to_str" do
it "coerces using #to_str" do it "coerces using #to_str" do
o = mock('string') o = mock('string')
@ -66,6 +92,57 @@ describe "Time.new with a utc_offset argument" do
end end
end end
it "returns a Time with UTC offset specified as UTC" do
Time.new(2000, 1, 1, 0, 0, 0, "UTC").utc_offset.should == 0
end
it "returns a Time with UTC offset specified as a single letter military timezone" do
[
["A", 3600],
["B", 3600 * 2],
["C", 3600 * 3],
["D", 3600 * 4],
["E", 3600 * 5],
["F", 3600 * 6],
["G", 3600 * 7],
["H", 3600 * 8],
["I", 3600 * 9],
# J is not supported
["K", 3600 * 10],
["L", 3600 * 11],
["M", 3600 * 12],
["N", 3600 * -1],
["O", 3600 * -2],
["P", 3600 * -3],
["Q", 3600 * -4],
["R", 3600 * -5],
["S", 3600 * -6],
["T", 3600 * -7],
["U", 3600 * -8],
["V", 3600 * -9],
["W", 3600 * -10],
["X", 3600 * -11],
["Y", 3600 * -12],
["Z", 0]
].each do |letter, offset|
Time.new(2000, 1, 1, 0, 0, 0, letter).utc_offset.should == offset
end
end
ruby_version_is ""..."3.1" do
it "raises ArgumentError if the string argument is J" do
message = '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset'
-> { Time.new(2000, 1, 1, 0, 0, 0, "J") }.should raise_error(ArgumentError, message)
end
end
ruby_version_is "3.1" do
it "raises ArgumentError if the string argument is J" do
message = '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: J'
-> { Time.new(2000, 1, 1, 0, 0, 0, "J") }.should raise_error(ArgumentError, message)
end
end
it "returns a local Time if the argument is nil" do it "returns a local Time if the argument is nil" do
with_timezone("PST", -8) do with_timezone("PST", -8) do
t = Time.new(2000, 1, 1, 0, 0, 0, nil) t = Time.new(2000, 1, 1, 0, 0, 0, nil)
@ -93,7 +170,12 @@ describe "Time.new with a utc_offset argument" do
end end
it "raises ArgumentError if the String argument is not in an ASCII-compatible encoding" do it "raises ArgumentError if the String argument is not in an ASCII-compatible encoding" do
-> { Time.new(2000, 1, 1, 0, 0, 0, "-04:10".encode("UTF-16LE")) }.should raise_error(ArgumentError) # Don't check exception message - it was changed in previous CRuby versions:
# - "string contains null byte"
# - '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset'
-> {
Time.new(2000, 1, 1, 0, 0, 0, "-04:10".encode("UTF-16LE"))
}.should raise_error(ArgumentError)
end end
it "raises ArgumentError if the argument represents a value less than or equal to -86400 seconds" do it "raises ArgumentError if the argument represents a value less than or equal to -86400 seconds" do
@ -106,19 +188,9 @@ describe "Time.new with a utc_offset argument" do
-> { Time.new(2000, 1, 1, 0, 0, 0, 86400) }.should raise_error(ArgumentError) -> { Time.new(2000, 1, 1, 0, 0, 0, 86400) }.should raise_error(ArgumentError)
end end
it "raises ArgumentError if the seconds argument is negative" do
-> { Time.new(2000, 1, 1, 0, 0, -1) }.should raise_error(ArgumentError)
end
it "raises ArgumentError if the utc_offset argument is greater than or equal to 10e9" do it "raises ArgumentError if the utc_offset argument is greater than or equal to 10e9" do
-> { Time.new(2000, 1, 1, 0, 0, 0, 1000000000) }.should raise_error(ArgumentError) -> { Time.new(2000, 1, 1, 0, 0, 0, 1000000000) }.should raise_error(ArgumentError)
end end
it "raises ArgumentError if the month is greater than 12" do
# For some reason MRI uses a different message for month in 13-15 and month>=16
-> { Time.new(2000, 13, 1, 0, 0, 0, "+01:00") }.should raise_error(ArgumentError, /(mon|argument) out of range/)
-> { Time.new(2000, 16, 1, 0, 0, 0, "+01:00") }.should raise_error(ArgumentError, "argument out of range")
end
end end
describe "Time.new with a timezone argument" do describe "Time.new with a timezone argument" do

View File

@ -22,11 +22,11 @@ describe :time_gmtime, shared: true do
time.send(@method).should equal(time) time.send(@method).should equal(time)
end end
it "raises a RuntimeError if the time is not UTC" do it "raises a FrozenError if the time is not UTC" do
with_timezone("CST", -6) do with_timezone("CST", -6) do
time = Time.now time = Time.now
time.freeze time.freeze
-> { time.send(@method) }.should raise_error(RuntimeError) -> { time.send(@method) }.should raise_error(FrozenError)
end end
end end
end end

View File

@ -145,9 +145,10 @@ describe :time_params, shared: true do
end end
it "raises an ArgumentError for out of range month" do it "raises an ArgumentError for out of range month" do
# For some reason MRI uses a different message for month in 13-15 and month>=16
-> { -> {
Time.send(@method, 2008, 13, 31, 23, 59, 59) Time.send(@method, 2008, 16, 31, 23, 59, 59)
}.should raise_error(ArgumentError) }.should raise_error(ArgumentError, /(mon|argument) out of range/)
end end
it "raises an ArgumentError for out of range day" do it "raises an ArgumentError for out of range day" do
@ -169,9 +170,13 @@ describe :time_params, shared: true do
end end
it "raises an ArgumentError for out of range second" do it "raises an ArgumentError for out of range second" do
# For some reason MRI uses different messages for seconds 61-63 and seconds >= 64
-> { -> {
Time.send(@method, 2008, 12, 31, 23, 59, 61) Time.send(@method, 2008, 12, 31, 23, 59, 61)
}.should raise_error(ArgumentError) }.should raise_error(ArgumentError, /(sec|argument) out of range/)
-> {
Time.send(@method, 2008, 12, 31, 23, 59, -1)
}.should raise_error(ArgumentError, "argument out of range")
end end
it "raises ArgumentError when given 9 arguments" do it "raises ArgumentError when given 9 arguments" do

View File

@ -52,10 +52,42 @@ describe "Time#strftime" do
ruby_version_is "3.1" do ruby_version_is "3.1" do
it "supports RFC 3339 UTC for unknown offset local time, -0000, as %-z" do it "supports RFC 3339 UTC for unknown offset local time, -0000, as %-z" do
@time.strftime("%z").should == "+0000" time = Time.gm(2022)
@time.strftime("%-z").should == "-0000"
@time.strftime("%-:z").should == "-00:00" time.strftime("%z").should == "+0000"
@time.strftime("%-::z").should == "-00:00:00" time.strftime("%-z").should == "-0000"
time.strftime("%-:z").should == "-00:00"
time.strftime("%-::z").should == "-00:00:00"
end
it "applies '-' flag to UTC time" do
time = Time.utc(2022)
time.strftime("%-z").should == "-0000"
time = Time.gm(2022)
time.strftime("%-z").should == "-0000"
time = Time.new(2022, 1, 1, 0, 0, 0, "Z")
time.strftime("%-z").should == "-0000"
time = Time.new(2022, 1, 1, 0, 0, 0, "-00:00")
time.strftime("%-z").should == "-0000"
time = Time.new(2022, 1, 1, 0, 0, 0, "+03:00").utc
time.strftime("%-z").should == "-0000"
end
it "ignores '-' flag for non-UTC time" do
time = Time.new(2022, 1, 1, 0, 0, 0, "+03:00")
time.strftime("%-z").should == "+0300"
end
it "works correctly with width, _ and 0 flags, and :" do
Time.now.utc.strftime("%-_10z").should == " -000"
Time.now.utc.strftime("%-10z").should == "-000000000"
Time.now.utc.strftime("%-010:z").should == "-000000:00"
Time.now.utc.strftime("%-_10:z").should == " -0:00"
Time.now.utc.strftime("%-_10::z").should == " -0:00:00"
end end
end end
end end

View File

@ -4,8 +4,45 @@ require_relative 'shared/gmtime'
require_relative 'shared/time_params' require_relative 'shared/time_params'
describe "Time#utc?" do describe "Time#utc?" do
it "returns true if time represents a time in UTC (GMT)" do it "returns true only if time represents a time in UTC (GMT)" do
Time.now.should_not.utc? Time.now.utc?.should == false
Time.now.utc.utc?.should == true
end
it "treats time as UTC what was created in different ways" do
Time.now.utc.utc?.should == true
Time.now.gmtime.utc?.should == true
Time.now.getgm.utc?.should == true
Time.now.getutc.utc?.should == true
Time.utc(2022).utc?.should == true
end
it "does treat time with 'UTC' offset as UTC" do
Time.new(2022, 1, 1, 0, 0, 0, "UTC").utc?.should == true
Time.now.localtime("UTC").utc?.should == true
Time.at(Time.now, in: 'UTC').utc?.should == true
end
it "does treat time with Z offset as UTC" do
Time.new(2022, 1, 1, 0, 0, 0, "Z").utc?.should == true
Time.now.localtime("Z").utc?.should == true
Time.at(Time.now, in: 'Z').utc?.should == true
end
ruby_version_is "3.1" do
it "does treat time with -00:00 offset as UTC" do
Time.new(2022, 1, 1, 0, 0, 0, "-00:00").utc?.should == true
Time.now.localtime("-00:00").utc?.should == true
Time.at(Time.now, in: '-00:00').utc?.should == true
end
end
it "does not treat time with +00:00 offset as UTC" do
Time.new(2022, 1, 1, 0, 0, 0, "+00:00").utc?.should == false
end
it "does not treat time with 0 offset as UTC" do
Time.new(2022, 1, 1, 0, 0, 0, 0).utc?.should == false
end end
end end

View File

@ -52,14 +52,28 @@ describe "Time#zone" do
end end
it "doesn't raise errors for a Time with a fixed offset" do it "doesn't raise errors for a Time with a fixed offset" do
-> { Time.new(2001, 1, 1, 0, 0, 0, "+05:00").zone.should == nil
Time.new(2001, 1, 1, 0, 0, 0, "+05:00").zone
}.should_not raise_error
end end
end end
it "returns UTC when called on a UTC time" do it "returns UTC when called on a UTC time" do
Time.now.utc.zone.should == "UTC" Time.now.utc.zone.should == "UTC"
Time.now.gmtime.zone.should == "UTC"
Time.now.getgm.zone.should == "UTC"
Time.now.getutc.zone.should == "UTC"
Time.utc(2022).zone.should == "UTC"
Time.new(2022, 1, 1, 0, 0, 0, "UTC").zone.should == "UTC"
Time.new(2022, 1, 1, 0, 0, 0, "Z").zone.should == "UTC"
Time.now.localtime("UTC").zone.should == "UTC"
Time.now.localtime("Z").zone.should == "UTC"
Time.at(Time.now, in: 'UTC').zone.should == "UTC"
Time.at(Time.now, in: 'Z').zone.should == "UTC"
ruby_version_is "3.1" do
Time.new(2022, 1, 1, 0, 0, 0, "-00:00").zone.should == "UTC"
Time.now.localtime("-00:00").zone.should == "UTC"
Time.at(Time.now, in: '-00:00').zone.should == "UTC"
end
end end
platform_is_not :aix, :windows do platform_is_not :aix, :windows do

View File

@ -16,6 +16,15 @@ describe 'TracePoint#inspect' do
TracePoint.new(:line) {}.inspect.should == '#<TracePoint:disabled>' TracePoint.new(:line) {}.inspect.should == '#<TracePoint:disabled>'
end end
it "shows only whether it's enabled when outside the TracePoint handler" do
trace = TracePoint.new(:line) {}
trace.enable
trace.inspect.should == '#<TracePoint:enabled>'
trace.disable
end
it 'returns a String showing the event, path and line' do it 'returns a String showing the event, path and line' do
inspect = nil inspect = nil
line = nil line = nil

View File

@ -2,7 +2,10 @@ class LoadSpecWrap
ScratchPad << String ScratchPad << String
end end
LOAD_WRAP_SPECS_TOP_LEVEL_CONSTANT = 1
def load_wrap_specs_top_level_method def load_wrap_specs_top_level_method
:load_wrap_specs_top_level_method
end end
ScratchPad << method(:load_wrap_specs_top_level_method).owner ScratchPad << method(:load_wrap_specs_top_level_method).owner

Some files were not shown because too many files have changed in this diff Show More