diff options
62 files changed, 656 insertions, 59 deletions
diff --git a/spec/ruby/core/array/shared/slice.rb b/spec/ruby/core/array/shared/slice.rb index cf195ad7a4..540a050130 100644 --- a/spec/ruby/core/array/shared/slice.rb +++ b/spec/ruby/core/array/shared/slice.rb @@ -743,6 +743,30 @@ describe :array_slice, shared: true do @array.send(@method, eval("(-2..-4).step(10)")).should == [] @array.send(@method, eval("(-2...-4).step(10)")).should == [] end + + it "has range with bounds outside of array" do + # end is equal to array's length + @array.send(@method, (0..6).step(1)).should == [0, 1, 2, 3, 4, 5] + -> { @array.send(@method, (0..6).step(2)) }.should raise_error(RangeError) + + # end is greater than length with positive steps + @array.send(@method, (1..6).step(2)).should == [1, 3, 5] + @array.send(@method, (2..7).step(2)).should == [2, 4] + -> { @array.send(@method, (2..8).step(2)) }.should raise_error(RangeError) + + # begin is greater than length with negative steps + @array.send(@method, (6..1).step(-2)).should == [5, 3, 1] + @array.send(@method, (7..2).step(-2)).should == [5, 3] + -> { @array.send(@method, (8..2).step(-2)) }.should raise_error(RangeError) + end + + it "has endless range with start outside of array's bounds" do + @array.send(@method, eval("(6..).step(1)")).should == [] + @array.send(@method, eval("(7..).step(1)")).should == nil + + @array.send(@method, eval("(6..).step(2)")).should == [] + -> { @array.send(@method, eval("(7..).step(2)")) }.should raise_error(RangeError) + end end end diff --git a/spec/ruby/core/dir/shared/glob.rb b/spec/ruby/core/dir/shared/glob.rb index 69fb0f0a01..a38ff8aa68 100644 --- a/spec/ruby/core/dir/shared/glob.rb +++ b/spec/ruby/core/dir/shared/glob.rb @@ -55,12 +55,24 @@ describe :dir_glob, shared: true do end end + ruby_version_is "3.0"..."3.1" do + it "result is sorted with any non false value of sort:" do + result = Dir.send(@method, '*', sort: 0) + result.should == result.sort + + result = Dir.send(@method, '*', sort: nil) + result.should == result.sort + + result = Dir.send(@method, '*', sort: 'false') + result.should == result.sort + end + end + ruby_version_is "3.1" do - it "true or false is expected as sort:" do - -> {Dir.send(@method, '*', sort: nil)}.should raise_error ArgumentError, /true or false/ - -> {Dir.send(@method, '*', sort: 0)}.should raise_error ArgumentError, /true or false/ - -> {Dir.send(@method, '*', sort: "")}.should raise_error ArgumentError, /true or false/ - -> {Dir.send(@method, '*', sort: Object.new)}.should raise_error ArgumentError, /true or false/ + it "raises an ArgumentError if sort: is not true or false" do + -> { Dir.send(@method, '*', sort: 0) }.should raise_error ArgumentError, /expected true or false/ + -> { Dir.send(@method, '*', sort: nil) }.should raise_error ArgumentError, /expected true or false/ + -> { Dir.send(@method, '*', sort: 'false') }.should raise_error ArgumentError, /expected true or false/ end end diff --git a/spec/ruby/core/encoding/compatible_spec.rb b/spec/ruby/core/encoding/compatible_spec.rb index dc47a6553a..80ecab6155 100644 --- a/spec/ruby/core/encoding/compatible_spec.rb +++ b/spec/ruby/core/encoding/compatible_spec.rb @@ -54,7 +54,7 @@ describe "Encoding.compatible? String, String" do it "returns nil if the second's Encoding is not ASCII compatible" do a = "abc".force_encoding("UTF-8") - b = "123".force_encoding("UTF-16LE") + b = "1234".force_encoding("UTF-16LE") Encoding.compatible?(a, b).should be_nil end end diff --git a/spec/ruby/core/encoding/converter/putback_spec.rb b/spec/ruby/core/encoding/converter/putback_spec.rb index 87495eaf3f..c4e0a5da21 100644 --- a/spec/ruby/core/encoding/converter/putback_spec.rb +++ b/spec/ruby/core/encoding/converter/putback_spec.rb @@ -34,14 +34,23 @@ describe "Encoding::Converter#putback" do @ec.putback.should == "" end + it "returns the problematic bytes for UTF-16LE" do + ec = Encoding::Converter.new("utf-16le", "iso-8859-1") + src = "\x00\xd8\x61\x00" + dst = "" + ec.primitive_convert(src, dst).should == :invalid_byte_sequence + ec.primitive_errinfo.should == [:invalid_byte_sequence, "UTF-16LE", "UTF-8", "\x00\xD8", "a\x00"] + ec.putback.should == "a\x00".force_encoding("utf-16le") + ec.putback.should == "" + end + it "accepts an integer argument corresponding to the number of bytes to be put back" do ec = Encoding::Converter.new("utf-16le", "iso-8859-1") src = "\x00\xd8\x61\x00" dst = "" ec.primitive_convert(src, dst).should == :invalid_byte_sequence ec.primitive_errinfo.should == [:invalid_byte_sequence, "UTF-16LE", "UTF-8", "\x00\xD8", "a\x00"] - ec.putback(1).should == "\x00".force_encoding("utf-16le") - ec.putback.should == "a".force_encoding("utf-16le") + ec.putback(2).should == "a\x00".force_encoding("utf-16le") ec.putback.should == "" end end diff --git a/spec/ruby/core/enumerable/grep_spec.rb b/spec/ruby/core/enumerable/grep_spec.rb index ac3d3db641..b81075291f 100644 --- a/spec/ruby/core/enumerable/grep_spec.rb +++ b/spec/ruby/core/enumerable/grep_spec.rb @@ -65,6 +65,18 @@ describe "Enumerable#grep" do ["abc", "def"].grep(/b/).should == ["abc"] Regexp.last_match[0].should == "z" end + + it "correctly handles non-string elements" do + 'set last match' =~ /set last (.*)/ + [:a, 'b', 'z', :c, 42, nil].grep(/[a-d]/).should == [:a, 'b', :c] + $1.should == 'match' + + o = Object.new + def o.to_str + 'hello' + end + [o].grep(/ll/).first.should.equal?(o) + end end describe "with a block" do diff --git a/spec/ruby/core/enumerable/grep_v_spec.rb b/spec/ruby/core/enumerable/grep_v_spec.rb index 892640efa4..35fde27eb6 100644 --- a/spec/ruby/core/enumerable/grep_v_spec.rb +++ b/spec/ruby/core/enumerable/grep_v_spec.rb @@ -45,6 +45,18 @@ describe "Enumerable#grep_v" do ["abc", "def"].grep_v(/e/).should == ["abc"] Regexp.last_match[0].should == "z" end + + it "correctly handles non-string elements" do + 'set last match' =~ /set last (.*)/ + [:a, 'b', 'z', :c, 42, nil].grep_v(/[a-d]/).should == ['z', 42, nil] + $1.should == 'match' + + o = Object.new + def o.to_str + 'hello' + end + [o].grep_v(/mm/).first.should.equal?(o) + end end describe "without block" do diff --git a/spec/ruby/core/enumerator/arithmetic_sequence/begin_spec.rb b/spec/ruby/core/enumerator/arithmetic_sequence/begin_spec.rb index bed30c546d..1837a4f246 100644 --- a/spec/ruby/core/enumerator/arithmetic_sequence/begin_spec.rb +++ b/spec/ruby/core/enumerator/arithmetic_sequence/begin_spec.rb @@ -6,4 +6,13 @@ describe "Enumerator::ArithmeticSequence#begin" do (1..10).step.begin.should == 1 (1...10).step.begin.should == 1 end + + ruby_version_is "2.7" do + context "with beginless" do + it "returns nil as begin of the sequence" do + eval("(..10).step(1)").begin.should == nil + eval("(...10).step(1)").begin.should == nil + end + end + end end diff --git a/spec/ruby/core/enumerator/arithmetic_sequence/end_spec.rb b/spec/ruby/core/enumerator/arithmetic_sequence/end_spec.rb index 29e6e105cf..05429cac3e 100644 --- a/spec/ruby/core/enumerator/arithmetic_sequence/end_spec.rb +++ b/spec/ruby/core/enumerator/arithmetic_sequence/end_spec.rb @@ -6,4 +6,11 @@ describe "Enumerator::ArithmeticSequence#end" do (1..10).step.end.should == 10 (1...10).step(17).end.should == 10 end + + context "with endless" do + it "returns nil as end of the sequence" do + (1..).step(1).end.should == nil + (1...).step(1).end.should == nil + end + end end diff --git a/spec/ruby/core/exception/errno_spec.rb b/spec/ruby/core/exception/errno_spec.rb index 095a926e09..a063e522ea 100644 --- a/spec/ruby/core/exception/errno_spec.rb +++ b/spec/ruby/core/exception/errno_spec.rb @@ -56,3 +56,12 @@ describe "Errno::ENOTSUP" do end end end + +describe "Errno::ENOENT" do + it "lets subclasses inherit the default error message" do + c = Class.new(Errno::ENOENT) + raise c, "custom message" + rescue => e + e.message.should == "No such file or directory - custom message" + end +end diff --git a/spec/ruby/core/gc/auto_compact_spec.rb b/spec/ruby/core/gc/auto_compact_spec.rb index 386725996d..4f9d043171 100644 --- a/spec/ruby/core/gc/auto_compact_spec.rb +++ b/spec/ruby/core/gc/auto_compact_spec.rb @@ -12,6 +12,11 @@ ruby_version_is "3.0" do original = GC.auto_compact begin GC.auto_compact = !original + rescue NotImplementedError # platform does not support autocompact + skip + end + + begin GC.auto_compact.should == !original ensure GC.auto_compact = original diff --git a/spec/ruby/core/gc/measure_total_time_spec.rb b/spec/ruby/core/gc/measure_total_time_spec.rb new file mode 100644 index 0000000000..05d4598ebc --- /dev/null +++ b/spec/ruby/core/gc/measure_total_time_spec.rb @@ -0,0 +1,19 @@ +require_relative '../../spec_helper' + +ruby_version_is "3.1" do + describe "GC.measure_total_time" do + before :each do + @default = GC.measure_total_time + end + + after :each do + GC.measure_total_time = @default + end + + it "can set and get a boolean value" do + original = GC.measure_total_time + GC.measure_total_time = !original + GC.measure_total_time.should == !original + end + end +end diff --git a/spec/ruby/core/gc/stat_spec.rb b/spec/ruby/core/gc/stat_spec.rb index eb71fd9691..3b43b28a92 100644 --- a/spec/ruby/core/gc/stat_spec.rb +++ b/spec/ruby/core/gc/stat_spec.rb @@ -7,6 +7,16 @@ describe "GC.stat" do stat.keys.should.include?(:count) end + it "updates the given hash values" do + hash = { count: "hello", __other__: "world" } + stat = GC.stat(hash) + + stat.should be_kind_of(Hash) + stat.should equal hash + stat[:count].should be_kind_of(Integer) + stat[:__other__].should == "world" + end + it "the values are all Integer since rb_gc_stat() returns size_t" do GC.stat.values.each { |value| value.should be_kind_of(Integer) } end @@ -41,4 +51,12 @@ describe "GC.stat" do GC.stat(:total_allocated_objects).should be_kind_of(Integer) GC.stat[:total_allocated_objects].should be_kind_of(Integer) end + + it "raises an error if argument is not nil, a symbol, or a hash" do + -> { GC.stat(7) }.should raise_error(TypeError, "non-hash or symbol given") + end + + it "raises an error if an unknown key is given" do + -> { GC.stat(:foo) }.should raise_error(ArgumentError, "unknown key: foo") + end end diff --git a/spec/ruby/core/gc/total_time_spec.rb b/spec/ruby/core/gc/total_time_spec.rb new file mode 100644 index 0000000000..9b4f16e603 --- /dev/null +++ b/spec/ruby/core/gc/total_time_spec.rb @@ -0,0 +1,15 @@ +require_relative '../../spec_helper' + +ruby_version_is "3.1" do + describe "GC.total_time" do + it "returns an Integer" do + GC.total_time.should be_kind_of(Integer) + end + + it "increases as collections are run" do + time_before = GC.total_time + GC.start + GC.total_time.should > time_before + end + end +end diff --git a/spec/ruby/core/integer/plus_spec.rb b/spec/ruby/core/integer/plus_spec.rb index be626c3305..511a436872 100644 --- a/spec/ruby/core/integer/plus_spec.rb +++ b/spec/ruby/core/integer/plus_spec.rb @@ -40,4 +40,19 @@ describe "Integer#+" do -> { @bignum + :symbol}.should raise_error(TypeError) end end + + it "can be redefined" do + code = <<~RUBY + class Integer + alias_method :old_plus, :+ + def +(other) + self - other + end + end + result = 1 + 2 + Integer.alias_method :+, :old_plus + print result + RUBY + ruby_exe(code).should == "-1" + end end diff --git a/spec/ruby/core/kernel/clone_spec.rb b/spec/ruby/core/kernel/clone_spec.rb index f9daa2badc..38ae1984c0 100644 --- a/spec/ruby/core/kernel/clone_spec.rb +++ b/spec/ruby/core/kernel/clone_spec.rb @@ -31,10 +31,10 @@ describe "Kernel#clone" do describe "with no arguments" do it "copies frozen state from the original" do o2 = @obj.clone + o2.should_not.frozen? + @obj.freeze o3 = @obj.clone - - o2.should_not.frozen? o3.should.frozen? end @@ -44,6 +44,30 @@ describe "Kernel#clone" do end end + describe "with freeze: nil" do + ruby_version_is ""..."3.0" do + it "raises ArgumentError" do + -> { @obj.clone(freeze: nil) }.should raise_error(ArgumentError, /unexpected value for freeze: NilClass/) + end + end + + ruby_version_is "3.0" do + it "copies frozen state from the original, like #clone without arguments" do + o2 = @obj.clone(freeze: nil) + o2.should_not.frozen? + + @obj.freeze + o3 = @obj.clone(freeze: nil) + o3.should.frozen? + end + + it "copies frozen?" do + o = "".freeze.clone(freeze: nil) + o.frozen?.should be_true + end + end + end + describe "with freeze: true" do it 'makes a frozen copy if the original is frozen' do @obj.freeze @@ -112,6 +136,14 @@ describe "Kernel#clone" do end end + describe "with freeze: anything else" do + it 'raises ArgumentError when passed not true/false/nil' do + -> { @obj.clone(freeze: 1) }.should raise_error(ArgumentError, /unexpected value for freeze: Integer/) + -> { @obj.clone(freeze: "") }.should raise_error(ArgumentError, /unexpected value for freeze: String/) + -> { @obj.clone(freeze: Object.new) }.should raise_error(ArgumentError, /unexpected value for freeze: Object/) + end + end + it "copies instance variables" do clone = @obj.clone clone.one.should == 1 diff --git a/spec/ruby/core/kernel/fixtures/classes.rb b/spec/ruby/core/kernel/fixtures/classes.rb index 8de1407b92..541a4c075e 100644 --- a/spec/ruby/core/kernel/fixtures/classes.rb +++ b/spec/ruby/core/kernel/fixtures/classes.rb @@ -281,9 +281,14 @@ module KernelSpecs @two = two end - def initialize_copy(other) + def initialize_copy(other, **kw) ScratchPad.record object_id end + + # define to support calling #clone with optional :freeze keyword argument + def initialize_clone(other, **kw) + super(other) # to call #initialize_copy + end end class Clone diff --git a/spec/ruby/core/kernel/initialize_clone_spec.rb b/spec/ruby/core/kernel/initialize_clone_spec.rb new file mode 100644 index 0000000000..2d889f5aad --- /dev/null +++ b/spec/ruby/core/kernel/initialize_clone_spec.rb @@ -0,0 +1,28 @@ +require_relative '../../spec_helper' + +describe "Kernel#initialize_clone" do + it "is a private instance method" do + Kernel.should have_private_instance_method(:initialize_clone) + end + + it "returns the receiver" do + a = Object.new + b = Object.new + a.send(:initialize_clone, b).should == a + end + + it "calls #initialize_copy" do + a = Object.new + b = Object.new + a.should_receive(:initialize_copy).with(b) + a.send(:initialize_clone, b) + end + + ruby_version_is "3.0" do + it "accepts a :freeze keyword argument for obj.clone(freeze: value)" do + a = Object.new + b = Object.new + a.send(:initialize_clone, b, freeze: true).should == a + end + end +end diff --git a/spec/ruby/core/kernel/initialize_dup_spec.rb b/spec/ruby/core/kernel/initialize_dup_spec.rb new file mode 100644 index 0000000000..6dff34b7ad --- /dev/null +++ b/spec/ruby/core/kernel/initialize_dup_spec.rb @@ -0,0 +1,20 @@ +require_relative '../../spec_helper' + +describe "Kernel#initialize_dup" do + it "is a private instance method" do + Kernel.should have_private_instance_method(:initialize_dup) + end + + it "returns the receiver" do + a = Object.new + b = Object.new + a.send(:initialize_dup, b).should == a + end + + it "calls #initialize_copy" do + a = Object.new + b = Object.new + a.should_receive(:initialize_copy).with(b) + a.send(:initialize_dup, b) + end +end diff --git a/spec/ruby/core/kernel/instance_variables_spec.rb b/spec/ruby/core/kernel/instance_variables_spec.rb index 831f0662a2..677d8bb7b2 100644 --- a/spec/ruby/core/kernel/instance_variables_spec.rb +++ b/spec/ruby/core/kernel/instance_variables_spec.rb @@ -25,5 +25,16 @@ describe "Kernel#instance_variables" do a.instance_variable_set("@test", 1) a.instance_variables.should == [:@test] end + + it "returns the instances variables in the order declared" do + c = Class.new do + def initialize + @c = 1 + @a = 2 + @b = 3 + end + end + c.new.instance_variables.should == [:@c, :@a, :@b] + end end end diff --git a/spec/ruby/core/kernel/print_spec.rb b/spec/ruby/core/kernel/print_spec.rb index c8c4453d1e..7e7c9b822d 100644 --- a/spec/ruby/core/kernel/print_spec.rb +++ b/spec/ruby/core/kernel/print_spec.rb @@ -5,6 +5,18 @@ describe "Kernel#print" do it "is a private method" do Kernel.should have_private_instance_method(:print) end + + it "delegates to $stdout" do + -> { print :arg }.should output("arg") + end + + it "prints $_ when no arguments are given" do + orig_value = $_ + $_ = 'foo' + -> { print }.should output("foo") + ensure + $_ = orig_value + end end describe "Kernel.print" do diff --git a/spec/ruby/core/kernel/warn_spec.rb b/spec/ruby/core/kernel/warn_spec.rb index 511e741f32..7df6fa72d1 100644 --- a/spec/ruby/core/kernel/warn_spec.rb +++ b/spec/ruby/core/kernel/warn_spec.rb @@ -212,6 +212,70 @@ describe "Kernel#warn" do -> { warn('foo', **h) }.should complain("foo\n") end + ruby_version_is '3.0' do + it "calls Warning.warn without keyword arguments if Warning.warn does not accept keyword arguments" do + verbose = $VERBOSE + $VERBOSE = false + class << Warning + alias_method :_warn, :warn + def warn(message) + ScratchPad.record(message) + end + end + + begin + ScratchPad.clear + Kernel.warn("Chunky bacon!") + ScratchPad.recorded.should == "Chunky bacon!\n" + + Kernel.warn("Deprecated bacon!", category: :deprecated) + ScratchPad.recorded.should == "Deprecated bacon!\n" + ensure + class << Warning + remove_method :warn + alias_method :warn, :_warn + remove_method :_warn + end + $VERBOSE = verbose + end + end + + it "calls Warning.warn with category: nil if Warning.warn accepts keyword arguments" do + Warning.should_receive(:warn).with("Chunky bacon!\n", category: nil) + verbose = $VERBOSE + $VERBOSE = false + begin + Kernel.warn("Chunky bacon!") + ensure + $VERBOSE = verbose + end + end + + it "calls Warning.warn with given category keyword converted to a symbol" do + Warning.should_receive(:warn).with("Chunky bacon!\n", category: :deprecated) + verbose = $VERBOSE + $VERBOSE = false + begin + Kernel.warn("Chunky bacon!", category: 'deprecated') + ensure + $VERBOSE = verbose + end + end + end + + ruby_version_is ''...'3.0' do + it "calls Warning.warn with no keyword arguments" do + Warning.should_receive(:warn).with("Chunky bacon!\n") + verbose = $VERBOSE + $VERBOSE = false + begin + Kernel.warn("Chunky bacon!") + ensure + $VERBOSE = verbose + end + end + end + it "does not call Warning.warn if self is the Warning module" do # RubyGems redefines Kernel#warn so we need to use a subprocess and disable RubyGems here code = <<-RUBY diff --git a/spec/ruby/core/matchdata/captures_spec.rb b/spec/ruby/core/matchdata/captures_spec.rb index 8c0d2978b7..58d4620709 100644 --- a/spec/ruby/core/matchdata/captures_spec.rb +++ b/spec/ruby/core/matchdata/captures_spec.rb @@ -1,7 +1,15 @@ require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe "MatchData#captures" do it "returns an array of the match captures" do /(.)(.)(\d+)(\d)/.match("THX1138.").captures.should == ["H","X","113","8"] end + + ruby_version_is "3.0" do + it "returns instances of String when given a String subclass" do + str = MatchDataSpecs::MyString.new("THX1138: The Movie") + /(.)(.)(\d+)(\d)/.match(str).captures.each { |c| c.should be_an_instance_of(String) } + end + end end diff --git a/spec/ruby/core/matchdata/element_reference_spec.rb b/spec/ruby/core/matchdata/element_reference_spec.rb index 26550ac94d..3b976cb1c4 100644 --- a/spec/ruby/core/matchdata/element_reference_spec.rb +++ b/spec/ruby/core/matchdata/element_reference_spec.rb @@ -1,4 +1,5 @@ require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe "MatchData#[]" do it "acts as normal array indexing [index]" do @@ -20,6 +21,13 @@ describe "MatchData#[]" do it "supports ranges [start..end]" do /(.)(.)(\d+)(\d)/.match("THX1138.")[1..3].should == %w|H X 113| end + + ruby_version_is "3.0" do + it "returns instances of String when given a String subclass" do + str = MatchDataSpecs::MyString.new("THX1138.") + /(.)(.)(\d+)(\d)/.match(str)[0..-1].each { |m| m.should be_an_instance_of(String) } + end + end end describe "MatchData#[Symbol]" do diff --git a/spec/ruby/core/matchdata/fixtures/classes.rb b/spec/ruby/core/matchdata/fixtures/classes.rb new file mode 100644 index 0000000000..54795636e5 --- /dev/null +++ b/spec/ruby/core/matchdata/fixtures/classes.rb @@ -0,0 +1,3 @@ +module MatchDataSpecs + class MyString < String; end +end diff --git a/spec/ruby/core/matchdata/post_match_spec.rb b/spec/ruby/core/matchdata/post_match_spec.rb index 4ae51f107e..1a4ca0a83f 100644 --- a/spec/ruby/core/matchdata/post_match_spec.rb +++ b/spec/ruby/core/matchdata/post_match_spec.rb @@ -1,4 +1,5 @@ require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe "MatchData#post_match" do it "returns the string after the match equiv. special var $'" do @@ -33,4 +34,11 @@ describe "MatchData#post_match" do str = "abc".force_encoding Encoding::ISO_8859_1 str.match(/c/).post_match.encoding.should equal(Encoding::ISO_8859_1) end + + ruby_version_is "3.0" do + it "returns an instance of String when given a String subclass" do + str = MatchDataSpecs::MyString.new("THX1138: The Movie") + /(.)(.)(\d+)(\d)/.match(str).post_match.should be_an_instance_of(String) + end + end end diff --git a/spec/ruby/core/matchdata/pre_match_spec.rb b/spec/ruby/core/matchdata/pre_match_spec.rb index 824612c84c..9b50336c7d 100644 --- a/spec/ruby/core/matchdata/pre_match_spec.rb +++ b/spec/ruby/core/matchdata/pre_match_spec.rb @@ -1,4 +1,5 @@ require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe "MatchData#pre_match" do it "returns the string before the match, equiv. special var $`" do @@ -33,4 +34,11 @@ describe "MatchData#pre_match" do str = "abc".force_encoding Encoding::ISO_8859_1 str.match(/a/).pre_match.encoding.should equal(Encoding::ISO_8859_1) end + + ruby_version_is "3.0" do + it "returns an instance of String when given a String subclass" do + str = MatchDataSpecs::MyString.new("THX1138: The Movie") + /(.)(.)(\d+)(\d)/.match(str).pre_match.should be_an_instance_of(String) + end + end end diff --git a/spec/ruby/core/matchdata/to_a_spec.rb b/spec/ruby/core/matchdata/to_a_spec.rb index 6231d096fb..50f5a161a5 100644 --- a/spec/ruby/core/matchdata/to_a_spec.rb +++ b/spec/ruby/core/matchdata/to_a_spec.rb @@ -1,7 +1,15 @@ require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe "MatchData#to_a" do it "returns an array of matches" do /(.)(.)(\d+)(\d)/.match("THX1138.").to_a.should == ["HX1138", "H", "X", "113", "8"] end + + ruby_version_is "3.0" do + it "returns instances of String when given a String subclass" do + str = MatchDataSpecs::MyString.new("THX1138.") + /(.)(.)(\d+)(\d)/.match(str)[0..-1].to_a.each { |m| m.should be_an_instance_of(String) } + end + end end diff --git a/spec/ruby/core/matchdata/to_s_spec.rb b/spec/ruby/core/matchdata/to_s_spec.rb index 9e213bb342..aab0955ae1 100644 --- a/spec/ruby/core/matchdata/to_s_spec.rb +++ b/spec/ruby/core/matchdata/to_s_spec.rb @@ -1,7 +1,15 @@ require_relative '../../spec_helper' +require_relative 'fixtures/classes' describe "MatchData#to_s" do it "returns the entire matched string" do /(.)(.)(\d+)(\d)/.match("THX1138.").to_s.should == "HX1138" end + + ruby_version_is "3.0" do + it "returns an instance of String when given a String subclass" do + str = MatchDataSpecs::MyString.new("THX1138.") + /(.)(.)(\d+)(\d)/.match(str).to_s.should be_an_instance_of(String) + end + end end diff --git a/spec/ruby/core/numeric/clone_spec.rb b/spec/ruby/core/numeric/clone_spec.rb index e3bf0a9e7c..c3b06ca0c9 100644 --- a/spec/ruby/core/numeric/clone_spec.rb +++ b/spec/ruby/core/numeric/clone_spec.rb @@ -22,4 +22,11 @@ describe "Numeric#clone" do it "raises ArgumentError if passed freeze: false" do -> { 1.clone(freeze: false) }.should raise_error(ArgumentError, /can't unfreeze/) end + + ruby_version_is "3.0" do + it "does not change frozen status if passed freeze: nil" do + value = 1 + value.clone(freeze: nil).should equal(value) + end + end end diff --git a/spec/ruby/core/numeric/quo_spec.rb b/spec/ruby/core/numeric/quo_spec.rb index 5c952b11a9..b4a23fd476 100644 --- a/spec/ruby/core/numeric/quo_spec.rb +++ b/spec/ruby/core/numeric/quo_spec.rb @@ -52,4 +52,13 @@ describe "Numeric#quo" do obj.quo(19).should == 1.quo(20) end + + it "raises a ZeroDivisionError if the given argument is zero and not a Float" do + -> { 1.quo(0) }.should raise_error(ZeroDivisionError) + end + + it "returns infinity if the given argument is zero and is a Float" do + (1.quo(0.0)).to_s.should == 'Infinity' + (-1.quo(0.0)).to_s.should == '-Infinity' + end end diff --git a/spec/ruby/core/range/step_spec.rb b/spec/ruby/core/range/step_spec.rb index 624fa71f5f..4c69073854 100644 --- a/spec/ruby/core/range/step_spec.rb +++ b/spec/ruby/core/range/step_spec.rb @@ -481,6 +481,32 @@ describe "Range#step" do end end + ruby_version_is "2.7" do + context "when begin is not defined and end is numeric" do + it "returns an instance of Enumerator::ArithmeticSequence" do + eval("(..10)").step.class.should == Enumerator::ArithmeticSequence + end + end + end + + context "when range is endless" do + it "returns an instance of Enumerator::ArithmeticSequence when begin is numeric" do + (1..).step.class.should == Enumerator::ArithmeticSequence + end + + it "returns an instance of Enumerator when begin is not numeric" do + ("a"..).step.class.should == Enumerator + end + end + + ruby_version_is "2.7" do + context "when range is beginless and endless" do + it "returns an instance of Enumerator" do + Range.new(nil, nil).step.class.should == Enumerator + end + end + end + context "when begin and end are not numerics" do it "returns an instance of Enumerator" do ("a".."z").step.class.should == Enumerator diff --git a/spec/ruby/core/string/each_grapheme_cluster_spec.rb b/spec/ruby/core/string/each_grapheme_cluster_spec.rb index 632f2337f1..b45d89ecb0 100644 --- a/spec/ruby/core/string/each_grapheme_cluster_spec.rb +++ b/spec/ruby/core/string/each_grapheme_cluster_spec.rb @@ -6,4 +6,12 @@ describe "String#each_grapheme_cluster" do it_behaves_like :string_chars, :each_grapheme_cluster it_behaves_like :string_grapheme_clusters, :each_grapheme_cluster it_behaves_like :string_each_char_without_block, :each_grapheme_cluster + + ruby_version_is '3.0' do + it "yields String instances for subclasses" do + a = [] + StringSpecs::MyString.new("abc").each_grapheme_cluster { |s| a << s.class } + a.should == [String, String, String] + end + end end diff --git a/spec/ruby/core/string/force_encoding_spec.rb b/spec/ruby/core/string/force_encoding_spec.rb index 2fe5f79c0f..f37aaf9eb4 100644 --- a/spec/ruby/core/string/force_encoding_spec.rb +++ b/spec/ruby/core/string/force_encoding_spec.rb @@ -60,7 +60,7 @@ describe "String#force_encoding" do end it "does not transcode self" do - str = "\u{8612}" + str = "é" str.dup.force_encoding('utf-16le').should_not == str.encode('utf-16le') end diff --git a/spec/ruby/core/string/scan_spec.rb b/spec/ruby/core/string/scan_spec.rb index 024e97022a..5f86dbbecc 100644 --- a/spec/ruby/core/string/scan_spec.rb +++ b/spec/ruby/core/string/scan_spec.rb @@ -198,4 +198,12 @@ describe "String#scan with pattern and block" do third.should == 'c'; end end + + ruby_version_is '3.0' do + it "yields String instances for subclasses" do + a = [] + StringSpecs::MyString.new("abc").scan(/./) { |s| a << s.class } + a.should == [String, String, String] + end + end end diff --git a/spec/ruby/core/string/scrub_spec.rb b/spec/ruby/core/string/scrub_spec.rb index 4da44a7992..3137399291 100644 --- a/spec/ruby/core/string/scrub_spec.rb +++ b/spec/ruby/core/string/scrub_spec.rb @@ -56,7 +56,9 @@ describe "String#scrub with a custom replacement" do it "replaces invalid byte sequences in frozen strings" do x81 = [0x81].pack('C').force_encoding('utf-8') (-"abc\u3042#{x81}").scrub("*").should == "abc\u3042*" - utf16_str = ("abc".encode('UTF-16LE').bytes + [0x81]).pack('c*').force_encoding('UTF-16LE') + + leading_surrogate = [0x00, 0xD8] + utf16_str = ("abc".encode('UTF-16LE').bytes + leading_surrogate).pack('c*').force_encoding('UTF-16LE') (-(utf16_str)).scrub("*".encode('UTF-16LE')).should == "abc*".encode('UTF-16LE') end diff --git a/spec/ruby/core/string/shared/eql.rb b/spec/ruby/core/string/shared/eql.rb index 85b861f4f1..b57d6895ff 100644 --- a/spec/ruby/core/string/shared/eql.rb +++ b/spec/ruby/core/string/shared/eql.rb @@ -21,7 +21,7 @@ describe :string_eql_value, shared: true do end it "considers encoding compatibility" do - "hello".force_encoding("utf-8").send(@method, "hello".force_encoding("utf-32le")).should be_false + "abcd".force_encoding("utf-8").send(@method, "abcd".force_encoding("utf-32le")).should be_false end it "ignores subclass differences" do diff --git a/spec/ruby/core/string/shared/length.rb b/spec/ruby/core/string/shared/length.rb index b9eae5170f..e931961455 100644 --- a/spec/ruby/core/string/shared/length.rb +++ b/spec/ruby/core/string/shared/length.rb @@ -36,4 +36,20 @@ describe :string_length, shared: true do concat.force_encoding(Encoding::ASCII_8BIT) concat.size.should == 4 end + + it "adds 1 for every invalid byte in UTF-8" do + "\xF4\x90\x80\x80".size.should == 4 + "a\xF4\x90\x80\x80b".size.should == 6 + "é\xF4\x90\x80\x80è".size.should == 6 + end + + it "adds 1 (and not 2) for a incomplete surrogate in UTF-16" do + "\x00\xd8".force_encoding("UTF-16LE").size.should == 1 + "\xd8\x00".force_encoding("UTF-16BE").size.should == 1 + end + + it "adds 1 for a broken sequence in UTF-32" do + "\x04\x03\x02\x01".force_encoding("UTF-32LE").size.should == 1 + "\x01\x02\x03\x04".force_encoding("UTF-32BE").size.should == 1 + end end diff --git a/spec/ruby/core/string/valid_encoding_spec.rb b/spec/ruby/core/string/valid_encoding_spec.rb index d5bf31710f..be7cef7a8e 100644 --- a/spec/ruby/core/string/valid_encoding_spec.rb +++ b/spec/ruby/core/string/valid_encoding_spec.rb @@ -43,10 +43,10 @@ describe "String#valid_encoding?" do str.force_encoding('KOI8-R').valid_encoding?.should be_true str.force_encoding('KOI8-U').valid_encoding?.should be_true str.force_encoding('Shift_JIS').valid_encoding?.should be_false - str.force_encoding('UTF-16BE').valid_encoding?.should be_false - str.force_encoding('UTF-16LE').valid_encoding?.should be_false - str.force_encoding('UTF-32BE').valid_encoding?.should be_false - str.force_encoding('UTF-32LE').valid_encoding?.should be_false + "\xD8\x00".force_encoding('UTF-16BE').valid_encoding?.should be_false + "\x00\xD8".force_encoding('UTF-16LE').valid_encoding?.should be_false + "\x04\x03\x02\x01".force_encoding('UTF-32BE').valid_encoding?.should be_false + "\x01\x02\x03\x04".force_encoding('UTF-32LE').valid_encoding?.should be_false str.force_encoding('Windows-1251').valid_encoding?.should be_true str.force_encoding('IBM437').valid_encoding?.should be_true str.force_encoding('IBM737').valid_encoding?.should be_true diff --git a/spec/ruby/core/warning/element_reference_spec.rb b/spec/ruby/core/warning/element_reference_spec.rb index a346cf535b..f51cc87de5 100644 --- a/spec/ruby/core/warning/element_reference_spec.rb +++ b/spec/ruby/core/warning/element_reference_spec.rb @@ -12,5 +12,11 @@ ruby_version_is '2.7' do it "raises for unknown category" do -> { Warning[:noop] }.should raise_error(ArgumentError, /unknown category: noop/) end + + it "raises for non-Symbol category" do + -> { Warning[42] }.should raise_error(TypeError) + -> { Warning[false] }.should raise_error(TypeError) + -> { Warning["noop"] }.should raise_error(TypeError) + end end end diff --git a/spec/ruby/core/warning/element_set_spec.rb b/spec/ruby/core/warning/element_set_spec.rb index 3b0ea45c9b..611060fb3a 100644 --- a/spec/ruby/core/warning/element_set_spec.rb +++ b/spec/ruby/core/warning/element_set_spec.rb @@ -27,5 +27,11 @@ ruby_version_is '2.7' do it "raises for unknown category" do -> { Warning[:noop] = false }.should raise_error(ArgumentError, /unknown category: noop/) end + + it "raises for non-Symbol category" do + -> { Warning[42] = false }.should raise_error(TypeError) + -> { Warning[false] = false }.should raise_error(TypeError) + -> { Warning["noop"] = false }.should raise_error(TypeError) + end end end diff --git a/spec/ruby/core/warning/warn_spec.rb b/spec/ruby/core/warning/warn_spec.rb index 2ded6a109d..5ccff3aa2b 100644 --- a/spec/ruby/core/warning/warn_spec.rb +++ b/spec/ruby/core/warning/warn_spec.rb @@ -51,7 +51,6 @@ describe "Warning.warn" do end end - ruby_version_is '3.0' do it "is called by Kernel.warn with nil category keyword" do Warning.should_receive(:warn).with("Chunky bacon!\n", category: nil) @@ -69,7 +68,7 @@ describe "Warning.warn" do verbose = $VERBOSE $VERBOSE = false begin - Kernel.warn("Chunky bacon!", category: 'deprecated') + Kernel.warn("Chunky bacon!", category: "deprecated") ensure $VERBOSE = verbose end diff --git a/spec/ruby/language/class_variable_spec.rb b/spec/ruby/language/class_variable_spec.rb index 9a4b36e82b..f98deaa081 100644 --- a/spec/ruby/language/class_variable_spec.rb +++ b/spec/ruby/language/class_variable_spec.rb @@ -94,6 +94,12 @@ ruby_version_is "3.0" do }.should raise_error(RuntimeError, 'class variable access from toplevel') end + it "does not raise an error when checking if defined from the toplevel scope" do + -> { + eval "defined?(@@cvar_toplevel1)" + }.should_not raise_error + end + it "raises a RuntimeError when a class variable is overtaken in an ancestor class" do parent = Class.new() subclass = Class.new(parent) diff --git a/spec/ruby/language/regexp/encoding_spec.rb b/spec/ruby/language/regexp/encoding_spec.rb index 8e2a294b95..febc3fdb37 100644 --- a/spec/ruby/language/regexp/encoding_spec.rb +++ b/spec/ruby/language/regexp/encoding_spec.rb @@ -38,6 +38,10 @@ describe "Regexps with encoding modifiers" do /#{/./}/n.match("\303\251").to_a.should == ["\303"] end + it "warns when using /n with a match string with non-ASCII characters and an encoding other than ASCII-8BIT" do + -> { /./n.match("\303\251".force_encoding('utf-8')) }.should complain(%r{historical binary regexp match /.../n against UTF-8 string}) + end + it 'uses US-ASCII as /n encoding if all chars are 7-bit' do /./n.encoding.should == Encoding::US_ASCII end @@ -117,6 +121,19 @@ describe "Regexps with encoding modifiers" do -> { /\A[[:space:]]*\z/ =~ " ".encode("UTF-16LE") }.should raise_error(Encoding::CompatibilityError) end + it "raises Encoding::CompatibilityError when the regexp has a fixed, non-ASCII-compatible encoding" do + -> { Regexp.new("".force_encoding("UTF-16LE"), Regexp::FIXEDENCODING) =~ " ".encode("UTF-8") }.should raise_error(Encoding::CompatibilityError) + end + + it "raises Encoding::CompatibilityError when the regexp has a fixed encoding and the match string has non-ASCII characters" do + -> { Regexp.new("".force_encoding("US-ASCII"), Regexp::FIXEDENCODING) =~ "\303\251".force_encoding('UTF-8') }.should raise_error(Encoding::CompatibilityError) + end + + it "raises ArgumentError when trying to match a broken String" do + s = "\x80".force_encoding('UTF-8') + -> { s =~ /./ }.should raise_error(ArgumentError, "invalid byte sequence in UTF-8") + end + it "computes the Regexp Encoding for each interpolated Regexp instance" do make_regexp = -> str { /#{str}/ } diff --git a/spec/ruby/library/fiber/resume_spec.rb b/spec/ruby/library/fiber/resume_spec.rb index 39d14bdda0..8b7c104a6f 100644 --- a/spec/ruby/library/fiber/resume_spec.rb +++ b/spec/ruby/library/fiber/resume_spec.rb @@ -10,6 +10,12 @@ describe "Fiber#resume" do fiber2.resume -> { fiber2.resume }.should raise_error(FiberError) end + + it "raises a FiberError if the Fiber attempts to resume a resuming fiber" do + root_fiber = Fiber.current + fiber1 = Fiber.new { root_fiber.resume } + -> { fiber1.resume }.should raise_error(FiberError, /double resume/) + end end ruby_version_is '3.0' do @@ -19,5 +25,11 @@ describe "Fiber#resume" do fiber2.resume.should == 10 fiber2.resume.should == 20 end + + it "raises a FiberError if the Fiber attempts to resume a resuming fiber" do + root_fiber = Fiber.current + fiber1 = Fiber.new { root_fiber.resume } + -> { fiber1.resume }.should raise_error(FiberError, /attempt to resume a resuming fiber/) + end end end diff --git a/spec/ruby/library/rexml/element/each_element_with_attribute_spec.rb b/spec/ruby/library/rexml/element/each_element_with_attribute_spec.rb index f2d779e577..dcc6dbbf17 100644 --- a/spec/ruby/library/rexml/element/each_element_with_attribute_spec.rb +++ b/spec/ruby/library/rexml/element/each_element_with_attribute_spec.rb @@ -12,23 +12,23 @@ ruby_version_is ''...'3.0' do @son.attributes["name"] = "Fred" @document.root << @father @document.root << @son - @childs = [] + @children = [] end - it "returns childs with attribute" do - @document.each_element_with_attribute("name") { |elem| @childs << elem } - @childs[0].should == @father - @childs[1].should == @son + it "returns children with attribute" do + @document.each_element_with_attribute("name") { |elem| @children << elem } + @children[0].should == @father + @children[1].should == @son end it "takes attribute value as second argument" do @document.each_element_with_attribute("name", "Fred"){ |elem| elem.should == @son } end - it "takes max number of childs as third argument" do - @document.each_element_with_attribute("name", nil, 1) { |elem| @childs << elem } - @childs.size.should == 1 - @childs[0].should == @father + it "takes max number of children as third argument" do + @document.each_element_with_attribute("name", nil, 1) { |elem| @children << elem } + @children.size.should == 1 + @children[0].should == @father end it "takes XPath filter as fourth argument" do diff --git a/spec/ruby/library/rexml/element/each_element_with_text_spec.rb b/spec/ruby/library/rexml/element/each_element_with_text_spec.rb index 8f9d062c99..a4a200d237 100644 --- a/spec/ruby/library/rexml/element/each_element_with_text_spec.rb +++ b/spec/ruby/library/rexml/element/each_element_with_text_spec.rb @@ -16,10 +16,10 @@ ruby_version_is ''...'3.0' do @document.root << @joe @document.root << @fred @document.root << @another - @childs = [] + @children = [] end - it "returns childs with text" do + it "returns children with text" do @document.each_element_with_text("Joe"){|c| c.should == @joe} end diff --git a/spec/ruby/library/rexml/element/has_text_spec.rb b/spec/ruby/library/rexml/element/has_text_spec.rb index de19fe0763..206c167ae6 100644 --- a/spec/ruby/library/rexml/element/has_text_spec.rb +++ b/spec/ruby/library/rexml/element/has_text_spec.rb @@ -11,7 +11,7 @@ ruby_version_is ''...'3.0' do e.has_text?.should be_true end - it "returns false if it has no Text childs" do + it "returns false if it has no Text children" do e = REXML::Element.new("Person") e.has_text?.should be_false end diff --git a/spec/ruby/library/rexml/node/parent_spec.rb b/spec/ruby/library/rexml/node/parent_spec.rb index 07425e8f36..43c3a747e0 100644 --- a/spec/ruby/library/rexml/node/parent_spec.rb +++ b/spec/ruby/library/rexml/node/parent_spec.rb @@ -14,7 +14,7 @@ ruby_version_is ''...'3.0' do e.should.parent? end - # This includes attributes, CDatas and declarations. + # This includes attributes, CData and declarations. it "returns false for Texts" do e = REXML::Text.new("foo") e.should_not.parent? diff --git a/spec/ruby/library/rexml/shared/elements_to_a.rb b/spec/ruby/library/rexml/shared/elements_to_a.rb index 388250d8b3..b7169f0b2e 100644 --- a/spec/ruby/library/rexml/shared/elements_to_a.rb +++ b/spec/ruby/library/rexml/shared/elements_to_a.rb @@ -19,7 +19,7 @@ describe :rexml_elements_to_a, shared: true do # always needs the first param (even if it's nil). # A patch was submitted: # http://rubyforge.org/tracker/index.php?func=detail&aid=19354&group_id=426&atid=1698 - it "returns all childs if xpath is nil" do + it "returns all children if xpath is nil" do @e.elements.send(@method).should == [@first, @second] end diff --git a/spec/ruby/library/stringio/ungetbyte_spec.rb b/spec/ruby/library/stringio/ungetbyte_spec.rb index 2f082acbf6..87b27b837e 100644 --- a/spec/ruby/library/stringio/ungetbyte_spec.rb +++ b/spec/ruby/library/stringio/ungetbyte_spec.rb @@ -12,7 +12,7 @@ describe "StringIO#ungetbyte" do io.string.should == 'Shis is a simple string.' end - it "ungets a single byte from a string in the middle of a multibyte characte" do + it "ungets a single byte from a string in the middle of a multibyte character" do str = "\u01a9" io = StringIO.new(str) b = io.getbyte diff --git a/spec/ruby/library/stringscanner/check_until_spec.rb b/spec/ruby/library/stringscanner/check_until_spec.rb index e92ae5a2e9..ad222fd76b 100644 --- a/spec/ruby/library/stringscanner/check_until_spec.rb +++ b/spec/ruby/library/stringscanner/check_until_spec.rb @@ -12,4 +12,10 @@ describe "StringScanner#check_until" do @s.matched.should == "a" @s.check_until(/test/).should == "This is a test" end + + it "raises TypeError if given a String" do + -> { + @s.check_until('T') + }.should raise_error(TypeError, 'wrong argument type String (expected Regexp)') + end end diff --git a/spec/ruby/library/stringscanner/exist_spec.rb b/spec/ruby/library/stringscanner/exist_spec.rb index beafadc07b..ff860a0d3e 100644 --- a/spec/ruby/library/stringscanner/exist_spec.rb +++ b/spec/ruby/library/stringscanner/exist_spec.rb @@ -21,4 +21,10 @@ describe "StringScanner#exist?" do @s.scan(/This is/) @s.exist?(/i/).should == nil end + + it "raises TypeError if given a String" do + -> { + @s.exist?('T') + }.should raise_error(TypeError, 'wrong argument type String (expected Regexp)') + end end diff --git a/spec/ruby/library/stringscanner/matched_size_spec.rb b/spec/ruby/library/stringscanner/matched_size_spec.rb index a36bd3aafe..d9c338a07e 100644 --- a/spec/ruby/library/stringscanner/matched_size_spec.rb +++ b/spec/ruby/library/stringscanner/matched_size_spec.rb @@ -1,7 +1,24 @@ require_relative '../../spec_helper' -require_relative 'shared/matched_size' require 'strscan' describe "StringScanner#matched_size" do - it_behaves_like :strscan_matched_size, :matched_size + before :each do + @s = StringScanner.new("This is a test") + end + + it "returns the size of the most recent match" do + @s.check(/This/) + @s.matched_size.should == 4 + @s.matched_size.should == 4 + @s.scan(//) + @s.matched_size.should == 0 + end + + it "returns nil if there was no recent match" do + @s.matched_size.should == nil + @s.check(/\d+/) + @s.matched_size.should == nil + @s.terminate + @s.matched_size.should == nil + end end diff --git a/spec/ruby/library/stringscanner/scan_until_spec.rb b/spec/ruby/library/stringscanner/scan_until_spec.rb index 94239db50e..6b7782572d 100644 --- a/spec/ruby/library/stringscanner/scan_until_spec.rb +++ b/spec/ruby/library/stringscanner/scan_until_spec.rb @@ -20,4 +20,10 @@ describe "StringScanner#scan_until" do @s.scan(/T/) @s.scan_until(/^h/).should == "h" end + + it "raises TypeError if given a String" do + -> { + @s.scan_until('T') + }.should raise_error(TypeError, 'wrong argument type String (expected Regexp)') + end end diff --git a/spec/ruby/library/stringscanner/search_full_spec.rb b/spec/ruby/library/stringscanner/search_full_spec.rb index da9067e012..7d2a714fa5 100644 --- a/spec/ruby/library/stringscanner/search_full_spec.rb +++ b/spec/ruby/library/stringscanner/search_full_spec.rb @@ -27,4 +27,10 @@ describe "StringScanner#search_full" do @s.search_full(/This/, true, true).should == "This" @s.pos.should == 4 end + + it "raises TypeError if given a String" do + -> { + @s.search_full('T', true, true) + }.should raise_error(TypeError, 'wrong argument type String (expected Regexp)') + end end diff --git a/spec/ruby/library/stringscanner/shared/matched_size.rb b/spec/ruby/library/stringscanner/shared/matched_size.rb deleted file mode 100644 index 92174733f7..0000000000 --- a/spec/ruby/library/stringscanner/shared/matched_size.rb +++ /dev/null @@ -1,21 +0,0 @@ -describe :strscan_matched_size, shared: true do - before :each do - @s = StringScanner.new("This is a test") - end - - it "returns the size of the most recent match" do - @s.check(/This/) - @s.send(@method).should == 4 - @s.send(@method).should == 4 - @s.scan(//) - @s.send(@method).should == 0 - end - - it "returns nil if there was no recent match" do - @s.send(@method).should == nil - @s.check(/\d+/) - @s.send(@method).should == nil - @s.terminate - @s.send(@method).should == nil - end -end diff --git a/spec/ruby/library/stringscanner/size_spec.rb b/spec/ruby/library/stringscanner/size_spec.rb new file mode 100644 index 0000000000..3e475489e3 --- /dev/null +++ b/spec/ruby/library/stringscanner/size_spec.rb @@ -0,0 +1,17 @@ +require_relative '../../spec_helper' +require 'strscan' + +describe "StringScanner#size" do + before :each do + @s = StringScanner.new("This is a test") + end + + it "returns the number of captures groups of the last match" do + @s.scan(/(.)(.)(.)/) + @s.size.should == 4 + end + + it "returns nil if there is no last match" do + @s.size.should == nil + end +end diff --git a/spec/ruby/library/stringscanner/skip_until_spec.rb b/spec/ruby/library/stringscanner/skip_until_spec.rb index 73eb91b8ad..7b56f13e4f 100644 --- a/spec/ruby/library/stringscanner/skip_until_spec.rb +++ b/spec/ruby/library/stringscanner/skip_until_spec.rb @@ -15,4 +15,10 @@ describe "StringScanner#skip_until" do it "returns nil if no match was found" do @s.skip_until(/d+/).should == nil end + + it "raises TypeError if given a String" do + -> { + @s.skip_until('T') + }.should raise_error(TypeError, 'wrong argument type String (expected Regexp)') + end end diff --git a/spec/ruby/optional/capi/class_spec.rb b/spec/ruby/optional/capi/class_spec.rb index c2424668b9..a2d8b3e38a 100644 --- a/spec/ruby/optional/capi/class_spec.rb +++ b/spec/ruby/optional/capi/class_spec.rb @@ -12,6 +12,7 @@ autoload :ClassIdUnderAutoload, "#{object_path}/class_id_under_autoload_spec" describe :rb_path_to_class, shared: true do it "returns a class or module from a scoped String" do @s.send(@method, "CApiClassSpecs::A::B").should equal(CApiClassSpecs::A::B) + @s.send(@method, "CApiClassSpecs::A::M").should equal(CApiClassSpecs::A::M) end it "resolves autoload constants" do @@ -27,7 +28,9 @@ describe :rb_path_to_class, shared: true do end it "raises a TypeError if the constant is not a class or module" do - -> { @s.send(@method, "CApiClassSpecs::A::C") }.should raise_error(TypeError) + -> { + @s.send(@method, "CApiClassSpecs::A::C") + }.should raise_error(TypeError, 'CApiClassSpecs::A::C does not refer to class/module') end it "raises an ArgumentError even if a constant in the path exists on toplevel" do diff --git a/spec/ruby/optional/capi/ext/string_spec.c b/spec/ruby/optional/capi/ext/string_spec.c index 099363c951..2a21304a10 100644 --- a/spec/ruby/optional/capi/ext/string_spec.c +++ b/spec/ruby/optional/capi/ext/string_spec.c @@ -577,6 +577,14 @@ static VALUE string_spec_rb_str_catf(VALUE self, VALUE mesg) { return rb_str_catf(mesg, "fmt %d %d number", 41, 6); } +static VALUE string_spec_rb_str_locktmp(VALUE self, VALUE str) { + return rb_str_locktmp(str); +} + +static VALUE string_spec_rb_str_unlocktmp(VALUE self, VALUE str) { + return rb_str_unlocktmp(str); +} + void Init_string_spec(void) { VALUE cls = rb_define_class("CApiStringSpecs", rb_cObject); rb_define_method(cls, "rb_cstr2inum", string_spec_rb_cstr2inum, 2); @@ -672,6 +680,8 @@ void Init_string_spec(void) { rb_define_method(cls, "rb_utf8_str_new_cstr", string_spec_rb_utf8_str_new_cstr, 0); rb_define_method(cls, "rb_str_vcatf", string_spec_rb_str_vcatf, 1); rb_define_method(cls, "rb_str_catf", string_spec_rb_str_catf, 1); + rb_define_method(cls, "rb_str_locktmp", string_spec_rb_str_locktmp, 1); + rb_define_method(cls, "rb_str_unlocktmp", string_spec_rb_str_unlocktmp, 1); } #ifdef __cplusplus diff --git a/spec/ruby/optional/capi/fixtures/class.rb b/spec/ruby/optional/capi/fixtures/class.rb index dbb0b69967..193c7174e0 100644 --- a/spec/ruby/optional/capi/fixtures/class.rb +++ b/spec/ruby/optional/capi/fixtures/class.rb @@ -87,5 +87,8 @@ class CApiClassSpecs class B end + + module M + end end end diff --git a/spec/ruby/optional/capi/string_spec.rb b/spec/ruby/optional/capi/string_spec.rb index 3cd88a7390..ce387ffa49 100644 --- a/spec/ruby/optional/capi/string_spec.rb +++ b/spec/ruby/optional/capi/string_spec.rb @@ -1209,4 +1209,31 @@ end str.should == "test fmt 41 6 number" end end + + describe "rb_str_locktmp" do + it "raises an error when trying to lock an already locked string" do + str = "test" + @s.rb_str_locktmp(str).should == str + -> { @s.rb_str_locktmp(str) }.should raise_error(RuntimeError, 'temporal locking already locked string') + end + + it "locks a string so that modifications would raise an error" do + str = "test" + @s.rb_str_locktmp(str).should == str + -> { str.upcase! }.should raise_error(RuntimeError, 'can\'t modify string; temporarily locked') + end + end + + describe "rb_str_unlocktmp" do + it "unlocks a locked string" do + str = "test" + @s.rb_str_locktmp(str) + @s.rb_str_unlocktmp(str).should == str + str.upcase!.should == "TEST" + end + + it "raises an error when trying to unlock an already unlocked string" do + -> { @s.rb_str_unlocktmp("test") }.should raise_error(RuntimeError, 'temporal unlocking already unlocked string') + end + end end |