Update to ruby/spec@f8987ac
This commit is contained in:
parent
d7af8afe1b
commit
cee62c6738
@ -277,13 +277,13 @@ describe :kernel_sprintf, shared: true do
|
||||
end
|
||||
|
||||
describe "Kernel#sprintf" do
|
||||
it_behaves_like :kernel_sprintf, -> (format, *args) {
|
||||
it_behaves_like :kernel_sprintf, -> format, *args {
|
||||
sprintf(format, *args)
|
||||
}
|
||||
end
|
||||
|
||||
describe "Kernel.sprintf" do
|
||||
it_behaves_like :kernel_sprintf, -> (format, *args) {
|
||||
it_behaves_like :kernel_sprintf, -> format, *args {
|
||||
Kernel.sprintf(format, *args)
|
||||
}
|
||||
end
|
||||
|
@ -35,7 +35,7 @@ More precisely, every latest stable MRI release should [pass](https://github.com
|
||||
|
||||
### Synchronization with Ruby Implementations
|
||||
|
||||
The specs are synchronized both ways around once a month by @eregon between ruby/spec, MRI, JRuby and TruffleRuby,
|
||||
The specs are synchronized both ways around once a month by @andrykonchin between ruby/spec, MRI, JRuby and TruffleRuby,
|
||||
using [this script](https://github.com/ruby/mspec/blob/master/tool/sync/sync-rubyspec.rb).
|
||||
Each of these repositories has a full copy of the specs under `spec/ruby` to ease editing specs.
|
||||
Any of these repositories can be used to add or edit specs, use what is most convenient for you.
|
||||
|
@ -7,7 +7,7 @@ require_relative '../enumerable/shared/enumeratorized'
|
||||
# Mutating the array while it is being iterated is discouraged as it can result in confusing behavior.
|
||||
# Yet a Ruby implementation must not crash in such a case, and following the simple CRuby behavior makes sense.
|
||||
# CRuby simply reads the array storage and checks the size for every iteration;
|
||||
# like `i = 0; while i < size; yield self[i]; end`
|
||||
# like `i = 0; while i < size; yield self[i]; i += 1; end`
|
||||
|
||||
describe "Array#each" do
|
||||
it "yields each element to the block" do
|
||||
|
@ -21,7 +21,7 @@ describe "Array#+" do
|
||||
([1, 2, 3] + obj).should == [1, 2, 3, "x", "y"]
|
||||
end
|
||||
|
||||
it "raises a Typeerror if the given argument can't be converted to an array" do
|
||||
it "raises a TypeError if the given argument can't be converted to an array" do
|
||||
-> { [1, 2, 3] + nil }.should raise_error(TypeError)
|
||||
-> { [1, 2, 3] + "abc" }.should raise_error(TypeError)
|
||||
end
|
||||
|
@ -45,6 +45,12 @@ describe "Array#to_h" do
|
||||
[:a, :b].to_h { |k| [k, k.to_s] }.should == { a: 'a', b: 'b' }
|
||||
end
|
||||
|
||||
it "passes to a block each element as a single argument" do
|
||||
ScratchPad.record []
|
||||
[[:a, 1], [:b, 2]].to_h { |*args| ScratchPad << args; [args[0], args[1]] }
|
||||
ScratchPad.recorded.sort.should == [[[:a, 1]], [[:b, 2]]]
|
||||
end
|
||||
|
||||
it "raises ArgumentError if block returns longer or shorter array" do
|
||||
-> do
|
||||
[:a, :b].to_h { |k| [k, k.to_s, 1] }
|
||||
|
@ -16,6 +16,23 @@ describe :enumerable_inject, shared: true do
|
||||
|
||||
it "can take two argument" do
|
||||
EnumerableSpecs::Numerous.new(1, 2, 3).send(@method, 10, :-).should == 4
|
||||
EnumerableSpecs::Numerous.new(1, 2, 3).send(@method, 10, "-").should == 4
|
||||
|
||||
[1, 2, 3].send(@method, 10, :-).should == 4
|
||||
[1, 2, 3].send(@method, 10, "-").should == 4
|
||||
end
|
||||
|
||||
it "converts non-Symbol method name argument to String with #to_str if two arguments" do
|
||||
name = Object.new
|
||||
def name.to_str; "-"; end
|
||||
|
||||
EnumerableSpecs::Numerous.new(1, 2, 3).send(@method, 10, name).should == 4
|
||||
[1, 2, 3].send(@method, 10, name).should == 4
|
||||
end
|
||||
|
||||
it "raises TypeError when the second argument is not Symbol or String and it cannot be converted to String if two arguments" do
|
||||
-> { EnumerableSpecs::Numerous.new(1, 2, 3).send(@method, 10, Object.new) }.should raise_error(TypeError, /is not a symbol nor a string/)
|
||||
-> { [1, 2, 3].send(@method, 10, Object.new) }.should raise_error(TypeError, /is not a symbol nor a string/)
|
||||
end
|
||||
|
||||
it "ignores the block if two arguments" do
|
||||
@ -39,6 +56,25 @@ describe :enumerable_inject, shared: true do
|
||||
|
||||
it "can take a symbol argument" do
|
||||
EnumerableSpecs::Numerous.new(10, 1, 2, 3).send(@method, :-).should == 4
|
||||
[10, 1, 2, 3].send(@method, :-).should == 4
|
||||
end
|
||||
|
||||
it "can take a String argument" do
|
||||
EnumerableSpecs::Numerous.new(10, 1, 2, 3).send(@method, "-").should == 4
|
||||
[10, 1, 2, 3].send(@method, "-").should == 4
|
||||
end
|
||||
|
||||
it "converts non-Symbol method name argument to String with #to_str" do
|
||||
name = Object.new
|
||||
def name.to_str; "-"; end
|
||||
|
||||
EnumerableSpecs::Numerous.new(10, 1, 2, 3).send(@method, name).should == 4
|
||||
[10, 1, 2, 3].send(@method, name).should == 4
|
||||
end
|
||||
|
||||
it "raises TypeError when passed not Symbol or String method name argument and it cannot be converted to String" do
|
||||
-> { EnumerableSpecs::Numerous.new(10, 1, 2, 3).send(@method, Object.new) }.should raise_error(TypeError, /is not a symbol nor a string/)
|
||||
-> { [10, 1, 2, 3].send(@method, Object.new) }.should raise_error(TypeError, /is not a symbol nor a string/)
|
||||
end
|
||||
|
||||
it "without argument takes a block with an accumulator (with first element as initial value) and the current element. Value of block becomes new accumulator" do
|
||||
@ -77,7 +113,6 @@ describe :enumerable_inject, shared: true do
|
||||
EnumerableSpecs::EachDefiner.new('a','b','c').send(@method) {|result, i| i+result}.should == "cba"
|
||||
EnumerableSpecs::EachDefiner.new(3, 4, 5).send(@method) {|result, i| result*i}.should == 60
|
||||
EnumerableSpecs::EachDefiner.new([1], 2, 'a','b').send(@method){|r,i| r<<i}.should == [1, 2, 'a', 'b']
|
||||
|
||||
end
|
||||
|
||||
it "returns nil when fails(legacy rubycon)" do
|
||||
|
@ -53,6 +53,14 @@ describe "Enumerable#to_h" do
|
||||
@enum.to_h { |k| [k, k.to_s] }.should == { a: 'a', b: 'b' }
|
||||
end
|
||||
|
||||
it "passes to a block each element as a single argument" do
|
||||
enum_of_arrays = EnumerableSpecs::EachDefiner.new([:a, 1], [:b, 2])
|
||||
|
||||
ScratchPad.record []
|
||||
enum_of_arrays.to_h { |*args| ScratchPad << args; [args[0], args[1]] }
|
||||
ScratchPad.recorded.sort.should == [[[:a, 1]], [[:b, 2]]]
|
||||
end
|
||||
|
||||
it "raises ArgumentError if block returns longer or shorter array" do
|
||||
-> do
|
||||
@enum.to_h { |k| [k, k.to_s, 1] }
|
||||
|
12
spec/ruby/core/env/to_h_spec.rb
vendored
12
spec/ruby/core/env/to_h_spec.rb
vendored
@ -18,6 +18,18 @@ describe "ENV.to_h" do
|
||||
ENV.to_h { |k, v| [k, v.upcase] }.should == { 'a' => "B", 'c' => "D" }
|
||||
end
|
||||
|
||||
it "passes to a block each pair's key and value as separate arguments" do
|
||||
ENV.replace("a" => "b", "c" => "d")
|
||||
|
||||
ScratchPad.record []
|
||||
ENV.to_h { |k, v| ScratchPad << [k, v]; [k, v] }
|
||||
ScratchPad.recorded.sort.should == [["a", "b"], ["c", "d"]]
|
||||
|
||||
ScratchPad.record []
|
||||
ENV.to_h { |*args| ScratchPad << args; [args[0], args[1]] }
|
||||
ScratchPad.recorded.sort.should == [["a", "b"], ["c", "d"]]
|
||||
end
|
||||
|
||||
it "does not require the array elements to be strings" do
|
||||
ENV.replace("a" => "b", "c" => "d")
|
||||
ENV.to_h { |k, v| [k.to_sym, v.to_sym] }.should == { :a => :b, :c => :d }
|
||||
|
@ -15,14 +15,6 @@ describe "Exception#detailed_message" do
|
||||
exception.full_message(highlight: false).should.include? "<prefix>new error<suffix>"
|
||||
end
|
||||
|
||||
it "accepts highlight keyword argument and adds escape control sequences" do
|
||||
RuntimeError.new("new error").detailed_message(highlight: true).should == "\e[1mnew error (\e[1;4mRuntimeError\e[m\e[1m)\e[m"
|
||||
end
|
||||
|
||||
it "allows and ignores other keyword arguments" do
|
||||
RuntimeError.new("new error").detailed_message(foo: true).should == "new error (RuntimeError)"
|
||||
end
|
||||
|
||||
it "returns just a message if exception class is anonymous" do
|
||||
Class.new(RuntimeError).new("message").detailed_message.should == "message"
|
||||
end
|
||||
@ -31,13 +23,30 @@ describe "Exception#detailed_message" do
|
||||
RuntimeError.new("").detailed_message.should == "unhandled exception"
|
||||
end
|
||||
|
||||
it "returns just class name for an instance of RuntimeError subclass with empty message" do
|
||||
it "returns just class name for an instance other than RuntimeError with empty message" do
|
||||
DetailedMessageSpec::C.new("").detailed_message.should == "DetailedMessageSpec::C"
|
||||
StandardError.new("").detailed_message.should == "StandardError"
|
||||
end
|
||||
|
||||
it "returns a generated class name for an instance of RuntimeError anonymous subclass with empty message" do
|
||||
klass = Class.new(RuntimeError)
|
||||
klass.new("").detailed_message.should =~ /\A#<Class:0x\h+>\z/
|
||||
end
|
||||
|
||||
it "accepts highlight keyword argument and adds escape control sequences" do
|
||||
RuntimeError.new("new error").detailed_message(highlight: true).should == "\e[1mnew error (\e[1;4mRuntimeError\e[m\e[1m)\e[m"
|
||||
end
|
||||
|
||||
it "accepts highlight keyword argument and adds escape control sequences for an instance of RuntimeError with empty message" do
|
||||
RuntimeError.new("").detailed_message(highlight: true).should == "\e[1;4munhandled exception\e[m"
|
||||
end
|
||||
|
||||
it "accepts highlight keyword argument and adds escape control sequences for an instance other than RuntimeError with empty message" do
|
||||
StandardError.new("").detailed_message(highlight: true).should == "\e[1;4mStandardError\e[m"
|
||||
end
|
||||
|
||||
it "allows and ignores other keyword arguments" do
|
||||
RuntimeError.new("new error").detailed_message(foo: true).should == "new error (RuntimeError)"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,7 +1,70 @@
|
||||
require_relative '../../spec_helper'
|
||||
require_relative 'fixtures/classes'
|
||||
require_relative 'shared/replace'
|
||||
|
||||
describe "Hash#replace" do
|
||||
it_behaves_like :hash_replace, :replace
|
||||
it "replaces the contents of self with other" do
|
||||
h = { a: 1, b: 2 }
|
||||
h.replace(c: -1, d: -2).should equal(h)
|
||||
h.should == { c: -1, d: -2 }
|
||||
end
|
||||
|
||||
it "tries to convert the passed argument to a hash using #to_hash" do
|
||||
obj = mock('{1=>2,3=>4}')
|
||||
obj.should_receive(:to_hash).and_return({ 1 => 2, 3 => 4 })
|
||||
|
||||
h = {}
|
||||
h.replace(obj)
|
||||
h.should == { 1 => 2, 3 => 4 }
|
||||
end
|
||||
|
||||
it "calls to_hash on hash subclasses" do
|
||||
h = {}
|
||||
h.replace(HashSpecs::ToHashHash[1 => 2])
|
||||
h.should == { 1 => 2 }
|
||||
end
|
||||
|
||||
it "transfers the compare_by_identity flag" do
|
||||
hash_a = { a: 1 }
|
||||
hash_b = { b: 2 }
|
||||
hash_b.compare_by_identity
|
||||
hash_a.should_not.compare_by_identity?
|
||||
hash_a.replace(hash_b)
|
||||
hash_a.should.compare_by_identity?
|
||||
|
||||
hash_a = { a: 1 }
|
||||
hash_b = { b: 2 }
|
||||
hash_a.compare_by_identity
|
||||
hash_a.should.compare_by_identity?
|
||||
hash_a.replace(hash_b)
|
||||
hash_a.should_not.compare_by_identity?
|
||||
end
|
||||
|
||||
it "does not transfer default values" do
|
||||
hash_a = {}
|
||||
hash_b = Hash.new(5)
|
||||
hash_a.replace(hash_b)
|
||||
hash_a.default.should == 5
|
||||
|
||||
hash_a = {}
|
||||
hash_b = Hash.new { |h, k| k * 2 }
|
||||
hash_a.replace(hash_b)
|
||||
hash_a.default(5).should == 10
|
||||
|
||||
hash_a = Hash.new { |h, k| k * 5 }
|
||||
hash_b = Hash.new(-> { raise "Should not invoke lambda" })
|
||||
hash_a.replace(hash_b)
|
||||
hash_a.default.should == hash_b.default
|
||||
end
|
||||
|
||||
it "raises a FrozenError if called on a frozen instance that would not be modified" do
|
||||
-> do
|
||||
HashSpecs.frozen_hash.replace(HashSpecs.frozen_hash)
|
||||
end.should raise_error(FrozenError)
|
||||
end
|
||||
|
||||
it "raises a FrozenError if called on a frozen instance that is modified" do
|
||||
-> do
|
||||
HashSpecs.frozen_hash.replace(HashSpecs.empty_frozen_hash)
|
||||
end.should raise_error(FrozenError)
|
||||
end
|
||||
end
|
||||
|
@ -1,51 +0,0 @@
|
||||
describe :hash_replace, shared: true do
|
||||
it "replaces the contents of self with other" do
|
||||
h = { a: 1, b: 2 }
|
||||
h.send(@method, c: -1, d: -2).should equal(h)
|
||||
h.should == { c: -1, d: -2 }
|
||||
end
|
||||
|
||||
it "tries to convert the passed argument to a hash using #to_hash" do
|
||||
obj = mock('{1=>2,3=>4}')
|
||||
obj.should_receive(:to_hash).and_return({ 1 => 2, 3 => 4 })
|
||||
|
||||
h = {}
|
||||
h.send(@method, obj)
|
||||
h.should == { 1 => 2, 3 => 4 }
|
||||
end
|
||||
|
||||
it "calls to_hash on hash subclasses" do
|
||||
h = {}
|
||||
h.send(@method, HashSpecs::ToHashHash[1 => 2])
|
||||
h.should == { 1 => 2 }
|
||||
end
|
||||
|
||||
it "does not transfer default values" do
|
||||
hash_a = {}
|
||||
hash_b = Hash.new(5)
|
||||
hash_a.send(@method, hash_b)
|
||||
hash_a.default.should == 5
|
||||
|
||||
hash_a = {}
|
||||
hash_b = Hash.new { |h, k| k * 2 }
|
||||
hash_a.send(@method, hash_b)
|
||||
hash_a.default(5).should == 10
|
||||
|
||||
hash_a = Hash.new { |h, k| k * 5 }
|
||||
hash_b = Hash.new(-> { raise "Should not invoke lambda" })
|
||||
hash_a.send(@method, hash_b)
|
||||
hash_a.default.should == hash_b.default
|
||||
end
|
||||
|
||||
it "raises a FrozenError if called on a frozen instance that would not be modified" do
|
||||
-> do
|
||||
HashSpecs.frozen_hash.send(@method, HashSpecs.frozen_hash)
|
||||
end.should raise_error(FrozenError)
|
||||
end
|
||||
|
||||
it "raises a FrozenError if called on a frozen instance that is modified" do
|
||||
-> do
|
||||
HashSpecs.frozen_hash.send(@method, HashSpecs.empty_frozen_hash)
|
||||
end.should raise_error(FrozenError)
|
||||
end
|
||||
end
|
@ -37,6 +37,16 @@ describe "Hash#to_h" do
|
||||
{ a: 1, b: 2 }.to_h { |k, v| [k.to_s, v*v]}.should == { "a" => 1, "b" => 4 }
|
||||
end
|
||||
|
||||
it "passes to a block each pair's key and value as separate arguments" do
|
||||
ScratchPad.record []
|
||||
{ a: 1, b: 2 }.to_h { |k, v| ScratchPad << [k, v]; [k, v] }
|
||||
ScratchPad.recorded.sort.should == [[:a, 1], [:b, 2]]
|
||||
|
||||
ScratchPad.record []
|
||||
{ a: 1, b: 2 }.to_h { |*args| ScratchPad << args; [args[0], args[1]] }
|
||||
ScratchPad.recorded.sort.should == [[:a, 1], [:b, 2]]
|
||||
end
|
||||
|
||||
it "raises ArgumentError if block returns longer or shorter array" do
|
||||
-> do
|
||||
{ a: 1, b: 2 }.to_h { |k, v| [k.to_s, v*v, 1] }
|
||||
|
@ -10,12 +10,12 @@ describe "Integer#chr without argument" do
|
||||
end
|
||||
|
||||
it "raises a RangeError is self is less than 0" do
|
||||
-> { -1.chr }.should raise_error(RangeError)
|
||||
-> { (-bignum_value).chr }.should raise_error(RangeError)
|
||||
-> { -1.chr }.should raise_error(RangeError, /-1 out of char range/)
|
||||
-> { (-bignum_value).chr }.should raise_error(RangeError, /bignum out of char range/)
|
||||
end
|
||||
|
||||
it "raises a RangeError if self is too large" do
|
||||
-> { 2206368128.chr(Encoding::UTF_8) }.should raise_error(RangeError)
|
||||
-> { 2206368128.chr(Encoding::UTF_8) }.should raise_error(RangeError, /2206368128 out of char range/)
|
||||
end
|
||||
|
||||
describe "when Encoding.default_internal is nil" do
|
||||
@ -48,8 +48,8 @@ describe "Integer#chr without argument" do
|
||||
end
|
||||
|
||||
it "raises a RangeError is self is greater than 255" do
|
||||
-> { 256.chr }.should raise_error(RangeError)
|
||||
-> { bignum_value.chr }.should raise_error(RangeError)
|
||||
-> { 256.chr }.should raise_error(RangeError, /256 out of char range/)
|
||||
-> { bignum_value.chr }.should raise_error(RangeError, /bignum out of char range/)
|
||||
end
|
||||
end
|
||||
|
||||
@ -137,7 +137,7 @@ describe "Integer#chr without argument" do
|
||||
[620, "TIS-620"]
|
||||
].each do |integer, encoding_name|
|
||||
Encoding.default_internal = Encoding.find(encoding_name)
|
||||
-> { integer.chr }.should raise_error(RangeError)
|
||||
-> { integer.chr }.should raise_error(RangeError, /(invalid codepoint|out of char range)/)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -165,12 +165,12 @@ describe "Integer#chr with an encoding argument" do
|
||||
|
||||
# http://redmine.ruby-lang.org/issues/4869
|
||||
it "raises a RangeError is self is less than 0" do
|
||||
-> { -1.chr(Encoding::UTF_8) }.should raise_error(RangeError)
|
||||
-> { (-bignum_value).chr(Encoding::EUC_JP) }.should raise_error(RangeError)
|
||||
-> { -1.chr(Encoding::UTF_8) }.should raise_error(RangeError, /-1 out of char range/)
|
||||
-> { (-bignum_value).chr(Encoding::EUC_JP) }.should raise_error(RangeError, /bignum out of char range/)
|
||||
end
|
||||
|
||||
it "raises a RangeError if self is too large" do
|
||||
-> { 2206368128.chr(Encoding::UTF_8) }.should raise_error(RangeError)
|
||||
-> { 2206368128.chr(Encoding::UTF_8) }.should raise_error(RangeError, /2206368128 out of char range/)
|
||||
end
|
||||
|
||||
it "returns a String with the specified encoding" do
|
||||
|
77
spec/ruby/core/io/autoclose_spec.rb
Normal file
77
spec/ruby/core/io/autoclose_spec.rb
Normal file
@ -0,0 +1,77 @@
|
||||
require_relative '../../spec_helper'
|
||||
require_relative 'fixtures/classes'
|
||||
|
||||
describe "IO#autoclose?" do
|
||||
before :each do
|
||||
@io = IOSpecs.io_fixture "lines.txt"
|
||||
end
|
||||
|
||||
after :each do
|
||||
@io.autoclose = true unless @io.closed?
|
||||
@io.close unless @io.closed?
|
||||
end
|
||||
|
||||
it "is set to true by default" do
|
||||
@io.should.autoclose?
|
||||
end
|
||||
|
||||
it "cannot be queried on a closed IO object" do
|
||||
@io.close
|
||||
-> { @io.autoclose? }.should raise_error(IOError, /closed stream/)
|
||||
end
|
||||
end
|
||||
|
||||
describe "IO#autoclose=" do
|
||||
before :each do
|
||||
@io = IOSpecs.io_fixture "lines.txt"
|
||||
end
|
||||
|
||||
after :each do
|
||||
@io.autoclose = true unless @io.closed?
|
||||
@io.close unless @io.closed?
|
||||
end
|
||||
|
||||
it "can be set to true" do
|
||||
@io.autoclose = false
|
||||
@io.autoclose = true
|
||||
@io.should.autoclose?
|
||||
end
|
||||
|
||||
it "can be set to false" do
|
||||
@io.autoclose = true
|
||||
@io.autoclose = false
|
||||
@io.should_not.autoclose?
|
||||
end
|
||||
|
||||
it "can be set to any truthy value" do
|
||||
@io.autoclose = false
|
||||
@io.autoclose = 42
|
||||
@io.should.autoclose?
|
||||
|
||||
@io.autoclose = false
|
||||
@io.autoclose = Object.new
|
||||
@io.should.autoclose?
|
||||
end
|
||||
|
||||
it "can be set to any falsy value" do
|
||||
@io.autoclose = true
|
||||
@io.autoclose = nil
|
||||
@io.should_not.autoclose?
|
||||
end
|
||||
|
||||
it "can be set multiple times" do
|
||||
@io.autoclose = true
|
||||
@io.should.autoclose?
|
||||
|
||||
@io.autoclose = false
|
||||
@io.should_not.autoclose?
|
||||
|
||||
@io.autoclose = true
|
||||
@io.should.autoclose?
|
||||
end
|
||||
|
||||
it "cannot be set on a closed IO object" do
|
||||
@io.close
|
||||
-> { @io.autoclose = false }.should raise_error(IOError, /closed stream/)
|
||||
end
|
||||
end
|
@ -43,16 +43,44 @@ describe 'Kernel#caller' do
|
||||
lines[1].should =~ /\A#{path}:2:in [`']block in <main>'\n\z/
|
||||
end
|
||||
|
||||
it "can be called with a range" do
|
||||
locations1 = caller(0)
|
||||
locations2 = caller(2..4)
|
||||
locations1[2..4].should == locations2
|
||||
end
|
||||
|
||||
it "works with endless ranges" do
|
||||
locations1 = KernelSpecs::CallerTest.locations(0)
|
||||
locations2 = KernelSpecs::CallerTest.locations(eval("(2..)"))
|
||||
locations2.map(&:to_s).should == locations1[2..-1].map(&:to_s)
|
||||
locations2.should == locations1[2..-1]
|
||||
end
|
||||
|
||||
it "works with beginless ranges" do
|
||||
locations1 = KernelSpecs::CallerTest.locations(0)
|
||||
locations2 = KernelSpecs::CallerTest.locations((..5))
|
||||
locations2.map(&:to_s)[eval("(2..)")].should == locations1[(..5)].map(&:to_s)[eval("(2..)")]
|
||||
locations2[eval("(2..)")].should == locations1[(..5)][eval("(2..)")]
|
||||
end
|
||||
|
||||
it "can be called with a range whose end is negative" do
|
||||
locations1 = caller(0)
|
||||
locations2 = caller(2..-1)
|
||||
locations3 = caller(2..-2)
|
||||
locations1[2..-1].should == locations2
|
||||
locations1[2..-2].should == locations3
|
||||
end
|
||||
|
||||
it "must return nil if omitting more locations than available" do
|
||||
caller(100).should == nil
|
||||
caller(100..-1).should == nil
|
||||
end
|
||||
|
||||
it "must return [] if omitting exactly the number of locations available" do
|
||||
omit = caller(0).length
|
||||
caller(omit).should == []
|
||||
end
|
||||
|
||||
it "must return the same locations when called with 1..-1 and when called with no arguments" do
|
||||
caller.should == caller(1..-1)
|
||||
end
|
||||
|
||||
guard -> { Kernel.instance_method(:tap).source_location } do
|
||||
|
@ -21,7 +21,7 @@ describe "Kernel#sleep" do
|
||||
sleep(Rational(1, 999)).should >= 0
|
||||
end
|
||||
|
||||
it "accepts any Object that reponds to divmod" do
|
||||
it "accepts any Object that responds to divmod" do
|
||||
o = Object.new
|
||||
def o.divmod(*); [0, 0.001]; end
|
||||
sleep(o).should >= 0
|
||||
|
@ -20,6 +20,11 @@ describe "MatchData#[]" do
|
||||
# negative index is larger than the number of match values
|
||||
/(.)(.)(\d+)(\d)/.match("THX1138.")[-30, 2].should == nil
|
||||
|
||||
# positive index larger than number of match values
|
||||
/(.)(.)(\d+)(\d)/.match("THX1138.")[5, 2].should == []
|
||||
/(.)(.)(\d+)(\d)/.match("THX1138.")[6, 2].should == nil
|
||||
/(.)(.)(\d+)(\d)/.match("THX1138.")[30, 2].should == nil
|
||||
|
||||
# length argument larger than number of match values is capped to match value length
|
||||
/(.)(.)(\d+)(\d)/.match("THX1138.")[3, 10].should == %w|113 8|
|
||||
|
||||
|
@ -56,7 +56,7 @@ describe :regexp_new_string, shared: true do
|
||||
end
|
||||
|
||||
it "raises a RegexpError when passed an incorrect regexp" do
|
||||
-> { Regexp.send(@method, "^[$", 0) }.should raise_error(RegexpError)
|
||||
-> { Regexp.send(@method, "^[$", 0) }.should raise_error(RegexpError, Regexp.new(Regexp.escape("premature end of char-class: /^[$/")))
|
||||
end
|
||||
|
||||
it "does not set Regexp options if only given one argument" do
|
||||
@ -261,7 +261,7 @@ describe :regexp_new_string, shared: true do
|
||||
|
||||
describe "with escaped characters" do
|
||||
it "raises a Regexp error if there is a trailing backslash" do
|
||||
-> { Regexp.send(@method, "\\") }.should raise_error(RegexpError)
|
||||
-> { Regexp.send(@method, "\\") }.should raise_error(RegexpError, Regexp.new(Regexp.escape("too short escape sequence: /\\/")))
|
||||
end
|
||||
|
||||
it "does not raise a Regexp error if there is an escaped trailing backslash" do
|
||||
@ -293,7 +293,7 @@ describe :regexp_new_string, shared: true do
|
||||
end
|
||||
|
||||
it "raises a RegexpError if \\x is not followed by any hexadecimal digits" do
|
||||
-> { Regexp.send(@method, "\\" + "xn") }.should raise_error(RegexpError)
|
||||
-> { Regexp.send(@method, "\\" + "xn") }.should raise_error(RegexpError, Regexp.new(Regexp.escape("invalid hex escape: /\\xn/")))
|
||||
end
|
||||
|
||||
it "accepts an escaped string interpolation" do
|
||||
@ -453,15 +453,15 @@ describe :regexp_new_string, shared: true do
|
||||
end
|
||||
|
||||
it "raises a RegexpError if less than four digits are given for \\uHHHH" do
|
||||
-> { Regexp.send(@method, "\\" + "u304") }.should raise_error(RegexpError)
|
||||
-> { Regexp.send(@method, "\\" + "u304") }.should raise_error(RegexpError, Regexp.new(Regexp.escape("invalid Unicode escape: /\\u304/")))
|
||||
end
|
||||
|
||||
it "raises a RegexpError if the \\u{} escape is empty" do
|
||||
-> { Regexp.send(@method, "\\" + "u{}") }.should raise_error(RegexpError)
|
||||
-> { Regexp.send(@method, "\\" + "u{}") }.should raise_error(RegexpError, Regexp.new(Regexp.escape("invalid Unicode list: /\\u{}/")))
|
||||
end
|
||||
|
||||
it "raises a RegexpError if more than six hexadecimal digits are given" do
|
||||
-> { Regexp.send(@method, "\\" + "u{0ffffff}") }.should raise_error(RegexpError)
|
||||
-> { Regexp.send(@method, "\\" + "u{0ffffff}") }.should raise_error(RegexpError, Regexp.new(Regexp.escape("invalid Unicode range: /\\u{0ffffff}/")))
|
||||
end
|
||||
|
||||
it "returns a Regexp with US-ASCII encoding if only 7-bit ASCII characters are present regardless of the input String's encoding" do
|
||||
|
@ -61,10 +61,22 @@ describe "String#encode" do
|
||||
str.encode(invalid: :replace).should_not equal(str)
|
||||
end
|
||||
|
||||
it "normalizes newlines" do
|
||||
"\r\nfoo".encode(universal_newline: true).should == "\nfoo"
|
||||
it "normalizes newlines with cr_newline option" do
|
||||
"\r\nfoo".encode(cr_newline: true).should == "\r\rfoo"
|
||||
"\rfoo".encode(cr_newline: true).should == "\rfoo"
|
||||
"\nfoo".encode(cr_newline: true).should == "\rfoo"
|
||||
end
|
||||
|
||||
it "normalizes newlines with crlf_newline option" do
|
||||
"\r\nfoo".encode(crlf_newline: true).should == "\r\r\nfoo"
|
||||
"\rfoo".encode(crlf_newline: true).should == "\rfoo"
|
||||
"\nfoo".encode(crlf_newline: true).should == "\r\nfoo"
|
||||
end
|
||||
|
||||
it "normalizes newlines with universal_newline option" do
|
||||
"\r\nfoo".encode(universal_newline: true).should == "\nfoo"
|
||||
"\rfoo".encode(universal_newline: true).should == "\nfoo"
|
||||
"\nfoo".encode(universal_newline: true).should == "\nfoo"
|
||||
end
|
||||
|
||||
it "replaces invalid encoding in source with default replacement" do
|
||||
|
@ -194,6 +194,190 @@ describe :string_encode, shared: true do
|
||||
end
|
||||
end
|
||||
|
||||
describe "given the fallback option" do
|
||||
context "given a hash" do
|
||||
it "looks up the replacement value from the hash" do
|
||||
encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: { "\ufffd" => "bar" })
|
||||
encoded.should == "Bbar"
|
||||
end
|
||||
|
||||
it "calls to_str on the returned value" do
|
||||
obj = Object.new
|
||||
obj.should_receive(:to_str).and_return("bar")
|
||||
encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: { "\ufffd" => obj })
|
||||
encoded.should == "Bbar"
|
||||
end
|
||||
|
||||
it "does not call to_s on the returned value" do
|
||||
obj = Object.new
|
||||
obj.should_not_receive(:to_s)
|
||||
-> {
|
||||
"B\ufffd".encode(Encoding::US_ASCII, fallback: { "\ufffd" => obj })
|
||||
}.should raise_error(TypeError, "no implicit conversion of Object into String")
|
||||
end
|
||||
|
||||
it "raises an error if the key is not present in the hash" do
|
||||
-> {
|
||||
"B\ufffd".encode(Encoding::US_ASCII, fallback: { "foo" => "bar" })
|
||||
}.should raise_error(Encoding::UndefinedConversionError, "U+FFFD from UTF-8 to US-ASCII")
|
||||
end
|
||||
|
||||
it "raises an error if the value is itself invalid" do
|
||||
-> {
|
||||
"B\ufffd".encode(Encoding::US_ASCII, fallback: { "\ufffd" => "\uffee" })
|
||||
}.should raise_error(ArgumentError, "too big fallback string")
|
||||
end
|
||||
|
||||
it "uses the hash's default value if set" do
|
||||
hash = {}
|
||||
hash.default = "bar"
|
||||
encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: hash)
|
||||
encoded.should == "Bbar"
|
||||
end
|
||||
|
||||
it "uses the result of calling default_proc if set" do
|
||||
hash = {}
|
||||
hash.default_proc = -> _, _ { "bar" }
|
||||
encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: hash)
|
||||
encoded.should == "Bbar"
|
||||
end
|
||||
end
|
||||
|
||||
context "given an object inheriting from Hash" do
|
||||
before do
|
||||
klass = Class.new(Hash)
|
||||
@hash_like = klass.new
|
||||
@hash_like["\ufffd"] = "bar"
|
||||
end
|
||||
|
||||
it "looks up the replacement value from the object" do
|
||||
encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: @hash_like)
|
||||
encoded.should == "Bbar"
|
||||
end
|
||||
end
|
||||
|
||||
context "given an object responding to []" do
|
||||
before do
|
||||
klass = Class.new do
|
||||
def [](c) = c.bytes.inspect
|
||||
end
|
||||
@hash_like = klass.new
|
||||
end
|
||||
|
||||
it "calls [] on the object, passing the invalid character" do
|
||||
encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: @hash_like)
|
||||
encoded.should == "B[239, 191, 189]"
|
||||
end
|
||||
end
|
||||
|
||||
context "given an object not responding to []" do
|
||||
before do
|
||||
@non_hash_like = Object.new
|
||||
end
|
||||
|
||||
it "raises an error" do
|
||||
-> {
|
||||
"B\ufffd".encode(Encoding::US_ASCII, fallback: @non_hash_like)
|
||||
}.should raise_error(Encoding::UndefinedConversionError, "U+FFFD from UTF-8 to US-ASCII")
|
||||
end
|
||||
end
|
||||
|
||||
context "given a proc" do
|
||||
it "calls the proc to get the replacement value, passing in the invalid character" do
|
||||
encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: proc { |c| c.bytes.inspect })
|
||||
encoded.should == "B[239, 191, 189]"
|
||||
end
|
||||
|
||||
it "calls to_str on the returned value" do
|
||||
obj = Object.new
|
||||
obj.should_receive(:to_str).and_return("bar")
|
||||
encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: proc { |c| obj })
|
||||
encoded.should == "Bbar"
|
||||
end
|
||||
|
||||
it "does not call to_s on the returned value" do
|
||||
obj = Object.new
|
||||
obj.should_not_receive(:to_s)
|
||||
-> {
|
||||
"B\ufffd".encode(Encoding::US_ASCII, fallback: proc { |c| obj })
|
||||
}.should raise_error(TypeError, "no implicit conversion of Object into String")
|
||||
end
|
||||
|
||||
it "raises an error if the returned value is itself invalid" do
|
||||
-> {
|
||||
"B\ufffd".encode(Encoding::US_ASCII, fallback: -> c { "\uffee" })
|
||||
}.should raise_error(ArgumentError, "too big fallback string")
|
||||
end
|
||||
end
|
||||
|
||||
context "given a lambda" do
|
||||
it "calls the lambda to get the replacement value, passing in the invalid character" do
|
||||
encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: -> c { c.bytes.inspect })
|
||||
encoded.should == "B[239, 191, 189]"
|
||||
end
|
||||
|
||||
it "calls to_str on the returned value" do
|
||||
obj = Object.new
|
||||
obj.should_receive(:to_str).and_return("bar")
|
||||
encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: -> c { obj })
|
||||
encoded.should == "Bbar"
|
||||
end
|
||||
|
||||
it "does not call to_s on the returned value" do
|
||||
obj = Object.new
|
||||
obj.should_not_receive(:to_s)
|
||||
-> {
|
||||
"B\ufffd".encode(Encoding::US_ASCII, fallback: -> c { obj })
|
||||
}.should raise_error(TypeError, "no implicit conversion of Object into String")
|
||||
end
|
||||
|
||||
it "raises an error if the returned value is itself invalid" do
|
||||
-> {
|
||||
"B\ufffd".encode(Encoding::US_ASCII, fallback: -> c { "\uffee" })
|
||||
}.should raise_error(ArgumentError, "too big fallback string")
|
||||
end
|
||||
end
|
||||
|
||||
context "given a method" do
|
||||
def replace(c) = c.bytes.inspect
|
||||
def replace_bad(c) = "\uffee"
|
||||
|
||||
def replace_to_str(c)
|
||||
obj = Object.new
|
||||
obj.should_receive(:to_str).and_return("bar")
|
||||
obj
|
||||
end
|
||||
|
||||
def replace_to_s(c)
|
||||
obj = Object.new
|
||||
obj.should_not_receive(:to_s)
|
||||
obj
|
||||
end
|
||||
|
||||
it "calls the method to get the replacement value, passing in the invalid character" do
|
||||
encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: method(:replace))
|
||||
encoded.should == "B[239, 191, 189]"
|
||||
end
|
||||
|
||||
it "calls to_str on the returned value" do
|
||||
encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: method(:replace_to_str))
|
||||
encoded.should == "Bbar"
|
||||
end
|
||||
|
||||
it "does not call to_s on the returned value" do
|
||||
-> {
|
||||
"B\ufffd".encode(Encoding::US_ASCII, fallback: method(:replace_to_s))
|
||||
}.should raise_error(TypeError, "no implicit conversion of Object into String")
|
||||
end
|
||||
|
||||
it "raises an error if the returned value is itself invalid" do
|
||||
-> {
|
||||
"B\ufffd".encode(Encoding::US_ASCII, fallback: method(:replace_bad))
|
||||
}.should raise_error(ArgumentError, "too big fallback string")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "given the xml: :text option" do
|
||||
it "replaces all instances of '&' with '&'" do
|
||||
'& and &'.send(@method, "UTF-8", xml: :text).should == '& and &'
|
||||
|
@ -21,6 +21,18 @@ describe "Struct#to_h" do
|
||||
h.should == { "make" => "ford", "model" => "ranger", "year" => "" }
|
||||
end
|
||||
|
||||
it "passes to a block each pair's key and value as separate arguments" do
|
||||
s = StructClasses::Ruby.new('3.2.4', 'macos')
|
||||
|
||||
ScratchPad.record []
|
||||
s.to_h { |k, v| ScratchPad << [k, v]; [k, v] }
|
||||
ScratchPad.recorded.sort.should == [[:platform, 'macos'], [:version, '3.2.4']]
|
||||
|
||||
ScratchPad.record []
|
||||
s.to_h { |*args| ScratchPad << args; [args[0], args[1]] }
|
||||
ScratchPad.recorded.sort.should == [[:platform, 'macos'], [:version, '3.2.4']]
|
||||
end
|
||||
|
||||
it "raises ArgumentError if block returns longer or shorter array" do
|
||||
-> do
|
||||
StructClasses::Car.new.to_h { |k, v| [k.to_s, "#{v}".downcase, 1] }
|
||||
|
@ -14,12 +14,40 @@ describe "Thread#thread_variable_get" do
|
||||
end
|
||||
|
||||
it "returns the value previously set by #thread_variable_set" do
|
||||
@t.thread_variable_set :a, 49
|
||||
@t.thread_variable_set(:a, 49)
|
||||
@t.thread_variable_get(:a).should == 49
|
||||
end
|
||||
|
||||
it "returns a value private to self" do
|
||||
@t.thread_variable_set :thread_variable_get_spec, 82
|
||||
@t.thread_variable_set(:thread_variable_get_spec, 82)
|
||||
Thread.current.thread_variable_get(:thread_variable_get_spec).should be_nil
|
||||
end
|
||||
|
||||
it "accepts String and Symbol keys interchangeably" do
|
||||
@t.thread_variable_set("a", 49)
|
||||
@t.thread_variable_get("a").should == 49
|
||||
@t.thread_variable_get(:a).should == 49
|
||||
end
|
||||
|
||||
it "converts a key that is neither String nor Symbol with #to_str" do
|
||||
key = mock('key')
|
||||
key.should_receive(:to_str).and_return('a')
|
||||
@t.thread_variable_set(:a, 49)
|
||||
@t.thread_variable_get(key).should == 49
|
||||
end
|
||||
|
||||
it "does not raise FrozenError if the thread is frozen" do
|
||||
@t.freeze
|
||||
@t.thread_variable_get(:a).should be_nil
|
||||
end
|
||||
|
||||
it "does not raise a TypeError if the key is neither Symbol nor String, nor responds to #to_str" do
|
||||
@t.thread_variable_get(123).should be_nil
|
||||
end
|
||||
|
||||
it "does not try to convert the key with #to_sym" do
|
||||
key = mock('key')
|
||||
key.should_not_receive(:to_sym)
|
||||
@t.thread_variable_get(key).should be_nil
|
||||
end
|
||||
end
|
||||
|
@ -10,17 +10,53 @@ describe "Thread#thread_variable_set" do
|
||||
end
|
||||
|
||||
it "returns the value set" do
|
||||
(@t.thread_variable_set :a, 2).should == 2
|
||||
@t.thread_variable_set(:a, 2).should == 2
|
||||
end
|
||||
|
||||
it "sets a value that will be returned by #thread_variable_get" do
|
||||
@t.thread_variable_set :a, 49
|
||||
@t.thread_variable_set(:a, 49)
|
||||
@t.thread_variable_get(:a).should == 49
|
||||
end
|
||||
|
||||
it "sets a value private to self" do
|
||||
@t.thread_variable_set :thread_variable_get_spec, 82
|
||||
@t.thread_variable_set(:thread_variable_get_spec, 82)
|
||||
@t.thread_variable_get(:thread_variable_get_spec).should == 82
|
||||
Thread.current.thread_variable_get(:thread_variable_get_spec).should be_nil
|
||||
end
|
||||
|
||||
it "accepts String and Symbol keys interchangeably" do
|
||||
@t.thread_variable_set('a', 49)
|
||||
@t.thread_variable_get('a').should == 49
|
||||
|
||||
@t.thread_variable_set(:a, 50)
|
||||
@t.thread_variable_get('a').should == 50
|
||||
end
|
||||
|
||||
it "converts a key that is neither String nor Symbol with #to_str" do
|
||||
key = mock('key')
|
||||
key.should_receive(:to_str).and_return('a')
|
||||
@t.thread_variable_set(key, 49)
|
||||
@t.thread_variable_get(:a).should == 49
|
||||
end
|
||||
|
||||
it "removes a key if the value is nil" do
|
||||
@t.thread_variable_set(:a, 52)
|
||||
@t.thread_variable_set(:a, nil)
|
||||
@t.thread_variable?(:a).should be_false
|
||||
end
|
||||
|
||||
it "raises a FrozenError if the thread is frozen" do
|
||||
@t.freeze
|
||||
-> { @t.thread_variable_set(:a, 1) }.should raise_error(FrozenError, "can't modify frozen thread locals")
|
||||
end
|
||||
|
||||
it "raises a TypeError if the key is neither Symbol nor String, nor responds to #to_str" do
|
||||
-> { @t.thread_variable_set(123, 1) }.should raise_error(TypeError, '123 is not a symbol')
|
||||
end
|
||||
|
||||
it "does not try to convert the key with #to_sym" do
|
||||
key = mock('key')
|
||||
key.should_not_receive(:to_sym)
|
||||
-> { @t.thread_variable_set(key, 42) }.should raise_error(TypeError, "#{key.inspect} is not a symbol")
|
||||
end
|
||||
end
|
||||
|
@ -10,12 +10,44 @@ describe "Thread#thread_variable?" do
|
||||
end
|
||||
|
||||
it "returns false if the thread variables do not contain 'key'" do
|
||||
@t.thread_variable_set :a, 2
|
||||
@t.thread_variable_set(:a, 2)
|
||||
@t.thread_variable?(:b).should be_false
|
||||
end
|
||||
|
||||
it "returns true if the thread variables contain 'key'" do
|
||||
@t.thread_variable_set :a, 2
|
||||
@t.thread_variable_set(:a, 2)
|
||||
@t.thread_variable?(:a).should be_true
|
||||
end
|
||||
|
||||
it "accepts String and Symbol keys interchangeably" do
|
||||
@t.thread_variable?('a').should be_false
|
||||
@t.thread_variable?(:a).should be_false
|
||||
|
||||
@t.thread_variable_set(:a, 49)
|
||||
|
||||
@t.thread_variable?('a').should be_true
|
||||
@t.thread_variable?(:a).should be_true
|
||||
end
|
||||
|
||||
it "converts a key that is neither String nor Symbol with #to_str" do
|
||||
key = mock('key')
|
||||
key.should_receive(:to_str).and_return('a')
|
||||
@t.thread_variable_set(:a, 49)
|
||||
@t.thread_variable?(key).should be_true
|
||||
end
|
||||
|
||||
it "does not raise FrozenError if the thread is frozen" do
|
||||
@t.freeze
|
||||
@t.thread_variable?(:a).should be_false
|
||||
end
|
||||
|
||||
it "does not raise a TypeError if the key is neither Symbol nor String, nor responds to #to_str" do
|
||||
@t.thread_variable?(123).should be_false
|
||||
end
|
||||
|
||||
it "does not try to convert the key with #to_sym" do
|
||||
key = mock('key')
|
||||
key.should_not_receive(:to_sym)
|
||||
@t.thread_variable?(key).should be_false
|
||||
end
|
||||
end
|
||||
|
@ -10,15 +10,15 @@ describe "Thread#thread_variables" do
|
||||
end
|
||||
|
||||
it "returns the keys of all the values set" do
|
||||
@t.thread_variable_set :a, 2
|
||||
@t.thread_variable_set :b, 4
|
||||
@t.thread_variable_set :c, 6
|
||||
@t.thread_variable_set(:a, 2)
|
||||
@t.thread_variable_set(:b, 4)
|
||||
@t.thread_variable_set(:c, 6)
|
||||
@t.thread_variables.sort.should == [:a, :b, :c]
|
||||
end
|
||||
|
||||
it "sets a value private to self" do
|
||||
@t.thread_variable_set :a, 82
|
||||
@t.thread_variable_set :b, 82
|
||||
it "returns the keys private to self" do
|
||||
@t.thread_variable_set(:a, 82)
|
||||
@t.thread_variable_set(:b, 82)
|
||||
Thread.current.thread_variables.should_not include(:a, :b)
|
||||
end
|
||||
|
||||
@ -26,4 +26,14 @@ describe "Thread#thread_variables" do
|
||||
Thread.current.thread_variables.should == []
|
||||
@t.thread_variables.should == []
|
||||
end
|
||||
|
||||
it "returns keys as Symbols" do
|
||||
key = mock('key')
|
||||
key.should_receive(:to_str).and_return('a')
|
||||
|
||||
@t.thread_variable_set(key, 49)
|
||||
@t.thread_variable_set('b', 50)
|
||||
@t.thread_variable_set(:c, 51)
|
||||
@t.thread_variables.sort.should == [:a, :b, :c]
|
||||
end
|
||||
end
|
||||
|
@ -1,4 +1,5 @@
|
||||
require_relative '../../spec_helper'
|
||||
require_relative '../../shared/time/yday'
|
||||
|
||||
describe "Time#yday" do
|
||||
it "returns an integer representing the day of the year, 1..366" do
|
||||
@ -7,15 +8,5 @@ describe "Time#yday" do
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns the correct value for each day of each month' do
|
||||
mdays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
|
||||
|
||||
yday = 1
|
||||
mdays.each_with_index do |days, month|
|
||||
days.times do |day|
|
||||
Time.new(2014, month+1, day+1).yday.should == yday
|
||||
yday += 1
|
||||
end
|
||||
end
|
||||
end
|
||||
it_behaves_like :time_yday, -> year, month, day { Time.new(year, month, day).yday }
|
||||
end
|
||||
|
@ -19,6 +19,27 @@ describe "The for expression" do
|
||||
end
|
||||
end
|
||||
|
||||
it "iterates over a list of arrays and destructures with an empty splat" do
|
||||
for i, * in [[1,2]]
|
||||
i.should == 1
|
||||
end
|
||||
end
|
||||
|
||||
it "iterates over a list of arrays and destructures with a splat" do
|
||||
for i, *j in [[1,2]]
|
||||
i.should == 1
|
||||
j.should == [2]
|
||||
end
|
||||
end
|
||||
|
||||
it "iterates over a list of arrays and destructures with a splat and additional targets" do
|
||||
for i, *j, k in [[1,2,3,4]]
|
||||
i.should == 1
|
||||
j.should == [2,3]
|
||||
k.should == 4
|
||||
end
|
||||
end
|
||||
|
||||
it "iterates over an Hash passing each key-value pair to the block" do
|
||||
k = 0
|
||||
l = 0
|
||||
@ -81,6 +102,88 @@ describe "The for expression" do
|
||||
end
|
||||
end
|
||||
|
||||
it "allows a global variable as an iterator name" do
|
||||
old_global_var = $var
|
||||
m = [1,2,3]
|
||||
n = 0
|
||||
for $var in m
|
||||
n += 1
|
||||
end
|
||||
$var.should == 3
|
||||
n.should == 3
|
||||
$var = old_global_var
|
||||
end
|
||||
|
||||
it "allows an attribute as an iterator name" do
|
||||
class OFor
|
||||
attr_accessor :target
|
||||
end
|
||||
|
||||
ofor = OFor.new
|
||||
m = [1,2,3]
|
||||
n = 0
|
||||
for ofor.target in m
|
||||
n += 1
|
||||
end
|
||||
ofor.target.should == 3
|
||||
n.should == 3
|
||||
end
|
||||
|
||||
# Segfault in MRI 3.3 and lower: https://bugs.ruby-lang.org/issues/20468
|
||||
ruby_bug "#20468", ""..."3.4" do
|
||||
it "allows an attribute with safe navigation as an iterator name" do
|
||||
class OFor
|
||||
attr_accessor :target
|
||||
end
|
||||
|
||||
ofor = OFor.new
|
||||
m = [1,2,3]
|
||||
n = 0
|
||||
eval <<~RUBY
|
||||
for ofor&.target in m
|
||||
n += 1
|
||||
end
|
||||
RUBY
|
||||
ofor.target.should == 3
|
||||
n.should == 3
|
||||
end
|
||||
|
||||
it "allows an attribute with safe navigation on a nil base as an iterator name" do
|
||||
ofor = nil
|
||||
m = [1,2,3]
|
||||
n = 0
|
||||
eval <<~RUBY
|
||||
for ofor&.target in m
|
||||
n += 1
|
||||
end
|
||||
RUBY
|
||||
ofor.should be_nil
|
||||
n.should == 3
|
||||
end
|
||||
end
|
||||
|
||||
it "allows an array index writer as an iterator name" do
|
||||
arr = [:a, :b, :c]
|
||||
m = [1,2,3]
|
||||
n = 0
|
||||
for arr[1] in m
|
||||
n += 1
|
||||
end
|
||||
arr.should == [:a, 3, :c]
|
||||
n.should == 3
|
||||
end
|
||||
|
||||
it "allows a hash index writer as an iterator name" do
|
||||
hash = { a: 10, b: 20, c: 30 }
|
||||
m = [1,2,3]
|
||||
n = 0
|
||||
for hash[:b] in m
|
||||
n += 1
|
||||
end
|
||||
hash.should == { a: 10, b: 3, c: 30 }
|
||||
n.should == 3
|
||||
end
|
||||
|
||||
# 1.9 behaviour verified by nobu in
|
||||
# http://redmine.ruby-lang.org/issues/show/2053
|
||||
it "yields only as many values as there are arguments" do
|
||||
|
@ -106,4 +106,14 @@ HERE
|
||||
SquigglyHeredocSpecs.least_indented_on_the_first_line_single.should == "a\n b\n c\n"
|
||||
SquigglyHeredocSpecs.least_indented_on_the_last_line_single.should == " a\n b\nc\n"
|
||||
end
|
||||
|
||||
it "reports line numbers inside HEREDOC with method call" do
|
||||
-> {
|
||||
<<-HERE.chomp
|
||||
a
|
||||
b
|
||||
#{c}
|
||||
HERE
|
||||
}.should raise_error(NameError) { |e| e.backtrace[0].should.start_with?("#{__FILE__}:#{__LINE__ - 2}") }
|
||||
end
|
||||
end
|
||||
|
@ -5,7 +5,7 @@ describe "Pattern matching" do
|
||||
ScratchPad.record []
|
||||
end
|
||||
|
||||
describe "can be standalone assoc operator that" do
|
||||
describe "Rightward assignment (`=>`) that can be standalone assoc operator that" do
|
||||
it "deconstructs value" do
|
||||
suppress_warning do
|
||||
[0, 1] => [a, b]
|
||||
@ -22,6 +22,23 @@ describe "Pattern matching" do
|
||||
[a, defined?(b)].should == [0, nil]
|
||||
end
|
||||
end
|
||||
|
||||
it "can work with keywords" do
|
||||
{ a: 0, b: 1 } => { a:, b: }
|
||||
[a, b].should == [0, 1]
|
||||
end
|
||||
end
|
||||
|
||||
describe "One-line pattern matching" do
|
||||
it "can be used to check if a pattern matches for Array-like entities" do
|
||||
([0, 1] in [a, b]).should == true
|
||||
([0, 1] in [a, b, c]).should == false
|
||||
end
|
||||
|
||||
it "can be used to check if a pattern matches for Hash-like entities" do
|
||||
({ a: 0, b: 1 } in { a:, b: }).should == true
|
||||
({ a: 0, b: 1 } in { a:, b:, c: }).should == false
|
||||
end
|
||||
end
|
||||
|
||||
describe "find pattern" do
|
||||
|
@ -52,6 +52,16 @@ describe "The rescue keyword" do
|
||||
RescueSpecs::SafeNavigationSetterCaptor.should_capture_exception
|
||||
end
|
||||
|
||||
it 'using a safely navigated setter method on a nil target' do
|
||||
target = nil
|
||||
begin
|
||||
raise SpecificExampleException, "Raising this to be handled below"
|
||||
rescue SpecificExampleException => target&.captured_error
|
||||
:caught
|
||||
end.should == :caught
|
||||
target.should be_nil
|
||||
end
|
||||
|
||||
it 'using a setter method' do
|
||||
RescueSpecs::SetterCaptor.should_capture_exception
|
||||
end
|
||||
|
3
spec/ruby/library/coverage/fixtures/code_with_begin.rb
Normal file
3
spec/ruby/library/coverage/fixtures/code_with_begin.rb
Normal file
@ -0,0 +1,3 @@
|
||||
begin
|
||||
'coverage with begin'
|
||||
end
|
@ -6,6 +6,7 @@ describe 'Coverage.result' do
|
||||
@class_file = fixture __FILE__, 'some_class.rb'
|
||||
@config_file = fixture __FILE__, 'start_coverage.rb'
|
||||
@eval_code_file = fixture __FILE__, 'eval_code.rb'
|
||||
@with_begin_file = fixture __FILE__, 'code_with_begin.rb'
|
||||
end
|
||||
|
||||
before :each do
|
||||
@ -16,6 +17,7 @@ describe 'Coverage.result' do
|
||||
$LOADED_FEATURES.delete(@class_file)
|
||||
$LOADED_FEATURES.delete(@config_file)
|
||||
$LOADED_FEATURES.delete(@eval_code_file)
|
||||
$LOADED_FEATURES.delete(@with_begin_file)
|
||||
|
||||
Coverage.result if Coverage.running?
|
||||
end
|
||||
@ -354,4 +356,16 @@ describe 'Coverage.result' do
|
||||
|
||||
Coverage.peek_result.should == result
|
||||
end
|
||||
|
||||
it 'covers 100% lines with begin' do
|
||||
Coverage.start
|
||||
require @with_begin_file.chomp('.rb')
|
||||
result = Coverage.result
|
||||
|
||||
result.should == {
|
||||
@with_begin_file => [
|
||||
nil, 1, nil
|
||||
]
|
||||
}
|
||||
end
|
||||
end
|
||||
|
@ -38,7 +38,7 @@ describe "Date#year" do
|
||||
end
|
||||
|
||||
describe "Date#yday" do
|
||||
it "determines the year" do
|
||||
it "determines the day of the year" do
|
||||
Date.civil(2007, 1, 17).yday.should == 17
|
||||
Date.civil(2008, 10, 28).yday.should == 302
|
||||
end
|
||||
|
@ -1,6 +1,7 @@
|
||||
require_relative '../../spec_helper'
|
||||
require_relative '../../shared/time/yday'
|
||||
require 'date'
|
||||
|
||||
describe "Date#yday" do
|
||||
it "needs to be reviewed for spec completeness"
|
||||
it_behaves_like :time_yday, -> year, month, day { Date.new(year, month, day).yday }
|
||||
end
|
||||
|
7
spec/ruby/library/datetime/yday_spec.rb
Normal file
7
spec/ruby/library/datetime/yday_spec.rb
Normal file
@ -0,0 +1,7 @@
|
||||
require_relative '../../spec_helper'
|
||||
require_relative '../../shared/time/yday'
|
||||
require 'date'
|
||||
|
||||
describe "DateTime#yday" do
|
||||
it_behaves_like :time_yday, -> year, month, day { DateTime.new(year, month, day).yday }
|
||||
end
|
@ -34,6 +34,18 @@ describe :net_ftp_puttextfile, shared: true do
|
||||
remote_lines.should == local_lines.gsub("\n", "\r\n")
|
||||
end
|
||||
|
||||
guard -> { Net::FTP::VERSION < '0.3.6' } do
|
||||
it "returns nil" do
|
||||
@ftp.send(@method, @local_fixture_file, "text").should be_nil
|
||||
end
|
||||
end
|
||||
|
||||
guard -> { Net::FTP::VERSION >= '0.3.6' } do
|
||||
it "returns the response" do
|
||||
@ftp.send(@method, @local_fixture_file, "text").should == @ftp.last_response
|
||||
end
|
||||
end
|
||||
|
||||
describe "when passed a block" do
|
||||
it "yields each transmitted line" do
|
||||
res = []
|
||||
|
@ -2,7 +2,6 @@ require_relative '../spec_helper'
|
||||
require_relative '../fixtures/classes'
|
||||
|
||||
describe "Socket::IPSocket#getaddress" do
|
||||
|
||||
it "returns the IP address of hostname" do
|
||||
addr_local = IPSocket.getaddress(SocketSpecs.hostname)
|
||||
["127.0.0.1", "::1"].include?(addr_local).should == true
|
||||
@ -14,6 +13,10 @@ describe "Socket::IPSocket#getaddress" do
|
||||
IPSocket.getaddress('::1').should == '::1'
|
||||
end
|
||||
|
||||
it 'returns IPv4 compatible IPv6 addresses' do
|
||||
IPSocket.getaddress('::ffff:192.168.1.1').should == '::ffff:192.168.1.1'
|
||||
end
|
||||
|
||||
# There is no way to make this fail-proof on all machines, because
|
||||
# DNS servers like opendns return A records for ANY host, including
|
||||
# traditionally invalidly named ones.
|
||||
|
@ -1,9 +1,11 @@
|
||||
require_relative '../spec_helper'
|
||||
require_relative '../fixtures/classes'
|
||||
require_relative '../shared/partially_closable_sockets'
|
||||
require_relative 'shared/pair'
|
||||
|
||||
with_feature :unix_socket do
|
||||
describe "UNIXSocket.pair" do
|
||||
it_should_behave_like :unixsocket_pair
|
||||
it_should_behave_like :partially_closable_sockets
|
||||
|
||||
before :each do
|
||||
@ -14,25 +16,5 @@ with_feature :unix_socket do
|
||||
@s1.close
|
||||
@s2.close
|
||||
end
|
||||
|
||||
it "returns a pair of connected sockets" do
|
||||
@s1.puts "foo"
|
||||
@s2.gets.should == "foo\n"
|
||||
end
|
||||
|
||||
it "returns sockets with no name" do
|
||||
@s1.path.should == @s2.path
|
||||
@s1.path.should == ""
|
||||
end
|
||||
|
||||
it "returns sockets with no address" do
|
||||
@s1.addr.should == ["AF_UNIX", ""]
|
||||
@s2.addr.should == ["AF_UNIX", ""]
|
||||
end
|
||||
|
||||
it "returns sockets with no peeraddr" do
|
||||
@s1.peeraddr.should == ["AF_UNIX", ""]
|
||||
@s2.peeraddr.should == ["AF_UNIX", ""]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
29
spec/ruby/library/socket/unixsocket/shared/pair.rb
Normal file
29
spec/ruby/library/socket/unixsocket/shared/pair.rb
Normal file
@ -0,0 +1,29 @@
|
||||
require_relative '../../spec_helper'
|
||||
require_relative '../../fixtures/classes'
|
||||
|
||||
describe :unixsocket_pair, shared: true do
|
||||
it "returns two UNIXSockets" do
|
||||
@s1.should be_an_instance_of(UNIXSocket)
|
||||
@s2.should be_an_instance_of(UNIXSocket)
|
||||
end
|
||||
|
||||
it "returns a pair of connected sockets" do
|
||||
@s1.puts "foo"
|
||||
@s2.gets.should == "foo\n"
|
||||
end
|
||||
|
||||
it "sets the socket paths to empty Strings" do
|
||||
@s1.path.should == ""
|
||||
@s2.path.should == ""
|
||||
end
|
||||
|
||||
it "sets the socket addresses to empty Strings" do
|
||||
@s1.addr.should == ["AF_UNIX", ""]
|
||||
@s2.addr.should == ["AF_UNIX", ""]
|
||||
end
|
||||
|
||||
it "sets the socket peer addresses to empty Strings" do
|
||||
@s1.peeraddr.should == ["AF_UNIX", ""]
|
||||
@s2.peeraddr.should == ["AF_UNIX", ""]
|
||||
end
|
||||
end
|
@ -1,40 +1,20 @@
|
||||
require_relative '../spec_helper'
|
||||
require_relative '../fixtures/classes'
|
||||
require_relative '../shared/partially_closable_sockets'
|
||||
require_relative 'shared/pair'
|
||||
|
||||
with_feature :unix_socket do
|
||||
describe 'UNIXSocket.socketpair' do
|
||||
before do
|
||||
describe "UNIXSocket.socketpair" do
|
||||
it_should_behave_like :unixsocket_pair
|
||||
it_should_behave_like :partially_closable_sockets
|
||||
|
||||
before :each do
|
||||
@s1, @s2 = UNIXSocket.socketpair
|
||||
end
|
||||
|
||||
after do
|
||||
after :each do
|
||||
@s1.close
|
||||
@s2.close
|
||||
end
|
||||
|
||||
it 'returns two UNIXSockets' do
|
||||
@s1.should be_an_instance_of(UNIXSocket)
|
||||
@s2.should be_an_instance_of(UNIXSocket)
|
||||
end
|
||||
|
||||
it 'connects the sockets to each other' do
|
||||
@s1.write('hello')
|
||||
|
||||
@s2.recv(5).should == 'hello'
|
||||
end
|
||||
|
||||
it 'sets the socket paths to empty Strings' do
|
||||
@s1.path.should == ''
|
||||
@s2.path.should == ''
|
||||
end
|
||||
|
||||
it 'sets the socket addresses to empty Strings' do
|
||||
@s1.addr.should == ['AF_UNIX', '']
|
||||
@s2.addr.should == ['AF_UNIX', '']
|
||||
end
|
||||
|
||||
it 'sets the socket peer addresses to empty Strings' do
|
||||
@s1.peeraddr.should == ['AF_UNIX', '']
|
||||
@s2.peeraddr.should == ['AF_UNIX', '']
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -130,6 +130,26 @@ describe "StringIO#initialize when passed [Object, mode]" do
|
||||
-> { @io.send(:initialize, str, "w") }.should raise_error(Errno::EACCES)
|
||||
-> { @io.send(:initialize, str, "a") }.should raise_error(Errno::EACCES)
|
||||
end
|
||||
|
||||
it "truncates all the content if passed w mode" do
|
||||
io = StringIO.allocate
|
||||
source = +"example".encode(Encoding::ISO_8859_1);
|
||||
|
||||
io.send(:initialize, source, "w")
|
||||
|
||||
io.string.should.empty?
|
||||
io.string.encoding.should == Encoding::ISO_8859_1
|
||||
end
|
||||
|
||||
it "truncates all the content if passed IO::TRUNC mode" do
|
||||
io = StringIO.allocate
|
||||
source = +"example".encode(Encoding::ISO_8859_1);
|
||||
|
||||
io.send(:initialize, source, IO::TRUNC)
|
||||
|
||||
io.string.should.empty?
|
||||
io.string.encoding.should == Encoding::ISO_8859_1
|
||||
end
|
||||
end
|
||||
|
||||
describe "StringIO#initialize when passed [Object]" do
|
||||
@ -172,7 +192,7 @@ end
|
||||
# NOTE: Synchronise with core/io/new_spec.rb (core/io/shared/new.rb)
|
||||
describe "StringIO#initialize when passed keyword arguments" do
|
||||
it "sets the mode based on the passed :mode option" do
|
||||
io = StringIO.new("example", "r")
|
||||
io = StringIO.new("example", mode: "r")
|
||||
io.closed_read?.should be_false
|
||||
io.closed_write?.should be_true
|
||||
end
|
||||
|
@ -7,9 +7,9 @@ describe "StringScanner#scan_until" do
|
||||
end
|
||||
|
||||
it "returns the substring up to and including the end of the match" do
|
||||
@s.scan_until(/a/).should == "This is a"
|
||||
@s.pre_match.should == "This is "
|
||||
@s.post_match.should == " test"
|
||||
@s.scan_until(/a/).should == "This is a"
|
||||
@s.pre_match.should == "This is "
|
||||
@s.post_match.should == " test"
|
||||
end
|
||||
|
||||
it "returns nil if there's no match" do
|
||||
|
@ -221,7 +221,7 @@ static VALUE kernel_spec_rb_eval_string_protect(VALUE self, VALUE str, VALUE ary
|
||||
VALUE kernel_spec_rb_sys_fail(VALUE self, VALUE msg) {
|
||||
errno = 1;
|
||||
if (msg == Qnil) {
|
||||
rb_sys_fail(0);
|
||||
rb_sys_fail(NULL);
|
||||
} else if (self != Qundef) {
|
||||
rb_sys_fail(StringValuePtr(msg));
|
||||
}
|
||||
|
18
spec/ruby/shared/time/yday.rb
Normal file
18
spec/ruby/shared/time/yday.rb
Normal file
@ -0,0 +1,18 @@
|
||||
describe :time_yday, shared: true do
|
||||
it 'returns the correct value for each day of each month' do
|
||||
mdays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
|
||||
|
||||
yday = 1
|
||||
mdays.each_with_index do |days, month|
|
||||
days.times do |day|
|
||||
@method.call(2014, month+1, day+1).should == yday
|
||||
yday += 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it 'supports leap years' do
|
||||
@method.call(2016, 2, 29).should == 31 + 29
|
||||
@method.call(2016, 3, 1).should == 31 + 29 + 1
|
||||
end
|
||||
end
|
Loading…
x
Reference in New Issue
Block a user