diff --git a/core/numeric/abs_spec.rb b/core/numeric/abs_spec.rb index 8bec50e337..4b16e06c97 100644 --- a/core/numeric/abs_spec.rb +++ b/core/numeric/abs_spec.rb @@ -1,6 +1,19 @@ require_relative '../../spec_helper' -require_relative 'shared/abs' +require_relative 'fixtures/classes' describe "Numeric#abs" do - it_behaves_like :numeric_abs, :abs + before :each do + @obj = NumericSpecs::Subclass.new + end + + it "returns self when self is greater than 0" do + @obj.should_receive(:<).with(0).and_return(false) + @obj.abs.should == @obj + end + + it "returns self\#@- when self is less than 0" do + @obj.should_receive(:<).with(0).and_return(true) + @obj.should_receive(:-@).and_return(:absolute_value) + @obj.abs.should == :absolute_value + end end diff --git a/core/numeric/angle_spec.rb b/core/numeric/angle_spec.rb index bb38165777..25d2834a52 100644 --- a/core/numeric/angle_spec.rb +++ b/core/numeric/angle_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/arg' describe "Numeric#angle" do - it_behaves_like :numeric_arg, :angle + it "is an alias of Numeric#arg" do + Numeric.instance_method(:angle).should == Numeric.instance_method(:arg) + end end diff --git a/core/numeric/arg_spec.rb b/core/numeric/arg_spec.rb index ba3b57c687..4fd059d7fc 100644 --- a/core/numeric/arg_spec.rb +++ b/core/numeric/arg_spec.rb @@ -1,6 +1,38 @@ require_relative '../../spec_helper' -require_relative 'shared/arg' describe "Numeric#arg" do - it_behaves_like :numeric_arg, :arg + before :each do + @numbers = [ + 20, + Rational(3, 4), + bignum_value, + infinity_value + ] + end + + it "returns 0 if positive" do + @numbers.each do |number| + number.arg.should == 0 + end + end + + it "returns Pi if negative" do + @numbers.each do |number| + (0-number).arg.should == Math::PI + end + end + + describe "with a Numeric subclass" do + it "returns 0 if self#<(0) returns false" do + numeric = mock_numeric('positive') + numeric.should_receive(:<).with(0).and_return(false) + numeric.arg.should == 0 + end + + it "returns Pi if self#<(0) returns true" do + numeric = mock_numeric('positive') + numeric.should_receive(:<).with(0).and_return(true) + numeric.arg.should == Math::PI + end + end end diff --git a/core/numeric/conj_spec.rb b/core/numeric/conj_spec.rb index 7d4777ca60..f376a0d4b1 100644 --- a/core/numeric/conj_spec.rb +++ b/core/numeric/conj_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/conj' describe "Numeric#conj" do - it_behaves_like :numeric_conj, :conj + it "is an alias of Numeric#conjugate" do + Numeric.instance_method(:conj).should == Numeric.instance_method(:conjugate) + end end diff --git a/core/numeric/conjugate_spec.rb b/core/numeric/conjugate_spec.rb index 99854766e7..ea4731991d 100644 --- a/core/numeric/conjugate_spec.rb +++ b/core/numeric/conjugate_spec.rb @@ -1,6 +1,20 @@ require_relative '../../spec_helper' -require_relative 'shared/conj' describe "Numeric#conjugate" do - it_behaves_like :numeric_conj, :conjugate + before :each do + @numbers = [ + 20, # Integer + 398.72, # Float + Rational(3, 4), # Rational + bignum_value, + infinity_value, + nan_value + ] + end + + it "returns self" do + @numbers.each do |number| + number.conjugate.should.equal?(number) + end + end end diff --git a/core/numeric/imag_spec.rb b/core/numeric/imag_spec.rb index b9e343cee9..761d6b0dbe 100644 --- a/core/numeric/imag_spec.rb +++ b/core/numeric/imag_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/imag' describe "Numeric#imag" do - it_behaves_like :numeric_imag, :imag + it "is an alias of Numeric#imaginary" do + Numeric.instance_method(:imag).should == Numeric.instance_method(:imaginary) + end end diff --git a/core/numeric/imaginary_spec.rb b/core/numeric/imaginary_spec.rb index ec708cb505..7b5d94cc75 100644 --- a/core/numeric/imaginary_spec.rb +++ b/core/numeric/imaginary_spec.rb @@ -1,6 +1,26 @@ require_relative '../../spec_helper' -require_relative 'shared/imag' describe "Numeric#imaginary" do - it_behaves_like :numeric_imag, :imaginary + before :each do + @numbers = [ + 20, # Integer + 398.72, # Float + Rational(3, 4), # Rational + bignum_value, # Bignum + infinity_value, + nan_value + ].map{|n| [n,-n]}.flatten + end + + it "returns 0" do + @numbers.each do |number| + number.imaginary.should == 0 + end + end + + it "raises an ArgumentError if given any arguments" do + @numbers.each do |number| + -> { number.imaginary(number) }.should.raise(ArgumentError) + end + end end diff --git a/core/numeric/magnitude_spec.rb b/core/numeric/magnitude_spec.rb index 1371dff21f..ea4dbd166f 100644 --- a/core/numeric/magnitude_spec.rb +++ b/core/numeric/magnitude_spec.rb @@ -1,6 +1,7 @@ require_relative "../../spec_helper" -require_relative 'shared/abs' describe "Numeric#magnitude" do - it_behaves_like :numeric_abs, :magnitude + it "is an alias of Numeric#abs" do + Numeric.instance_method(:magnitude).should == Numeric.instance_method(:abs) + end end diff --git a/core/numeric/phase_spec.rb b/core/numeric/phase_spec.rb index bc1995303f..3abe8f2e02 100644 --- a/core/numeric/phase_spec.rb +++ b/core/numeric/phase_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/arg' describe "Numeric#phase" do - it_behaves_like :numeric_arg, :phase + it "is an alias of Numeric#arg" do + Numeric.instance_method(:phase).should == Numeric.instance_method(:arg) + end end diff --git a/core/numeric/rect_spec.rb b/core/numeric/rect_spec.rb index 79a144c5a4..65cdcc5229 100644 --- a/core/numeric/rect_spec.rb +++ b/core/numeric/rect_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/rect' describe "Numeric#rect" do - it_behaves_like :numeric_rect, :rect + it "is an alias of Numeric#rectangular" do + Numeric.instance_method(:rect).should == Numeric.instance_method(:rectangular) + end end diff --git a/core/numeric/rectangular_spec.rb b/core/numeric/rectangular_spec.rb index 2c68985a16..81afccc12d 100644 --- a/core/numeric/rectangular_spec.rb +++ b/core/numeric/rectangular_spec.rb @@ -1,6 +1,48 @@ require_relative '../../spec_helper' -require_relative 'shared/rect' describe "Numeric#rectangular" do - it_behaves_like :numeric_rect, :rectangular + before :each do + @numbers = [ + 20, # Integer + 398.72, # Float + Rational(3, 4), # Rational + 99999999**99, # Bignum + infinity_value, + nan_value + ] + end + + it "returns an Array" do + @numbers.each do |number| + number.rectangular.should.instance_of?(Array) + end + end + + it "returns a two-element Array" do + @numbers.each do |number| + number.rectangular.size.should == 2 + end + end + + it "returns self as the first element" do + @numbers.each do |number| + if Float === number and number.nan? + number.rectangular.first.nan?.should == true + else + number.rectangular.first.should == number + end + end + end + + it "returns 0 as the last element" do + @numbers.each do |number| + number.rectangular.last.should == 0 + end + end + + it "raises an ArgumentError if given any arguments" do + @numbers.each do |number| + -> { number.rectangular(number) }.should.raise(ArgumentError) + end + end end diff --git a/core/numeric/shared/abs.rb b/core/numeric/shared/abs.rb deleted file mode 100644 index c3dadccfd6..0000000000 --- a/core/numeric/shared/abs.rb +++ /dev/null @@ -1,19 +0,0 @@ -require_relative '../../../spec_helper' -require_relative '../fixtures/classes' - -describe :numeric_abs, shared: true do - before :each do - @obj = NumericSpecs::Subclass.new - end - - it "returns self when self is greater than 0" do - @obj.should_receive(:<).with(0).and_return(false) - @obj.send(@method).should == @obj - end - - it "returns self\#@- when self is less than 0" do - @obj.should_receive(:<).with(0).and_return(true) - @obj.should_receive(:-@).and_return(:absolute_value) - @obj.send(@method).should == :absolute_value - end -end diff --git a/core/numeric/shared/arg.rb b/core/numeric/shared/arg.rb deleted file mode 100644 index c8e7ad8333..0000000000 --- a/core/numeric/shared/arg.rb +++ /dev/null @@ -1,38 +0,0 @@ -require_relative '../../../spec_helper' - -describe :numeric_arg, shared: true do - before :each do - @numbers = [ - 20, - Rational(3, 4), - bignum_value, - infinity_value - ] - end - - it "returns 0 if positive" do - @numbers.each do |number| - number.send(@method).should == 0 - end - end - - it "returns Pi if negative" do - @numbers.each do |number| - (0-number).send(@method).should == Math::PI - end - end - - describe "with a Numeric subclass" do - it "returns 0 if self#<(0) returns false" do - numeric = mock_numeric('positive') - numeric.should_receive(:<).with(0).and_return(false) - numeric.send(@method).should == 0 - end - - it "returns Pi if self#<(0) returns true" do - numeric = mock_numeric('positive') - numeric.should_receive(:<).with(0).and_return(true) - numeric.send(@method).should == Math::PI - end - end -end diff --git a/core/numeric/shared/conj.rb b/core/numeric/shared/conj.rb deleted file mode 100644 index 1a661fbbe8..0000000000 --- a/core/numeric/shared/conj.rb +++ /dev/null @@ -1,20 +0,0 @@ -require_relative '../../../spec_helper' - -describe :numeric_conj, shared: true do - before :each do - @numbers = [ - 20, # Integer - 398.72, # Float - Rational(3, 4), # Rational - bignum_value, - infinity_value, - nan_value - ] - end - - it "returns self" do - @numbers.each do |number| - number.send(@method).should.equal?(number) - end - end -end diff --git a/core/numeric/shared/imag.rb b/core/numeric/shared/imag.rb deleted file mode 100644 index 605a23d8c6..0000000000 --- a/core/numeric/shared/imag.rb +++ /dev/null @@ -1,26 +0,0 @@ -require_relative '../../../spec_helper' - -describe :numeric_imag, shared: true do - before :each do - @numbers = [ - 20, # Integer - 398.72, # Float - Rational(3, 4), # Rational - bignum_value, # Bignum - infinity_value, - nan_value - ].map{|n| [n,-n]}.flatten - end - - it "returns 0" do - @numbers.each do |number| - number.send(@method).should == 0 - end - end - - it "raises an ArgumentError if given any arguments" do - @numbers.each do |number| - -> { number.send(@method, number) }.should.raise(ArgumentError) - end - end -end diff --git a/core/numeric/shared/rect.rb b/core/numeric/shared/rect.rb deleted file mode 100644 index 32d03e45d2..0000000000 --- a/core/numeric/shared/rect.rb +++ /dev/null @@ -1,48 +0,0 @@ -require_relative '../../../spec_helper' - -describe :numeric_rect, shared: true do - before :each do - @numbers = [ - 20, # Integer - 398.72, # Float - Rational(3, 4), # Rational - 99999999**99, # Bignum - infinity_value, - nan_value - ] - end - - it "returns an Array" do - @numbers.each do |number| - number.send(@method).should.instance_of?(Array) - end - end - - it "returns a two-element Array" do - @numbers.each do |number| - number.send(@method).size.should == 2 - end - end - - it "returns self as the first element" do - @numbers.each do |number| - if Float === number and number.nan? - number.send(@method).first.nan?.should == true - else - number.send(@method).first.should == number - end - end - end - - it "returns 0 as the last element" do - @numbers.each do |number| - number.send(@method).last.should == 0 - end - end - - it "raises an ArgumentError if given any arguments" do - @numbers.each do |number| - -> { number.send(@method, number) }.should.raise(ArgumentError) - end - end -end diff --git a/core/proc/call_spec.rb b/core/proc/call_spec.rb index 6ec2fc8682..8b65be97c9 100644 --- a/core/proc/call_spec.rb +++ b/core/proc/call_spec.rb @@ -1,16 +1,138 @@ require_relative '../../spec_helper' -require_relative 'shared/call' -require_relative 'shared/call_arguments' +require_relative 'fixtures/common' +require_relative 'fixtures/proc_call' +require_relative 'fixtures/proc_call_frozen' describe "Proc#call" do - it_behaves_like :proc_call, :call - it_behaves_like :proc_call_block_args, :call -end + it "invokes self" do + Proc.new { "test!" }.call.should == "test!" + -> { "test!" }.call.should == "test!" + proc { "test!" }.call.should == "test!" + end -describe "Proc#call on a Proc created with Proc.new" do - it_behaves_like :proc_call_on_proc_new, :call -end + it "sets self's parameters to the given values" do + Proc.new { |a, b| a + b }.call(1, 2).should == 3 + Proc.new { |*args| args }.call(1, 2, 3, 4).should == [1, 2, 3, 4] + Proc.new { |_, *args| args }.call(1, 2, 3).should == [2, 3] + + -> a, b { a + b }.call(1, 2).should == 3 + -> *args { args }.call(1, 2, 3, 4).should == [1, 2, 3, 4] + -> _, *args { args }.call(1, 2, 3).should == [2, 3] + + proc { |a, b| a + b }.call(1, 2).should == 3 + proc { |*args| args }.call(1, 2, 3, 4).should == [1, 2, 3, 4] + proc { |_, *args| args }.call(1, 2, 3).should == [2, 3] + end + + it "can receive block arguments" do + Proc.new {|&b| b.call}.call {1 + 1}.should == 2 + -> &b { b.call}.call {1 + 1}.should == 2 + proc {|&b| b.call}.call {1 + 1}.should == 2 + end + + it "yields to the block given at declaration and not to the block argument" do + proc_creator = Object.new + def proc_creator.create + Proc.new do |&b| + yield + end + end + a_proc = proc_creator.create { 7 } + a_proc.call { 3 }.should == 7 + end + + it "can call its block argument declared with a block argument" do + proc_creator = Object.new + def proc_creator.create(method_name) + Proc.new do |&b| + yield + b.send(method_name) + end + end + a_proc = proc_creator.create(:call) { 7 } + a_proc.call { 3 }.should == 10 + end + + describe "on a Proc created with frozen_string_literal: true/false" do + it "doesn't duplicate frozen strings" do + ProcCallSpecs.call.frozen?.should == false + ProcCallSpecs.call_freeze.frozen?.should == true + ProcCallFrozenSpecs.call.frozen?.should == true + ProcCallFrozenSpecs.call_freeze.frozen?.should == true + end + end + + context "on a Proc created with Proc.new" do + it "replaces missing arguments with nil" do + Proc.new { |a, b| [a, b] }.call.should == [nil, nil] + Proc.new { |a, b| [a, b] }.call(1).should == [1, nil] + end + + it "silently ignores extra arguments" do + Proc.new { |a, b| a + b }.call(1, 2, 5).should == 3 + end + + it "auto-explodes a single Array argument" do + p = Proc.new { |a, b| [a, b] } + p.call(1, 2).should == [1, 2] + p.call([1, 2]).should == [1, 2] + p.call([1, 2, 3]).should == [1, 2] + p.call([1, 2, 3], 4).should == [[1, 2, 3], 4] + end + end + + context "on a Proc created with Kernel#lambda or Kernel#proc" do + it "ignores excess arguments when self is a proc" do + a = proc {|x| x}.call(1, 2) + a.should == 1 + + a = proc {|x| x}.call(1, 2, 3) + a.should == 1 + + a = proc {|x:| x}.call(2, x: 1) + a.should == 1 + end + + it "will call #to_ary on argument and return self if return is nil" do + argument = ProcSpecs::ToAryAsNil.new + result = proc { |x, _| x }.call(argument) + result.should == argument + end + + it "substitutes nil for missing arguments when self is a proc" do + proc {|x,y| [x,y]}.call.should == [nil,nil] + + a = proc {|x,y| [x, y]}.call(1) + a.should == [1,nil] + end + + it "raises an ArgumentError on excess arguments when self is a lambda" do + -> { + -> x { x }.call(1, 2) + }.should.raise(ArgumentError) + + -> { + -> x { x }.call(1, 2, 3) + }.should.raise(ArgumentError) + end + + it "raises an ArgumentError on missing arguments when self is a lambda" do + -> { + -> x { x }.call + }.should.raise(ArgumentError) + + -> { + -> x, y { [x,y] }.call(1) + }.should.raise(ArgumentError) + end + + it "treats a single Array argument as a single argument when self is a lambda" do + -> a { a }.call([1, 2]).should == [1, 2] + -> a, b { [a, b] }.call([1, 2], 3).should == [[1,2], 3] + end -describe "Proc#call on a Proc created with Kernel#lambda or Kernel#proc" do - it_behaves_like :proc_call_on_proc_or_lambda, :call + it "treats a single Array argument as a single argument when self is a proc" do + proc { |a| a }.call([1, 2]).should == [1, 2] + proc { |a, b| [a, b] }.call([1, 2], 3).should == [[1,2], 3] + end + end end diff --git a/core/proc/case_compare_spec.rb b/core/proc/case_compare_spec.rb index f11513cdb9..421afb24f0 100644 --- a/core/proc/case_compare_spec.rb +++ b/core/proc/case_compare_spec.rb @@ -1,16 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/call' -require_relative 'shared/call_arguments' describe "Proc#===" do - it_behaves_like :proc_call, :=== - it_behaves_like :proc_call_block_args, :=== -end - -describe "Proc#=== on a Proc created with Proc.new" do - it_behaves_like :proc_call_on_proc_new, :=== -end - -describe "Proc#=== on a Proc created with Kernel#lambda or Kernel#proc" do - it_behaves_like :proc_call_on_proc_or_lambda, :=== + it "is an alias of Proc#call" do + Proc.instance_method(:===).should == Proc.instance_method(:call) + end end diff --git a/core/proc/element_reference_spec.rb b/core/proc/element_reference_spec.rb index ea3a915a11..ac14292464 100644 --- a/core/proc/element_reference_spec.rb +++ b/core/proc/element_reference_spec.rb @@ -1,27 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/call' -require_relative 'shared/call_arguments' -require_relative 'fixtures/proc_aref' -require_relative 'fixtures/proc_aref_frozen' describe "Proc#[]" do - it_behaves_like :proc_call, :[] - it_behaves_like :proc_call_block_args, :[] -end - -describe "Proc#call on a Proc created with Proc.new" do - it_behaves_like :proc_call_on_proc_new, :call -end - -describe "Proc#call on a Proc created with Kernel#lambda or Kernel#proc" do - it_behaves_like :proc_call_on_proc_or_lambda, :call -end - -describe "Proc#[] with frozen_string_literal: true/false" do - it "doesn't duplicate frozen strings" do - ProcArefSpecs.aref.frozen?.should == false - ProcArefSpecs.aref_freeze.frozen?.should == true - ProcArefFrozenSpecs.aref.frozen?.should == true - ProcArefFrozenSpecs.aref_freeze.frozen?.should == true + it "is an alias of Proc#call" do + Proc.instance_method(:[]).should == Proc.instance_method(:call) end end diff --git a/core/proc/eql_spec.rb b/core/proc/eql_spec.rb index ad8f6749fc..1a5fb42a0e 100644 --- a/core/proc/eql_spec.rb +++ b/core/proc/eql_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/equal' describe "Proc#eql?" do - it_behaves_like :proc_equal, :eql? + it "is an alias of Proc#==" do + Proc.instance_method(:eql?).should == Proc.instance_method(:==) + end end diff --git a/core/proc/equal_value_spec.rb b/core/proc/equal_value_spec.rb index ec7f274732..92e462152e 100644 --- a/core/proc/equal_value_spec.rb +++ b/core/proc/equal_value_spec.rb @@ -1,6 +1,83 @@ require_relative '../../spec_helper' -require_relative 'shared/equal' +require_relative 'fixtures/common' describe "Proc#==" do - it_behaves_like :proc_equal, :== + it "is a public method" do + Proc.public_instance_methods(false).should.include?(:==) + end + + it "returns true if self and other are the same object" do + p = proc { :foo } + (p == p).should == true + + p = Proc.new { :foo } + (p == p).should == true + + p = -> { :foo } + (p == p).should == true + end + + it "returns true if other is a dup of the original" do + p = proc { :foo } + (p == p.dup).should == true + + p = Proc.new { :foo } + (p == p.dup).should == true + + p = -> { :foo } + (p == p.dup).should == true + end + + # identical here means the same method invocation. + it "returns false when bodies are the same but capture env is not identical" do + a = ProcSpecs.proc_for_1 + b = ProcSpecs.proc_for_1 + + (a == b).should == false + end + + it "returns false if procs are distinct but have the same body and environment" do + p = proc { :foo } + p2 = proc { :foo } + (p == p2).should == false + end + + it "returns false if lambdas are distinct but have same body and environment" do + x = -> { :foo } + x2 = -> { :foo } + (x == x2).should == false + end + + it "returns false if using comparing lambda to proc, even with the same body and env" do + p = -> { :foo } + p2 = proc { :foo } + (p == p2).should == false + + x = proc { :bar } + x2 = -> { :bar } + (x == x2).should == false + end + + it "returns false if other is not a Proc" do + p = proc { :foo } + (p == []).should == false + + p = Proc.new { :foo } + (p == Object.new).should == false + + p = -> { :foo } + (p == :foo).should == false + end + + it "returns false if self and other are both procs but have different bodies" do + p = proc { :bar } + p2 = proc { :foo } + (p == p2).should == false + end + + it "returns false if self and other are both lambdas but have different bodies" do + p = -> { :foo } + p2 = -> { :bar } + (p == p2).should == false + end end diff --git a/core/proc/fixtures/proc_aref.rb b/core/proc/fixtures/proc_aref.rb deleted file mode 100644 index 8ee355b14c..0000000000 --- a/core/proc/fixtures/proc_aref.rb +++ /dev/null @@ -1,10 +0,0 @@ -# frozen_string_literal: false -module ProcArefSpecs - def self.aref - proc {|a| a }["sometext"] - end - - def self.aref_freeze - proc {|a| a }["sometext".freeze] - end -end diff --git a/core/proc/fixtures/proc_aref_frozen.rb b/core/proc/fixtures/proc_aref_frozen.rb deleted file mode 100644 index 50a330ba4f..0000000000 --- a/core/proc/fixtures/proc_aref_frozen.rb +++ /dev/null @@ -1,10 +0,0 @@ -# frozen_string_literal: true -module ProcArefFrozenSpecs - def self.aref - proc {|a| a }["sometext"] - end - - def self.aref_freeze - proc {|a| a }["sometext".freeze] - end -end diff --git a/core/proc/fixtures/proc_call.rb b/core/proc/fixtures/proc_call.rb new file mode 100644 index 0000000000..32048f5319 --- /dev/null +++ b/core/proc/fixtures/proc_call.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: false +module ProcCallSpecs + def self.call + proc {|a| a }.call("sometext") + end + + def self.call_freeze + proc {|a| a }.call("sometext".freeze) + end +end diff --git a/core/proc/fixtures/proc_call_frozen.rb b/core/proc/fixtures/proc_call_frozen.rb new file mode 100644 index 0000000000..29ffc3c4c9 --- /dev/null +++ b/core/proc/fixtures/proc_call_frozen.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true +module ProcCallFrozenSpecs + def self.call + proc {|a| a }.call("sometext") + end + + def self.call_freeze + proc {|a| a }.call("sometext".freeze) + end +end diff --git a/core/proc/inspect_spec.rb b/core/proc/inspect_spec.rb index f53d34116f..96995ec410 100644 --- a/core/proc/inspect_spec.rb +++ b/core/proc/inspect_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/to_s' describe "Proc#inspect" do - it_behaves_like :proc_to_s, :inspect + it "is an alias of Proc#to_s" do + Proc.instance_method(:inspect).should == Proc.instance_method(:to_s) + end end diff --git a/core/proc/shared/call.rb b/core/proc/shared/call.rb deleted file mode 100644 index fae2331b68..0000000000 --- a/core/proc/shared/call.rb +++ /dev/null @@ -1,99 +0,0 @@ -require_relative '../fixtures/common' - -describe :proc_call, shared: true do - it "invokes self" do - Proc.new { "test!" }.send(@method).should == "test!" - -> { "test!" }.send(@method).should == "test!" - proc { "test!" }.send(@method).should == "test!" - end - - it "sets self's parameters to the given values" do - Proc.new { |a, b| a + b }.send(@method, 1, 2).should == 3 - Proc.new { |*args| args }.send(@method, 1, 2, 3, 4).should == [1, 2, 3, 4] - Proc.new { |_, *args| args }.send(@method, 1, 2, 3).should == [2, 3] - - -> a, b { a + b }.send(@method, 1, 2).should == 3 - -> *args { args }.send(@method, 1, 2, 3, 4).should == [1, 2, 3, 4] - -> _, *args { args }.send(@method, 1, 2, 3).should == [2, 3] - - proc { |a, b| a + b }.send(@method, 1, 2).should == 3 - proc { |*args| args }.send(@method, 1, 2, 3, 4).should == [1, 2, 3, 4] - proc { |_, *args| args }.send(@method, 1, 2, 3).should == [2, 3] - end -end - - -describe :proc_call_on_proc_new, shared: true do - it "replaces missing arguments with nil" do - Proc.new { |a, b| [a, b] }.send(@method).should == [nil, nil] - Proc.new { |a, b| [a, b] }.send(@method, 1).should == [1, nil] - end - - it "silently ignores extra arguments" do - Proc.new { |a, b| a + b }.send(@method, 1, 2, 5).should == 3 - end - - it "auto-explodes a single Array argument" do - p = Proc.new { |a, b| [a, b] } - p.send(@method, 1, 2).should == [1, 2] - p.send(@method, [1, 2]).should == [1, 2] - p.send(@method, [1, 2, 3]).should == [1, 2] - p.send(@method, [1, 2, 3], 4).should == [[1, 2, 3], 4] - end -end - -describe :proc_call_on_proc_or_lambda, shared: true do - it "ignores excess arguments when self is a proc" do - a = proc {|x| x}.send(@method, 1, 2) - a.should == 1 - - a = proc {|x| x}.send(@method, 1, 2, 3) - a.should == 1 - - a = proc {|x:| x}.send(@method, 2, x: 1) - a.should == 1 - end - - it "will call #to_ary on argument and return self if return is nil" do - argument = ProcSpecs::ToAryAsNil.new - result = proc { |x, _| x }.send(@method, argument) - result.should == argument - end - - it "substitutes nil for missing arguments when self is a proc" do - proc {|x,y| [x,y]}.send(@method).should == [nil,nil] - - a = proc {|x,y| [x, y]}.send(@method, 1) - a.should == [1,nil] - end - - it "raises an ArgumentError on excess arguments when self is a lambda" do - -> { - -> x { x }.send(@method, 1, 2) - }.should.raise(ArgumentError) - - -> { - -> x { x }.send(@method, 1, 2, 3) - }.should.raise(ArgumentError) - end - - it "raises an ArgumentError on missing arguments when self is a lambda" do - -> { - -> x { x }.send(@method) - }.should.raise(ArgumentError) - - -> { - -> x, y { [x,y] }.send(@method, 1) - }.should.raise(ArgumentError) - end - - it "treats a single Array argument as a single argument when self is a lambda" do - -> a { a }.send(@method, [1, 2]).should == [1, 2] - -> a, b { [a, b] }.send(@method, [1, 2], 3).should == [[1,2], 3] - end - - it "treats a single Array argument as a single argument when self is a proc" do - proc { |a| a }.send(@method, [1, 2]).should == [1, 2] - proc { |a, b| [a, b] }.send(@method, [1, 2], 3).should == [[1,2], 3] - end -end diff --git a/core/proc/shared/call_arguments.rb b/core/proc/shared/call_arguments.rb deleted file mode 100644 index 91ada3439e..0000000000 --- a/core/proc/shared/call_arguments.rb +++ /dev/null @@ -1,29 +0,0 @@ -describe :proc_call_block_args, shared: true do - it "can receive block arguments" do - Proc.new {|&b| b.send(@method)}.send(@method) {1 + 1}.should == 2 - -> &b { b.send(@method)}.send(@method) {1 + 1}.should == 2 - proc {|&b| b.send(@method)}.send(@method) {1 + 1}.should == 2 - end - - it "yields to the block given at declaration and not to the block argument" do - proc_creator = Object.new - def proc_creator.create - Proc.new do |&b| - yield - end - end - a_proc = proc_creator.create { 7 } - a_proc.send(@method) { 3 }.should == 7 - end - - it "can call its block argument declared with a block argument" do - proc_creator = Object.new - def proc_creator.create(method_name) - Proc.new do |&b| - yield + b.send(method_name) - end - end - a_proc = proc_creator.create(@method) { 7 } - a_proc.call { 3 }.should == 10 - end -end diff --git a/core/proc/shared/equal.rb b/core/proc/shared/equal.rb deleted file mode 100644 index 4f6f6c41be..0000000000 --- a/core/proc/shared/equal.rb +++ /dev/null @@ -1,83 +0,0 @@ -require_relative '../../../spec_helper' -require_relative '../fixtures/common' - -describe :proc_equal, shared: true do - it "is a public method" do - Proc.public_instance_methods(false).should.include?(@method) - end - - it "returns true if self and other are the same object" do - p = proc { :foo } - p.send(@method, p).should == true - - p = Proc.new { :foo } - p.send(@method, p).should == true - - p = -> { :foo } - p.send(@method, p).should == true - end - - it "returns true if other is a dup of the original" do - p = proc { :foo } - p.send(@method, p.dup).should == true - - p = Proc.new { :foo } - p.send(@method, p.dup).should == true - - p = -> { :foo } - p.send(@method, p.dup).should == true - end - - # identical here means the same method invocation. - it "returns false when bodies are the same but capture env is not identical" do - a = ProcSpecs.proc_for_1 - b = ProcSpecs.proc_for_1 - - a.send(@method, b).should == false - end - - it "returns false if procs are distinct but have the same body and environment" do - p = proc { :foo } - p2 = proc { :foo } - p.send(@method, p2).should == false - end - - it "returns false if lambdas are distinct but have same body and environment" do - x = -> { :foo } - x2 = -> { :foo } - x.send(@method, x2).should == false - end - - it "returns false if using comparing lambda to proc, even with the same body and env" do - p = -> { :foo } - p2 = proc { :foo } - p.send(@method, p2).should == false - - x = proc { :bar } - x2 = -> { :bar } - x.send(@method, x2).should == false - end - - it "returns false if other is not a Proc" do - p = proc { :foo } - p.send(@method, []).should == false - - p = Proc.new { :foo } - p.send(@method, Object.new).should == false - - p = -> { :foo } - p.send(@method, :foo).should == false - end - - it "returns false if self and other are both procs but have different bodies" do - p = proc { :bar } - p2 = proc { :foo } - p.send(@method, p2).should == false - end - - it "returns false if self and other are both lambdas but have different bodies" do - p = -> { :foo } - p2 = -> { :bar } - p.send(@method, p2).should == false - end -end diff --git a/core/proc/shared/to_s.rb b/core/proc/shared/to_s.rb deleted file mode 100644 index a52688a89f..0000000000 --- a/core/proc/shared/to_s.rb +++ /dev/null @@ -1,60 +0,0 @@ -describe :proc_to_s, shared: true do - describe "for a proc created with Proc.new" do - it "returns a description including file and line number" do - Proc.new { "hello" }.send(@method).should =~ /^#$/ - end - - it "has a binary encoding" do - Proc.new { "hello" }.send(@method).encoding.should == Encoding::BINARY - end - end - - describe "for a proc created with lambda" do - it "returns a description including '(lambda)' and including file and line number" do - -> { "hello" }.send(@method).should =~ /^#$/ - end - - it "has a binary encoding" do - -> { "hello" }.send(@method).encoding.should == Encoding::BINARY - end - end - - describe "for a proc created with proc" do - it "returns a description including file and line number" do - proc { "hello" }.send(@method).should =~ /^#$/ - end - - it "has a binary encoding" do - proc { "hello" }.send(@method).encoding.should == Encoding::BINARY - end - end - - describe "for a proc created with UnboundMethod#to_proc" do - it "returns a description including '(lambda)' and optionally including file and line number" do - def hello; end - s = method("hello").to_proc.send(@method) - if s.include? __FILE__ - s.should =~ /^#$/ - else - s.should =~ /^#$/ - end - end - - it "has a binary encoding" do - def hello; end - method("hello").to_proc.send(@method).encoding.should == Encoding::BINARY - end - end - - describe "for a proc created with Symbol#to_proc" do - it "returns a description including '(&:symbol)'" do - proc = :foobar.to_proc - proc.send(@method).should.include?('(&:foobar)') - end - - it "has a binary encoding" do - proc = :foobar.to_proc - proc.send(@method).encoding.should == Encoding::BINARY - end - end -end diff --git a/core/proc/to_s_spec.rb b/core/proc/to_s_spec.rb index 5e9c46b6b8..58a9aa76fb 100644 --- a/core/proc/to_s_spec.rb +++ b/core/proc/to_s_spec.rb @@ -1,6 +1,62 @@ require_relative '../../spec_helper' -require_relative 'shared/to_s' describe "Proc#to_s" do - it_behaves_like :proc_to_s, :to_s + describe "for a proc created with Proc.new" do + it "returns a description including file and line number" do + Proc.new { "hello" }.to_s.should =~ /^#$/ + end + + it "has a binary encoding" do + Proc.new { "hello" }.to_s.encoding.should == Encoding::BINARY + end + end + + describe "for a proc created with lambda" do + it "returns a description including '(lambda)' and including file and line number" do + -> { "hello" }.to_s.should =~ /^#$/ + end + + it "has a binary encoding" do + -> { "hello" }.to_s.encoding.should == Encoding::BINARY + end + end + + describe "for a proc created with proc" do + it "returns a description including file and line number" do + proc { "hello" }.to_s.should =~ /^#$/ + end + + it "has a binary encoding" do + proc { "hello" }.to_s.encoding.should == Encoding::BINARY + end + end + + describe "for a proc created with UnboundMethod#to_proc" do + it "returns a description including '(lambda)' and optionally including file and line number" do + def hello; end + s = method("hello").to_proc.to_s + if s.include? __FILE__ + s.should =~ /^#$/ + else + s.should =~ /^#$/ + end + end + + it "has a binary encoding" do + def hello; end + method("hello").to_proc.to_s.encoding.should == Encoding::BINARY + end + end + + describe "for a proc created with Symbol#to_proc" do + it "returns a description including '(&:symbol)'" do + proc = :foobar.to_proc + proc.to_s.should.include?('(&:foobar)') + end + + it "has a binary encoding" do + proc = :foobar.to_proc + proc.to_s.encoding.should == Encoding::BINARY + end + end end diff --git a/core/proc/yield_spec.rb b/core/proc/yield_spec.rb index 365d5b04bd..e6ee2d5eff 100644 --- a/core/proc/yield_spec.rb +++ b/core/proc/yield_spec.rb @@ -1,16 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/call' -require_relative 'shared/call_arguments' describe "Proc#yield" do - it_behaves_like :proc_call, :yield - it_behaves_like :proc_call_block_args, :yield -end - -describe "Proc#yield on a Proc created with Proc.new" do - it_behaves_like :proc_call_on_proc_new, :yield -end - -describe "Proc#yield on a Proc created with Kernel#lambda or Kernel#proc" do - it_behaves_like :proc_call_on_proc_or_lambda, :yield + it "is an alias of Proc#call" do + Proc.instance_method(:yield).should == Proc.instance_method(:call) + end end diff --git a/core/range/entries_spec.rb b/core/range/entries_spec.rb new file mode 100644 index 0000000000..29296711dc --- /dev/null +++ b/core/range/entries_spec.rb @@ -0,0 +1,7 @@ +require_relative '../../spec_helper' + +describe "Range#entries" do + it "is an alias of Range#to_a" do + Range.instance_method(:entries).should == Range.instance_method(:to_a) + end +end diff --git a/core/range/include_spec.rb b/core/range/include_spec.rb index 66a049a90d..e5cc0dc234 100644 --- a/core/range/include_spec.rb +++ b/core/range/include_spec.rb @@ -1,12 +1,96 @@ # encoding: binary require_relative '../../spec_helper' +require_relative 'fixtures/classes' require_relative 'shared/cover_and_include' -require_relative 'shared/include' -require_relative 'shared/cover' describe "Range#include?" do it_behaves_like :range_cover_and_include, :include? - it_behaves_like :range_include, :include? + + describe "on string elements" do + it "returns true if other is matched by element.succ" do + ('a'..'c').include?('b').should == true + ('a'...'c').include?('b').should == true + end + + it "returns false if other is not matched by element.succ" do + ('a'..'c').include?('bc').should == false + ('a'...'c').include?('bc').should == false + end + end + + describe "with weird succ" do + describe "when included end value" do + before :each do + @range = RangeSpecs::TenfoldSucc.new(1)..RangeSpecs::TenfoldSucc.new(99) + end + + it "returns false if other is less than first element" do + @range.include?(RangeSpecs::TenfoldSucc.new(0)).should == false + end + + it "returns true if other is equal as first element" do + @range.include?(RangeSpecs::TenfoldSucc.new(1)).should == true + end + + it "returns true if other is matched by element.succ" do + @range.include?(RangeSpecs::TenfoldSucc.new(10)).should == true + end + + it "returns false if other is not matched by element.succ" do + @range.include?(RangeSpecs::TenfoldSucc.new(2)).should == false + end + + it "returns false if other is equal as last element but not matched by element.succ" do + @range.include?(RangeSpecs::TenfoldSucc.new(99)).should == false + end + + it "returns false if other is greater than last element but matched by element.succ" do + @range.include?(RangeSpecs::TenfoldSucc.new(100)).should == false + end + end + + describe "when excluded end value" do + before :each do + @range = RangeSpecs::TenfoldSucc.new(1)...RangeSpecs::TenfoldSucc.new(99) + end + + it "returns false if other is less than first element" do + @range.include?(RangeSpecs::TenfoldSucc.new(0)).should == false + end + + it "returns true if other is equal as first element" do + @range.include?(RangeSpecs::TenfoldSucc.new(1)).should == true + end + + it "returns true if other is matched by element.succ" do + @range.include?(RangeSpecs::TenfoldSucc.new(10)).should == true + end + + it "returns false if other is not matched by element.succ" do + @range.include?(RangeSpecs::TenfoldSucc.new(2)).should == false + end + + it "returns false if other is equal as last element but not matched by element.succ" do + @range.include?(RangeSpecs::TenfoldSucc.new(99)).should == false + end + + it "returns false if other is greater than last element but matched by element.succ" do + @range.include?(RangeSpecs::TenfoldSucc.new(100)).should == false + end + end + end + + describe "with Time endpoints" do + it "uses cover? logic" do + now = Time.now + range = (now..(now + 60)) + + range.include?(now).should == true + range.include?(now - 1).should == false + range.include?(now + 60).should == true + range.include?(now + 61).should == false + end + end it "does not include U+9995 in the range U+0999..U+9999" do ("\u{999}".."\u{9999}").include?("\u{9995}").should == false diff --git a/core/range/member_spec.rb b/core/range/member_spec.rb index 78299ae9e5..98835e4cf3 100644 --- a/core/range/member_spec.rb +++ b/core/range/member_spec.rb @@ -1,10 +1,7 @@ -# encoding: binary require_relative '../../spec_helper' -require_relative 'shared/cover_and_include' -require_relative 'shared/include' -require_relative 'shared/cover' describe "Range#member?" do - it_behaves_like :range_cover_and_include, :member? - it_behaves_like :range_include, :member? + it "is an alias of Range#include?" do + Range.instance_method(:member?).should == Range.instance_method(:include?) + end end diff --git a/core/range/shared/include.rb b/core/range/shared/include.rb deleted file mode 100644 index 5f0db48008..0000000000 --- a/core/range/shared/include.rb +++ /dev/null @@ -1,91 +0,0 @@ -# encoding: binary -require_relative '../../../spec_helper' -require_relative '../fixtures/classes' - -describe :range_include, shared: true do - describe "on string elements" do - it "returns true if other is matched by element.succ" do - ('a'..'c').send(@method, 'b').should == true - ('a'...'c').send(@method, 'b').should == true - end - - it "returns false if other is not matched by element.succ" do - ('a'..'c').send(@method, 'bc').should == false - ('a'...'c').send(@method, 'bc').should == false - end - end - - describe "with weird succ" do - describe "when included end value" do - before :each do - @range = RangeSpecs::TenfoldSucc.new(1)..RangeSpecs::TenfoldSucc.new(99) - end - - it "returns false if other is less than first element" do - @range.send(@method, RangeSpecs::TenfoldSucc.new(0)).should == false - end - - it "returns true if other is equal as first element" do - @range.send(@method, RangeSpecs::TenfoldSucc.new(1)).should == true - end - - it "returns true if other is matched by element.succ" do - @range.send(@method, RangeSpecs::TenfoldSucc.new(10)).should == true - end - - it "returns false if other is not matched by element.succ" do - @range.send(@method, RangeSpecs::TenfoldSucc.new(2)).should == false - end - - it "returns false if other is equal as last element but not matched by element.succ" do - @range.send(@method, RangeSpecs::TenfoldSucc.new(99)).should == false - end - - it "returns false if other is greater than last element but matched by element.succ" do - @range.send(@method, RangeSpecs::TenfoldSucc.new(100)).should == false - end - end - - describe "when excluded end value" do - before :each do - @range = RangeSpecs::TenfoldSucc.new(1)...RangeSpecs::TenfoldSucc.new(99) - end - - it "returns false if other is less than first element" do - @range.send(@method, RangeSpecs::TenfoldSucc.new(0)).should == false - end - - it "returns true if other is equal as first element" do - @range.send(@method, RangeSpecs::TenfoldSucc.new(1)).should == true - end - - it "returns true if other is matched by element.succ" do - @range.send(@method, RangeSpecs::TenfoldSucc.new(10)).should == true - end - - it "returns false if other is not matched by element.succ" do - @range.send(@method, RangeSpecs::TenfoldSucc.new(2)).should == false - end - - it "returns false if other is equal as last element but not matched by element.succ" do - @range.send(@method, RangeSpecs::TenfoldSucc.new(99)).should == false - end - - it "returns false if other is greater than last element but matched by element.succ" do - @range.send(@method, RangeSpecs::TenfoldSucc.new(100)).should == false - end - end - end - - describe "with Time endpoints" do - it "uses cover? logic" do - now = Time.now - range = (now..(now + 60)) - - range.include?(now).should == true - range.include?(now - 1).should == false - range.include?(now + 60).should == true - range.include?(now + 61).should == false - end - end -end diff --git a/core/rational/abs_spec.rb b/core/rational/abs_spec.rb index 54099aa14d..6bb4a0fbef 100644 --- a/core/rational/abs_spec.rb +++ b/core/rational/abs_spec.rb @@ -1,6 +1,11 @@ require_relative "../../spec_helper" -require_relative 'shared/abs' describe "Rational#abs" do - it_behaves_like :rational_abs, :abs + it "returns self's absolute value" do + Rational(3, 4).abs.should == Rational(3, 4) + Rational(-3, 4).abs.should == Rational(3, 4) + Rational(3, -4).abs.should == Rational(3, 4) + + Rational(bignum_value, -bignum_value).abs.should == Rational(bignum_value, bignum_value) + end end diff --git a/core/rational/magnitude_spec.rb b/core/rational/magnitude_spec.rb index f5f667edb1..0df637df7a 100644 --- a/core/rational/magnitude_spec.rb +++ b/core/rational/magnitude_spec.rb @@ -1,6 +1,7 @@ require_relative "../../spec_helper" -require_relative 'shared/abs' -describe "Rational#abs" do - it_behaves_like :rational_abs, :magnitude +describe "Rational#magnitude" do + it "is an alias of Rational#abs" do + Rational.instance_method(:magnitude).should == Rational.instance_method(:abs) + end end diff --git a/core/rational/quo_spec.rb b/core/rational/quo_spec.rb index 907898ad34..62178f403b 100644 --- a/core/rational/quo_spec.rb +++ b/core/rational/quo_spec.rb @@ -1,25 +1,7 @@ require_relative "../../spec_helper" describe "Rational#quo" do - it "calls #coerce on the passed argument with self" do - rational = Rational(3, 4) - obj = mock("Object") - obj.should_receive(:coerce).with(rational).and_return([1, 2]) - - rational.quo(obj) - end - - it "calls #/ on the coerced Rational with the coerced Object" do - rational = Rational(3, 4) - - coerced_rational = mock("Coerced Rational") - coerced_rational.should_receive(:/).and_return(:result) - - coerced_obj = mock("Coerced Object") - - obj = mock("Object") - obj.should_receive(:coerce).and_return([coerced_rational, coerced_obj]) - - rational.quo(obj).should == :result + it "is an alias of Rational#/" do + Rational.instance_method(:quo).should == Rational.instance_method(:/) end end diff --git a/core/rational/shared/abs.rb b/core/rational/shared/abs.rb deleted file mode 100644 index 3d64bcc1a0..0000000000 --- a/core/rational/shared/abs.rb +++ /dev/null @@ -1,11 +0,0 @@ -require_relative '../../../spec_helper' - -describe :rational_abs, shared: true do - it "returns self's absolute value" do - Rational(3, 4).send(@method).should == Rational(3, 4) - Rational(-3, 4).send(@method).should == Rational(3, 4) - Rational(3, -4).send(@method).should == Rational(3, 4) - - Rational(bignum_value, -bignum_value).send(@method).should == Rational(bignum_value, bignum_value) - end -end diff --git a/core/refinement/refined_class_spec.rb b/core/refinement/refined_class_spec.rb index b532d9a773..90f8d963d8 100644 --- a/core/refinement/refined_class_spec.rb +++ b/core/refinement/refined_class_spec.rb @@ -1,5 +1,4 @@ require_relative "../../spec_helper" -require_relative 'shared/target' describe "Refinement#refined_class" do ruby_version_is ""..."3.4" do diff --git a/core/refinement/shared/target.rb b/core/refinement/shared/target.rb deleted file mode 100644 index 79557bea0b..0000000000 --- a/core/refinement/shared/target.rb +++ /dev/null @@ -1,13 +0,0 @@ -describe :refinement_target, shared: true do - it "returns the class refined by the receiver" do - refinement_int = nil - - Module.new do - refine Integer do - refinement_int = self - end - end - - refinement_int.send(@method).should == Integer - end -end diff --git a/core/refinement/target_spec.rb b/core/refinement/target_spec.rb index 8bd816aea6..eaee71e8c6 100644 --- a/core/refinement/target_spec.rb +++ b/core/refinement/target_spec.rb @@ -1,6 +1,15 @@ require_relative "../../spec_helper" -require_relative 'shared/target' describe "Refinement#target" do - it_behaves_like :refinement_target, :target + it "returns the class refined by the receiver" do + refinement_int = nil + + Module.new do + refine Integer do + refinement_int = self + end + end + + refinement_int.target.should == Integer + end end diff --git a/core/regexp/eql_spec.rb b/core/regexp/eql_spec.rb index bd5ae43eb2..5924333fbd 100644 --- a/core/regexp/eql_spec.rb +++ b/core/regexp/eql_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/equal_value' describe "Regexp#eql?" do - it_behaves_like :regexp_eql, :eql? + it "is an alias of Regexp#==" do + Regexp.instance_method(:eql?).should == Regexp.instance_method(:==) + end end diff --git a/core/regexp/equal_value_spec.rb b/core/regexp/equal_value_spec.rb index 5455a30598..ad8dc33222 100644 --- a/core/regexp/equal_value_spec.rb +++ b/core/regexp/equal_value_spec.rb @@ -1,6 +1,33 @@ require_relative '../../spec_helper' -require_relative 'shared/equal_value' describe "Regexp#==" do - it_behaves_like :regexp_eql, :== + it "is true if self and other have the same pattern" do + (/abc/ == /abc/).should == true + (/abc/ == /abd/).should == false + end + + not_supported_on :opal do + it "is true if self and other have the same character set code" do + (/abc/ == /abc/x).should == false + (/abc/x == /abc/x).should == true + (/abc/u == /abc/n).should == false + (/abc/u == /abc/u).should == true + (/abc/n == /abc/n).should == true + end + end + + it "is true if other has the same #casefold? values" do + (/abc/ == /abc/i).should == false + (/abc/i == /abc/i).should == true + end + + not_supported_on :opal do + it "is true if self does not specify /n option and other does" do + (// == //n).should == true + end + + it "is true if self specifies /n option and other does not" do + (//n == //).should == true + end + end end diff --git a/core/regexp/escape_spec.rb b/core/regexp/escape_spec.rb index 6b06ab1cbc..99e5eb71d6 100644 --- a/core/regexp/escape_spec.rb +++ b/core/regexp/escape_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/quote' describe "Regexp.escape" do - it_behaves_like :regexp_quote, :escape + it "is an alias of Regexp.quote" do + Regexp.method(:escape).should == Regexp.method(:quote) + end end diff --git a/core/regexp/quote_spec.rb b/core/regexp/quote_spec.rb index 370ab13e30..27fa0c0669 100644 --- a/core/regexp/quote_spec.rb +++ b/core/regexp/quote_spec.rb @@ -1,6 +1,43 @@ +# encoding: binary + require_relative '../../spec_helper' -require_relative 'shared/quote' describe "Regexp.quote" do - it_behaves_like :regexp_quote, :quote + it "escapes any characters with special meaning in a regular expression" do + Regexp.quote('\*?{}.+^$[]()- ').should == '\\\\\*\?\{\}\.\+\^\$\[\]\(\)\-\\ ' + Regexp.quote("\*?{}.+^$[]()- ").should == '\\*\\?\\{\\}\\.\\+\\^\\$\\[\\]\\(\\)\\-\\ ' + Regexp.quote('\n\r\f\t').should == '\\\\n\\\\r\\\\f\\\\t' + Regexp.quote("\n\r\f\t").should == '\\n\\r\\f\\t' + end + + it "works with symbols" do + Regexp.quote(:symbol).should == 'symbol' + end + + it "works with substrings" do + str = ".+[]()"[1...-1] + Regexp.quote(str).should == '\+\[\]\(' + end + + it "works for broken strings" do + Regexp.quote("a.\x85b.".dup.force_encoding("US-ASCII")).should =="a\\.\x85b\\.".dup.force_encoding("US-ASCII") + Regexp.quote("a.\x80".dup.force_encoding("UTF-8")).should == "a\\.\x80".dup.force_encoding("UTF-8") + end + + it "sets the encoding of the result to US-ASCII if there are only US-ASCII characters present in the input String" do + str = "abc".dup.force_encoding("euc-jp") + Regexp.quote(str).encoding.should == Encoding::US_ASCII + end + + it "sets the encoding of the result to the encoding of the String if any non-US-ASCII characters are present in an input String with valid encoding" do + str = "ありがとう".dup.force_encoding("utf-8") + str.valid_encoding?.should == true + Regexp.quote(str).encoding.should == Encoding::UTF_8 + end + + it "sets the encoding of the result to BINARY if any non-US-ASCII characters are present in an input String with invalid encoding" do + str = "\xff".dup.force_encoding "us-ascii" + str.valid_encoding?.should == false + Regexp.quote("\xff").encoding.should == Encoding::BINARY + end end diff --git a/core/regexp/shared/equal_value.rb b/core/regexp/shared/equal_value.rb deleted file mode 100644 index 803988de9e..0000000000 --- a/core/regexp/shared/equal_value.rb +++ /dev/null @@ -1,31 +0,0 @@ -describe :regexp_eql, shared: true do - it "is true if self and other have the same pattern" do - /abc/.send(@method, /abc/).should == true - /abc/.send(@method, /abd/).should == false - end - - not_supported_on :opal do - it "is true if self and other have the same character set code" do - /abc/.send(@method, /abc/x).should == false - /abc/x.send(@method, /abc/x).should == true - /abc/u.send(@method, /abc/n).should == false - /abc/u.send(@method, /abc/u).should == true - /abc/n.send(@method, /abc/n).should == true - end - end - - it "is true if other has the same #casefold? values" do - /abc/.send(@method, /abc/i).should == false - /abc/i.send(@method, /abc/i).should == true - end - - not_supported_on :opal do - it "is true if self does not specify /n option and other does" do - //.send(@method, //n).should == true - end - - it "is true if self specifies /n option and other does not" do - //n.send(@method, //).should == true - end - end -end diff --git a/core/regexp/shared/quote.rb b/core/regexp/shared/quote.rb deleted file mode 100644 index 083f12d78c..0000000000 --- a/core/regexp/shared/quote.rb +++ /dev/null @@ -1,41 +0,0 @@ -# encoding: binary - -describe :regexp_quote, shared: true do - it "escapes any characters with special meaning in a regular expression" do - Regexp.send(@method, '\*?{}.+^$[]()- ').should == '\\\\\*\?\{\}\.\+\^\$\[\]\(\)\-\\ ' - Regexp.send(@method, "\*?{}.+^$[]()- ").should == '\\*\\?\\{\\}\\.\\+\\^\\$\\[\\]\\(\\)\\-\\ ' - Regexp.send(@method, '\n\r\f\t').should == '\\\\n\\\\r\\\\f\\\\t' - Regexp.send(@method, "\n\r\f\t").should == '\\n\\r\\f\\t' - end - - it "works with symbols" do - Regexp.send(@method, :symbol).should == 'symbol' - end - - it "works with substrings" do - str = ".+[]()"[1...-1] - Regexp.send(@method, str).should == '\+\[\]\(' - end - - it "works for broken strings" do - Regexp.send(@method, "a.\x85b.".dup.force_encoding("US-ASCII")).should =="a\\.\x85b\\.".dup.force_encoding("US-ASCII") - Regexp.send(@method, "a.\x80".dup.force_encoding("UTF-8")).should == "a\\.\x80".dup.force_encoding("UTF-8") - end - - it "sets the encoding of the result to US-ASCII if there are only US-ASCII characters present in the input String" do - str = "abc".dup.force_encoding("euc-jp") - Regexp.send(@method, str).encoding.should == Encoding::US_ASCII - end - - it "sets the encoding of the result to the encoding of the String if any non-US-ASCII characters are present in an input String with valid encoding" do - str = "ありがとう".dup.force_encoding("utf-8") - str.valid_encoding?.should == true - Regexp.send(@method, str).encoding.should == Encoding::UTF_8 - end - - it "sets the encoding of the result to BINARY if any non-US-ASCII characters are present in an input String with invalid encoding" do - str = "\xff".dup.force_encoding "us-ascii" - str.valid_encoding?.should == false - Regexp.send(@method, "\xff").encoding.should == Encoding::BINARY - end -end diff --git a/core/set/add_spec.rb b/core/set/add_spec.rb index 1ce03b1eab..1a018b186a 100644 --- a/core/set/add_spec.rb +++ b/core/set/add_spec.rb @@ -1,8 +1,18 @@ require_relative '../../spec_helper' -require_relative 'shared/add' describe "Set#add" do - it_behaves_like :set_add, :add + before :each do + @set = Set.new + end + + it "adds the passed Object to self" do + @set.add("dog") + @set.should.include?("dog") + end + + it "returns self" do + @set.add("dog").should.equal?(@set) + end end describe "Set#add?" do diff --git a/core/set/append_spec.rb b/core/set/append_spec.rb index 82d34d9130..4f4e2351e2 100644 --- a/core/set/append_spec.rb +++ b/core/set/append_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/add' describe "Set#<<" do - it_behaves_like :set_add, :<< + it "is an alias of Set#add" do + Set.instance_method(:<<).should == Set.instance_method(:add) + end end diff --git a/core/set/case_compare_spec.rb b/core/set/case_compare_spec.rb index 3781b1b963..6fe749c79b 100644 --- a/core/set/case_compare_spec.rb +++ b/core/set/case_compare_spec.rb @@ -1,11 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/include' describe "Set#===" do - it_behaves_like :set_include, :=== - - it "is an alias for include?" do - set = Set.new - set.method(:===).should == set.method(:include?) + it "is an alias of Set#include?" do + Set.instance_method(:===).should == Set.instance_method(:include?) end end diff --git a/core/set/case_equality_spec.rb b/core/set/case_equality_spec.rb deleted file mode 100644 index 19c1fb6b9c..0000000000 --- a/core/set/case_equality_spec.rb +++ /dev/null @@ -1,6 +0,0 @@ -require_relative '../../spec_helper' -require_relative 'shared/include' - -describe "Set#===" do - it_behaves_like :set_include, :=== -end diff --git a/core/set/collect_spec.rb b/core/set/collect_spec.rb index d186f1a0d9..b78ee493d4 100644 --- a/core/set/collect_spec.rb +++ b/core/set/collect_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/collect' describe "Set#collect!" do - it_behaves_like :set_collect_bang, :collect! + it "is an alias of Set#map!" do + Set.instance_method(:collect!).should == Set.instance_method(:map!) + end end diff --git a/core/set/difference_spec.rb b/core/set/difference_spec.rb index 149f946592..22d89973a8 100644 --- a/core/set/difference_spec.rb +++ b/core/set/difference_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/difference' describe "Set#difference" do - it_behaves_like :set_difference, :difference + it "is an alias of Set#-" do + Set.instance_method(:difference).should == Set.instance_method(:-) + end end diff --git a/core/set/eql_spec.rb b/core/set/eql_spec.rb index 6862ed4eda..e7eacf2999 100644 --- a/core/set/eql_spec.rb +++ b/core/set/eql_spec.rb @@ -1,14 +1,22 @@ require_relative '../../spec_helper' describe "Set#eql?" do - it "returns true when the passed argument is a Set and contains the same elements" do - Set[].should.eql?(Set[]) - Set[1, 2, 3].should.eql?(Set[1, 2, 3]) - Set[1, 2, 3].should.eql?(Set[3, 2, 1]) - Set["a", :b, ?c].should.eql?(Set[?c, :b, "a"]) + ruby_version_is ""..."4.0" do + it "returns true when the passed argument is a Set and contains the same elements" do + Set[].should.eql?(Set[]) + Set[1, 2, 3].should.eql?(Set[1, 2, 3]) + Set[1, 2, 3].should.eql?(Set[3, 2, 1]) + Set["a", :b, ?c].should.eql?(Set[?c, :b, "a"]) - Set[1, 2, 3].should_not.eql?(Set[1.0, 2, 3]) - Set[1, 2, 3].should_not.eql?(Set[2, 3]) - Set[1, 2, 3].should_not.eql?(Set[]) + Set[1, 2, 3].should_not.eql?(Set[1.0, 2, 3]) + Set[1, 2, 3].should_not.eql?(Set[2, 3]) + Set[1, 2, 3].should_not.eql?(Set[]) + end + end + + ruby_version_is "4.0" do + it "is an alias of Set#==" do + Set.instance_method(:eql?).should == Set.instance_method(:==) + end end end diff --git a/core/set/filter_spec.rb b/core/set/filter_spec.rb index 779254ad68..d0c294c27f 100644 --- a/core/set/filter_spec.rb +++ b/core/set/filter_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/select' describe "Set#filter!" do - it_behaves_like :set_select_bang, :filter! + it "is an alias of Set#select!" do + Set.instance_method(:filter!).should == Set.instance_method(:select!) + end end diff --git a/core/set/gt_spec.rb b/core/set/gt_spec.rb new file mode 100644 index 0000000000..8a7e421e40 --- /dev/null +++ b/core/set/gt_spec.rb @@ -0,0 +1,7 @@ +require_relative '../../spec_helper' + +describe "Set#>" do + it "is an alias of Set#proper_superset?" do + Set.instance_method(:>).should == Set.instance_method(:proper_superset?) + end +end diff --git a/core/set/gte_spec.rb b/core/set/gte_spec.rb new file mode 100644 index 0000000000..e98c3cb1e2 --- /dev/null +++ b/core/set/gte_spec.rb @@ -0,0 +1,7 @@ +require_relative '../../spec_helper' + +describe "Set#>=" do + it "is an alias of Set#superset?" do + Set.instance_method(:>=).should == Set.instance_method(:superset?) + end +end diff --git a/core/set/include_spec.rb b/core/set/include_spec.rb index dd33bbc3bd..92a6ca04e6 100644 --- a/core/set/include_spec.rb +++ b/core/set/include_spec.rb @@ -1,6 +1,31 @@ require_relative '../../spec_helper' -require_relative 'shared/include' describe "Set#include?" do - it_behaves_like :set_include, :include? + it "returns true when self contains the passed Object" do + set = Set[:a, :b, :c] + set.include?(:a).should == true + set.include?(:e).should == false + end + + describe "member equality" do + it "is checked using both #hash and #eql?" do + obj = Object.new + obj_another = Object.new + + def obj.hash; 42 end + def obj_another.hash; 42 end + def obj_another.eql?(o) hash == o.hash end + + set = Set["a", "b", "c", obj] + set.include?(obj_another).should == true + end + + it "is not checked using #==" do + obj = Object.new + set = Set["a", "b", "c"] + + obj.should_not_receive(:==) + set.include?(obj) + end + end end diff --git a/core/set/inspect_spec.rb b/core/set/inspect_spec.rb index 0dcce83eb6..45aeed280e 100644 --- a/core/set/inspect_spec.rb +++ b/core/set/inspect_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/inspect' describe "Set#inspect" do - it_behaves_like :set_inspect, :inspect + it "is an alias of Set#to_s" do + Set.instance_method(:inspect).should == Set.instance_method(:to_s) + end end diff --git a/core/set/intersection_spec.rb b/core/set/intersection_spec.rb index 136b886775..c14e1f62ad 100644 --- a/core/set/intersection_spec.rb +++ b/core/set/intersection_spec.rb @@ -1,10 +1,23 @@ require_relative '../../spec_helper' -require_relative 'shared/intersection' describe "Set#intersection" do - it_behaves_like :set_intersection, :intersection + it "is an alias of Set#&" do + Set.instance_method(:intersection).should == Set.instance_method(:&) + end end describe "Set#&" do - it_behaves_like :set_intersection, :& + before :each do + @set = Set[:a, :b, :c] + end + + it "returns a new Set containing only elements shared by self and the passed Enumerable" do + (@set & Set[:b, :c, :d, :e]).should == Set[:b, :c] + (@set & [:b, :c, :d]).should == Set[:b, :c] + end + + it "raises an ArgumentError when passed a non-Enumerable" do + -> { @set & 1 }.should.raise(ArgumentError) + -> { @set & Object.new }.should.raise(ArgumentError) + end end diff --git a/core/set/length_spec.rb b/core/set/length_spec.rb index 6bb697b4ca..9b0d3622b8 100644 --- a/core/set/length_spec.rb +++ b/core/set/length_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/length' describe "Set#length" do - it_behaves_like :set_length, :length + it "is an alias of Set#size" do + Set.instance_method(:length).should == Set.instance_method(:size) + end end diff --git a/core/set/lt_spec.rb b/core/set/lt_spec.rb new file mode 100644 index 0000000000..0f5bc9c642 --- /dev/null +++ b/core/set/lt_spec.rb @@ -0,0 +1,7 @@ +require_relative '../../spec_helper' + +describe "Set#<" do + it "is an alias of Set#proper_subset?" do + Set.instance_method(:<).should == Set.instance_method(:proper_subset?) + end +end diff --git a/core/set/lte_spec.rb b/core/set/lte_spec.rb new file mode 100644 index 0000000000..291d582240 --- /dev/null +++ b/core/set/lte_spec.rb @@ -0,0 +1,7 @@ +require_relative '../../spec_helper' + +describe "Set#<=" do + it "is an alias of Set#subset?" do + Set.instance_method(:<=).should == Set.instance_method(:subset?) + end +end diff --git a/core/set/map_spec.rb b/core/set/map_spec.rb index 996191b0a8..fd04a8bde1 100644 --- a/core/set/map_spec.rb +++ b/core/set/map_spec.rb @@ -1,6 +1,22 @@ require_relative '../../spec_helper' -require_relative 'shared/collect' describe "Set#map!" do - it_behaves_like :set_collect_bang, :map! + before :each do + @set = Set[1, 2, 3, 4, 5] + end + + it "yields each Object in self" do + res = [] + @set.map! { |x| res << x } + res.sort.should == [1, 2, 3, 4, 5].sort + end + + it "returns self" do + @set.map! { |x| x }.should.equal?(@set) + end + + it "replaces self with the return values of the block" do + @set.map! { |x| x * 2 } + @set.should == Set[2, 4, 6, 8, 10] + end end diff --git a/core/set/member_spec.rb b/core/set/member_spec.rb index 5c82e8f826..a36308eec7 100644 --- a/core/set/member_spec.rb +++ b/core/set/member_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/include' describe "Set#member?" do - it_behaves_like :set_include, :member? + it "is an alias of Set#include?" do + Set.instance_method(:member?).should == Set.instance_method(:include?) + end end diff --git a/core/set/minus_spec.rb b/core/set/minus_spec.rb index 72f98f985e..8574708559 100644 --- a/core/set/minus_spec.rb +++ b/core/set/minus_spec.rb @@ -1,6 +1,17 @@ require_relative '../../spec_helper' -require_relative 'shared/difference' describe "Set#-" do - it_behaves_like :set_difference, :- + before :each do + @set = Set[:a, :b, :c] + end + + it "returns a new Set containing self's elements excluding the elements in the passed Enumerable" do + (@set - Set[:a, :b]).should == Set[:c] + (@set - [:b, :c]).should == Set[:a] + end + + it "raises an ArgumentError when passed a non-Enumerable" do + -> { @set - 1 }.should.raise(ArgumentError) + -> { @set - Object.new }.should.raise(ArgumentError) + end end diff --git a/core/set/plus_spec.rb b/core/set/plus_spec.rb index 7e44ff0b7e..839f77fc39 100644 --- a/core/set/plus_spec.rb +++ b/core/set/plus_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/union' describe "Set#+" do - it_behaves_like :set_union, :+ + it "is an alias of Set#|" do + Set.instance_method(:+).should == Set.instance_method(:|) + end end diff --git a/core/set/select_spec.rb b/core/set/select_spec.rb index b458ffacaa..619194605b 100644 --- a/core/set/select_spec.rb +++ b/core/set/select_spec.rb @@ -1,6 +1,41 @@ require_relative '../../spec_helper' -require_relative 'shared/select' describe "Set#select!" do - it_behaves_like :set_select_bang, :select! + before :each do + @set = Set["one", "two", "three"] + end + + it "yields every element of self" do + ret = [] + @set.select! { |x| ret << x } + ret.sort.should == ["one", "two", "three"].sort + end + + it "keeps every element from self for which the passed block returns true" do + @set.select! { |x| x.size != 3 } + @set.size.should.eql?(1) + + @set.should_not.include?("one") + @set.should_not.include?("two") + @set.should.include?("three") + end + + it "returns self when self was modified" do + @set.select! { false }.should.equal?(@set) + end + + it "returns nil when self was not modified" do + @set.select! { true }.should == nil + end + + it "returns an Enumerator when passed no block" do + enum = @set.select! + enum.should.instance_of?(Enumerator) + + enum.each { |x| x.size != 3 } + + @set.should_not.include?("one") + @set.should_not.include?("two") + @set.should.include?("three") + end end diff --git a/core/set/shared/add.rb b/core/set/shared/add.rb deleted file mode 100644 index 8d6d83434f..0000000000 --- a/core/set/shared/add.rb +++ /dev/null @@ -1,14 +0,0 @@ -describe :set_add, shared: true do - before :each do - @set = Set.new - end - - it "adds the passed Object to self" do - @set.send(@method, "dog") - @set.should.include?("dog") - end - - it "returns self" do - @set.send(@method, "dog").should.equal?(@set) - end -end diff --git a/core/set/shared/collect.rb b/core/set/shared/collect.rb deleted file mode 100644 index ad5c5afa59..0000000000 --- a/core/set/shared/collect.rb +++ /dev/null @@ -1,20 +0,0 @@ -describe :set_collect_bang, shared: true do - before :each do - @set = Set[1, 2, 3, 4, 5] - end - - it "yields each Object in self" do - res = [] - @set.send(@method) { |x| res << x } - res.sort.should == [1, 2, 3, 4, 5].sort - end - - it "returns self" do - @set.send(@method) { |x| x }.should.equal?(@set) - end - - it "replaces self with the return values of the block" do - @set.send(@method) { |x| x * 2 } - @set.should == Set[2, 4, 6, 8, 10] - end -end diff --git a/core/set/shared/difference.rb b/core/set/shared/difference.rb deleted file mode 100644 index 8a17056a82..0000000000 --- a/core/set/shared/difference.rb +++ /dev/null @@ -1,15 +0,0 @@ -describe :set_difference, shared: true do - before :each do - @set = Set[:a, :b, :c] - end - - it "returns a new Set containing self's elements excluding the elements in the passed Enumerable" do - @set.send(@method, Set[:a, :b]).should == Set[:c] - @set.send(@method, [:b, :c]).should == Set[:a] - end - - it "raises an ArgumentError when passed a non-Enumerable" do - -> { @set.send(@method, 1) }.should.raise(ArgumentError) - -> { @set.send(@method, Object.new) }.should.raise(ArgumentError) - end -end diff --git a/core/set/shared/include.rb b/core/set/shared/include.rb deleted file mode 100644 index 82755ccf59..0000000000 --- a/core/set/shared/include.rb +++ /dev/null @@ -1,29 +0,0 @@ -describe :set_include, shared: true do - it "returns true when self contains the passed Object" do - set = Set[:a, :b, :c] - set.send(@method, :a).should == true - set.send(@method, :e).should == false - end - - describe "member equality" do - it "is checked using both #hash and #eql?" do - obj = Object.new - obj_another = Object.new - - def obj.hash; 42 end - def obj_another.hash; 42 end - def obj_another.eql?(o) hash == o.hash end - - set = Set["a", "b", "c", obj] - set.send(@method, obj_another).should == true - end - - it "is not checked using #==" do - obj = Object.new - set = Set["a", "b", "c"] - - obj.should_not_receive(:==) - set.send(@method, obj) - end - end -end diff --git a/core/set/shared/inspect.rb b/core/set/shared/inspect.rb deleted file mode 100644 index 31bd8accfd..0000000000 --- a/core/set/shared/inspect.rb +++ /dev/null @@ -1,45 +0,0 @@ -describe :set_inspect, shared: true do - it "returns a String representation of self" do - Set[].send(@method).should.is_a?(String) - Set[nil, false, true].send(@method).should.is_a?(String) - Set[1, 2, 3].send(@method).should.is_a?(String) - Set["1", "2", "3"].send(@method).should.is_a?(String) - Set[:a, "b", Set[?c]].send(@method).should.is_a?(String) - end - - ruby_version_is "4.0" do - it "does include the elements of the set" do - Set["1"].send(@method).should == 'Set["1"]' - end - end - - ruby_version_is ""..."4.0" do - it "does include the elements of the set" do - Set["1"].send(@method).should == '#' - end - end - - it "puts spaces between the elements" do - Set["1", "2"].send(@method).should.include?('", "') - end - - ruby_version_is "4.0" do - it "correctly handles cyclic-references" do - set1 = Set[] - set2 = Set[set1] - set1 << set2 - set1.send(@method).should.is_a?(String) - set1.send(@method).should.include?("Set[...]") - end - end - - ruby_version_is ""..."4.0" do - it "correctly handles cyclic-references" do - set1 = Set[] - set2 = Set[set1] - set1 << set2 - set1.send(@method).should.is_a?(String) - set1.send(@method).should.include?("#") - end - end -end diff --git a/core/set/shared/intersection.rb b/core/set/shared/intersection.rb deleted file mode 100644 index 978a4924ef..0000000000 --- a/core/set/shared/intersection.rb +++ /dev/null @@ -1,15 +0,0 @@ -describe :set_intersection, shared: true do - before :each do - @set = Set[:a, :b, :c] - end - - it "returns a new Set containing only elements shared by self and the passed Enumerable" do - @set.send(@method, Set[:b, :c, :d, :e]).should == Set[:b, :c] - @set.send(@method, [:b, :c, :d]).should == Set[:b, :c] - end - - it "raises an ArgumentError when passed a non-Enumerable" do - -> { @set.send(@method, 1) }.should.raise(ArgumentError) - -> { @set.send(@method, Object.new) }.should.raise(ArgumentError) - end -end diff --git a/core/set/shared/length.rb b/core/set/shared/length.rb deleted file mode 100644 index a8fcee9f39..0000000000 --- a/core/set/shared/length.rb +++ /dev/null @@ -1,6 +0,0 @@ -describe :set_length, shared: true do - it "returns the number of elements in the set" do - set = Set[:a, :b, :c] - set.send(@method).should == 3 - end -end diff --git a/core/set/shared/select.rb b/core/set/shared/select.rb deleted file mode 100644 index 0d4a53fffd..0000000000 --- a/core/set/shared/select.rb +++ /dev/null @@ -1,41 +0,0 @@ -require_relative '../../../spec_helper' - -describe :set_select_bang, shared: true do - before :each do - @set = Set["one", "two", "three"] - end - - it "yields every element of self" do - ret = [] - @set.send(@method) { |x| ret << x } - ret.sort.should == ["one", "two", "three"].sort - end - - it "keeps every element from self for which the passed block returns true" do - @set.send(@method) { |x| x.size != 3 } - @set.size.should.eql?(1) - - @set.should_not.include?("one") - @set.should_not.include?("two") - @set.should.include?("three") - end - - it "returns self when self was modified" do - @set.send(@method) { false }.should.equal?(@set) - end - - it "returns nil when self was not modified" do - @set.send(@method) { true }.should == nil - end - - it "returns an Enumerator when passed no block" do - enum = @set.send(@method) - enum.should.instance_of?(Enumerator) - - enum.each { |x| x.size != 3 } - - @set.should_not.include?("one") - @set.should_not.include?("two") - @set.should.include?("three") - end -end diff --git a/core/set/shared/union.rb b/core/set/shared/union.rb deleted file mode 100644 index dddf1716e5..0000000000 --- a/core/set/shared/union.rb +++ /dev/null @@ -1,15 +0,0 @@ -describe :set_union, shared: true do - before :each do - @set = Set[:a, :b, :c] - end - - it "returns a new Set containing all elements of self and the passed Enumerable" do - @set.send(@method, Set[:b, :d, :e]).should == Set[:a, :b, :c, :d, :e] - @set.send(@method, [:b, :e]).should == Set[:a, :b, :c, :e] - end - - it "raises an ArgumentError when passed a non-Enumerable" do - -> { @set.send(@method, 1) }.should.raise(ArgumentError) - -> { @set.send(@method, Object.new) }.should.raise(ArgumentError) - end -end diff --git a/core/set/size_spec.rb b/core/set/size_spec.rb index 4ae22c5f0a..c57272a235 100644 --- a/core/set/size_spec.rb +++ b/core/set/size_spec.rb @@ -1,6 +1,8 @@ require_relative '../../spec_helper' -require_relative 'shared/length' describe "Set#size" do - it_behaves_like :set_length, :size + it "returns the number of elements in the set" do + set = Set[:a, :b, :c] + set.size.should == 3 + end end diff --git a/core/set/to_s_spec.rb b/core/set/to_s_spec.rb index 55b8bfd9b2..7f768bdcbf 100644 --- a/core/set/to_s_spec.rb +++ b/core/set/to_s_spec.rb @@ -1,11 +1,47 @@ require_relative "../../spec_helper" -require_relative 'shared/inspect' describe "Set#to_s" do - it_behaves_like :set_inspect, :to_s + it "returns a String representation of self" do + Set[].to_s.should.is_a?(String) + Set[nil, false, true].to_s.should.is_a?(String) + Set[1, 2, 3].to_s.should.is_a?(String) + Set["1", "2", "3"].to_s.should.is_a?(String) + Set[:a, "b", Set[?c]].to_s.should.is_a?(String) + end + + ruby_version_is "4.0" do + it "does include the elements of the set" do + Set["1"].to_s.should == 'Set["1"]' + end + end + + ruby_version_is ""..."4.0" do + it "does include the elements of the set" do + Set["1"].to_s.should == '#' + end + end + + it "puts spaces between the elements" do + Set["1", "2"].to_s.should.include?('", "') + end + + ruby_version_is "4.0" do + it "correctly handles cyclic-references" do + set1 = Set[] + set2 = Set[set1] + set1 << set2 + set1.to_s.should.is_a?(String) + set1.to_s.should.include?("Set[...]") + end + end - it "is an alias of inspect" do - set = Set.new - set.method(:to_s).should == set.method(:inspect) + ruby_version_is ""..."4.0" do + it "correctly handles cyclic-references" do + set1 = Set[] + set2 = Set[set1] + set1 << set2 + set1.to_s.should.is_a?(String) + set1.to_s.should.include?("#") + end end end diff --git a/core/set/union_spec.rb b/core/set/union_spec.rb index 3e77022d4b..206535aae2 100644 --- a/core/set/union_spec.rb +++ b/core/set/union_spec.rb @@ -1,10 +1,23 @@ require_relative '../../spec_helper' -require_relative 'shared/union' describe "Set#union" do - it_behaves_like :set_union, :union + it "is an alias of Set#|" do + Set.instance_method(:union).should == Set.instance_method(:|) + end end describe "Set#|" do - it_behaves_like :set_union, :| + before :each do + @set = Set[:a, :b, :c] + end + + it "returns a new Set containing all elements of self and the passed Enumerable" do + (@set | Set[:b, :d, :e]).should == Set[:a, :b, :c, :d, :e] + (@set | [:b, :e]).should == Set[:a, :b, :c, :e] + end + + it "raises an ArgumentError when passed a non-Enumerable" do + -> { @set | 1 }.should.raise(ArgumentError) + -> { @set | Object.new }.should.raise(ArgumentError) + end end diff --git a/core/string/case_compare_spec.rb b/core/string/case_compare_spec.rb index b83d1adb91..f98ec003be 100644 --- a/core/string/case_compare_spec.rb +++ b/core/string/case_compare_spec.rb @@ -1,8 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/eql' -require_relative 'shared/equal_value' describe "String#===" do - it_behaves_like :string_eql_value, :=== - it_behaves_like :string_equal_value, :=== + it "is an alias of String#==" do + String.instance_method(:===).should == String.instance_method(:==) + end end diff --git a/core/string/codepoints_spec.rb b/core/string/codepoints_spec.rb index 51bd57d127..4434eb66a5 100644 --- a/core/string/codepoints_spec.rb +++ b/core/string/codepoints_spec.rb @@ -1,7 +1,6 @@ # encoding: binary require_relative '../../spec_helper' require_relative 'shared/codepoints' -require_relative 'shared/each_codepoint_without_block' describe "String#codepoints" do it_behaves_like :string_codepoints, :codepoints diff --git a/core/string/dedup_spec.rb b/core/string/dedup_spec.rb index 2b31d80708..940f07668e 100644 --- a/core/string/dedup_spec.rb +++ b/core/string/dedup_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/dedup' describe 'String#dedup' do - it_behaves_like :string_dedup, :dedup + it "is an alias of String#-@" do + String.instance_method(:dedup).should == String.instance_method(:-@) + end end diff --git a/core/string/each_codepoint_spec.rb b/core/string/each_codepoint_spec.rb index c11cb1beae..08d4292371 100644 --- a/core/string/each_codepoint_spec.rb +++ b/core/string/each_codepoint_spec.rb @@ -1,8 +1,38 @@ +# encoding: binary require_relative '../../spec_helper' require_relative 'shared/codepoints' -require_relative 'shared/each_codepoint_without_block' describe "String#each_codepoint" do it_behaves_like :string_codepoints, :each_codepoint - it_behaves_like :string_each_codepoint_without_block, :each_codepoint + + describe "when no block is given" do + it "returns an Enumerator" do + "".each_codepoint.should.instance_of?(Enumerator) + end + + it "returns an Enumerator even when self has an invalid encoding" do + s = "\xDF".dup.force_encoding(Encoding::UTF_8) + s.valid_encoding?.should == false + s.each_codepoint.should.instance_of?(Enumerator) + end + + describe "returned Enumerator" do + describe "size" do + it "should return the size of the string" do + str = "hello" + str.each_codepoint.size.should == str.size + str = "ola" + str.each_codepoint.size.should == str.size + str = "\303\207\342\210\202\303\251\306\222g" + str.each_codepoint.size.should == str.size + end + + it "should return the size of the string even when the string has an invalid encoding" do + s = "\xDF".dup.force_encoding(Encoding::UTF_8) + s.valid_encoding?.should == false + s.each_codepoint.size.should == 1 + end + end + end + end end diff --git a/core/string/equal_value_spec.rb b/core/string/equal_value_spec.rb index b9c9c372f8..e8b706c524 100644 --- a/core/string/equal_value_spec.rb +++ b/core/string/equal_value_spec.rb @@ -1,8 +1,30 @@ require_relative '../../spec_helper' require_relative 'shared/eql' -require_relative 'shared/equal_value' describe "String#==" do it_behaves_like :string_eql_value, :== - it_behaves_like :string_equal_value, :== + + it "returns false if obj does not respond to to_str" do + ('hello' == 5).should == false + not_supported_on :opal do + ('hello' == :hello).should == false + end + ('hello' == mock('x')).should == false + end + + it "returns obj == self if obj responds to to_str" do + obj = Object.new + + # String#== merely checks if #to_str is defined. It does + # not call it. + obj.stub!(:to_str) + + obj.should_receive(:==).and_return(true) + + ('hello' == obj).should == true + end + + it "is not fooled by NUL characters" do + ("abc\0def" == "abc\0xyz").should == false + end end diff --git a/core/string/intern_spec.rb b/core/string/intern_spec.rb index cd7dad4359..af85e56dba 100644 --- a/core/string/intern_spec.rb +++ b/core/string/intern_spec.rb @@ -1,7 +1,7 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' -require_relative 'shared/to_sym' describe "String#intern" do - it_behaves_like :string_to_sym, :intern + it "is an alias of String#to_sym" do + String.instance_method(:intern).should == String.instance_method(:to_sym) + end end diff --git a/core/string/length_spec.rb b/core/string/length_spec.rb index 98cee1f03d..a723babdbc 100644 --- a/core/string/length_spec.rb +++ b/core/string/length_spec.rb @@ -1,7 +1,56 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -require_relative 'shared/length' describe "String#length" do - it_behaves_like :string_length, :length + it "returns the length of self" do + "".length.should == 0 + "\x00".length.should == 1 + "one".length.should == 3 + "two".length.should == 3 + "three".length.should == 5 + "four".length.should == 4 + end + + it "returns the length of a string in different encodings" do + utf8_str = 'こにちわ' * 100 + utf8_str.length.should == 400 + utf8_str.encode(Encoding::UTF_32BE).length.should == 400 + utf8_str.encode(Encoding::SHIFT_JIS).length.should == 400 + end + + it "returns the length of the new self after encoding is changed" do + str = +'こにちわ' + str.length + + str.force_encoding('BINARY').length.should == 12 + end + + it "returns the correct length after force_encoding(BINARY)" do + utf8 = "あ" + ascii = "a" + concat = utf8 + ascii + + concat.encoding.should == Encoding::UTF_8 + concat.bytesize.should == 4 + + concat.length.should == 2 + concat.force_encoding(Encoding::ASCII_8BIT) + concat.length.should == 4 + end + + it "adds 1 for every invalid byte in UTF-8" do + "\xF4\x90\x80\x80".length.should == 4 + "a\xF4\x90\x80\x80b".length.should == 6 + "é\xF4\x90\x80\x80è".length.should == 6 + end + + it "adds 1 (and not 2) for a incomplete surrogate in UTF-16" do + "\x00\xd8".dup.force_encoding("UTF-16LE").length.should == 1 + "\xd8\x00".dup.force_encoding("UTF-16BE").length.should == 1 + end + + it "adds 1 for a broken sequence in UTF-32" do + "\x04\x03\x02\x01".dup.force_encoding("UTF-32LE").length.should == 1 + "\x01\x02\x03\x04".dup.force_encoding("UTF-32BE").length.should == 1 + end end diff --git a/core/string/next_spec.rb b/core/string/next_spec.rb index fcd3e5ef90..2ab121a909 100644 --- a/core/string/next_spec.rb +++ b/core/string/next_spec.rb @@ -1,11 +1,13 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' -require_relative 'shared/succ' describe "String#next" do - it_behaves_like :string_succ, :next + it "is an alias of String#succ" do + String.instance_method(:next).should == String.instance_method(:succ) + end end describe "String#next!" do - it_behaves_like :string_succ_bang, :"next!" + it "is an alias of String#succ!" do + String.instance_method(:next!).should == String.instance_method(:succ!) + end end diff --git a/core/string/shared/dedup.rb b/core/string/shared/dedup.rb deleted file mode 100644 index 59506c2901..0000000000 --- a/core/string/shared/dedup.rb +++ /dev/null @@ -1,51 +0,0 @@ -# frozen_string_literal: false -describe :string_dedup, shared: true do - it 'returns self if the String is frozen' do - input = 'foo'.freeze - output = input.send(@method) - - output.should.equal?(input) - output.should.frozen? - end - - it 'returns a frozen copy if the String is not frozen' do - input = 'foo' - output = input.send(@method) - - output.should.frozen? - output.should_not.equal?(input) - output.should == 'foo' - end - - it "returns the same object for equal unfrozen strings" do - origin = "this is a string" - dynamic = %w(this is a string).join(' ') - - origin.should_not.equal?(dynamic) - origin.send(@method).should.equal?(dynamic.send(@method)) - end - - it "returns the same object when it's called on the same String literal" do - "unfrozen string".send(@method).should.equal?("unfrozen string".send(@method)) - "unfrozen string".send(@method).should_not.equal?("another unfrozen string".send(@method)) - end - - it "deduplicates frozen strings" do - dynamic = %w(this string is frozen).join(' ').freeze - - dynamic.should_not.equal?("this string is frozen".freeze) - - dynamic.send(@method).should.equal?("this string is frozen".freeze) - dynamic.send(@method).should.equal?("this string is frozen".send(@method).freeze) - end - - it "does not deduplicate a frozen string when it has instance variables" do - dynamic = %w(this string is frozen).join(' ') - dynamic.instance_variable_set(:@a, 1) - dynamic.freeze - - dynamic.send(@method).should_not.equal?("this string is frozen".freeze) - dynamic.send(@method).should_not.equal?("this string is frozen".send(@method).freeze) - dynamic.send(@method).should.equal?(dynamic) - end -end diff --git a/core/string/shared/each_codepoint_without_block.rb b/core/string/shared/each_codepoint_without_block.rb deleted file mode 100644 index 60d603954c..0000000000 --- a/core/string/shared/each_codepoint_without_block.rb +++ /dev/null @@ -1,33 +0,0 @@ -# encoding: binary -describe :string_each_codepoint_without_block, shared: true do - describe "when no block is given" do - it "returns an Enumerator" do - "".send(@method).should.instance_of?(Enumerator) - end - - it "returns an Enumerator even when self has an invalid encoding" do - s = "\xDF".dup.force_encoding(Encoding::UTF_8) - s.valid_encoding?.should == false - s.send(@method).should.instance_of?(Enumerator) - end - - describe "returned Enumerator" do - describe "size" do - it "should return the size of the string" do - str = "hello" - str.send(@method).size.should == str.size - str = "ola" - str.send(@method).size.should == str.size - str = "\303\207\342\210\202\303\251\306\222g" - str.send(@method).size.should == str.size - end - - it "should return the size of the string even when the string has an invalid encoding" do - s = "\xDF".dup.force_encoding(Encoding::UTF_8) - s.valid_encoding?.should == false - s.send(@method).size.should == 1 - end - end - end - end -end diff --git a/core/string/shared/equal_value.rb b/core/string/shared/equal_value.rb deleted file mode 100644 index dfc5c7cd29..0000000000 --- a/core/string/shared/equal_value.rb +++ /dev/null @@ -1,29 +0,0 @@ -require_relative '../../../spec_helper' -require_relative '../fixtures/classes' - -describe :string_equal_value, shared: true do - it "returns false if obj does not respond to to_str" do - 'hello'.send(@method, 5).should == false - not_supported_on :opal do - 'hello'.send(@method, :hello).should == false - end - 'hello'.send(@method, mock('x')).should == false - end - - it "returns obj == self if obj responds to to_str" do - obj = Object.new - - # String#== merely checks if #to_str is defined. It does - # not call it. - obj.stub!(:to_str) - - # Don't use @method for :== in `obj.should_receive(:==)` - obj.should_receive(:==).and_return(true) - - 'hello'.send(@method, obj).should == true - end - - it "is not fooled by NUL characters" do - "abc\0def".send(@method, "abc\0xyz").should == false - end -end diff --git a/core/string/shared/length.rb b/core/string/shared/length.rb deleted file mode 100644 index ae572ba755..0000000000 --- a/core/string/shared/length.rb +++ /dev/null @@ -1,55 +0,0 @@ -# encoding: utf-8 - -describe :string_length, shared: true do - it "returns the length of self" do - "".send(@method).should == 0 - "\x00".send(@method).should == 1 - "one".send(@method).should == 3 - "two".send(@method).should == 3 - "three".send(@method).should == 5 - "four".send(@method).should == 4 - end - - it "returns the length of a string in different encodings" do - utf8_str = 'こにちわ' * 100 - utf8_str.send(@method).should == 400 - utf8_str.encode(Encoding::UTF_32BE).send(@method).should == 400 - utf8_str.encode(Encoding::SHIFT_JIS).send(@method).should == 400 - end - - it "returns the length of the new self after encoding is changed" do - str = +'こにちわ' - str.send(@method) - - str.force_encoding('BINARY').send(@method).should == 12 - end - - it "returns the correct length after force_encoding(BINARY)" do - utf8 = "あ" - ascii = "a" - concat = utf8 + ascii - - concat.encoding.should == Encoding::UTF_8 - concat.bytesize.should == 4 - - concat.send(@method).should == 2 - concat.force_encoding(Encoding::ASCII_8BIT) - concat.send(@method).should == 4 - end - - it "adds 1 for every invalid byte in UTF-8" do - "\xF4\x90\x80\x80".send(@method).should == 4 - "a\xF4\x90\x80\x80b".send(@method).should == 6 - "é\xF4\x90\x80\x80è".send(@method).should == 6 - end - - it "adds 1 (and not 2) for a incomplete surrogate in UTF-16" do - "\x00\xd8".dup.force_encoding("UTF-16LE").send(@method).should == 1 - "\xd8\x00".dup.force_encoding("UTF-16BE").send(@method).should == 1 - end - - it "adds 1 for a broken sequence in UTF-32" do - "\x04\x03\x02\x01".dup.force_encoding("UTF-32LE").send(@method).should == 1 - "\x01\x02\x03\x04".dup.force_encoding("UTF-32BE").send(@method).should == 1 - end -end diff --git a/core/string/shared/succ.rb b/core/string/shared/succ.rb deleted file mode 100644 index 8f1d327741..0000000000 --- a/core/string/shared/succ.rb +++ /dev/null @@ -1,87 +0,0 @@ -# encoding: binary -describe :string_succ, shared: true do - it "returns an empty string for empty strings" do - "".send(@method).should == "" - end - - it "returns the successor by increasing the rightmost alphanumeric (digit => digit, letter => letter with same case)" do - "abcd".send(@method).should == "abce" - "THX1138".send(@method).should == "THX1139" - - "<>".send(@method).should == "<>" - "==A??".send(@method).should == "==B??" - end - - it "increases non-alphanumerics (via ascii rules) if there are no alphanumerics" do - "***".send(@method).should == "**+" - "**`".send(@method).should == "**a" - end - - it "increases the next best alphanumeric (jumping over non-alphanumerics) if there is a carry" do - "dz".send(@method).should == "ea" - "HZ".send(@method).should == "IA" - "49".send(@method).should == "50" - - "izz".send(@method).should == "jaa" - "IZZ".send(@method).should == "JAA" - "699".send(@method).should == "700" - - "6Z99z99Z".send(@method).should == "7A00a00A" - - "1999zzz".send(@method).should == "2000aaa" - "NZ/[]ZZZ9999".send(@method).should == "OA/[]AAA0000" - end - - it "increases the next best character if there is a carry for non-alphanumerics" do - "(\xFF".send(@method).should == ")\x00" - "`\xFF".send(@method).should == "a\x00" - "<\xFF\xFF".send(@method).should == "=\x00\x00" - end - - it "adds an additional character (just left to the last increased one) if there is a carry and no character left to increase" do - "z".send(@method).should == "aa" - "Z".send(@method).should == "AA" - "9".send(@method).should == "10" - - "zz".send(@method).should == "aaa" - "ZZ".send(@method).should == "AAA" - "99".send(@method).should == "100" - - "9Z99z99Z".send(@method).should == "10A00a00A" - - "ZZZ9999".send(@method).should == "AAAA0000" - "/[]9999".send(@method).should == "/[]10000" - "/[]ZZZ9999".send(@method).should == "/[]AAAA0000" - "Z/[]ZZZ9999".send(@method).should == "AA/[]AAA0000" - - # non-alphanumeric cases - "\xFF".send(@method).should == "\x01\x00" - "\xFF\xFF".send(@method).should == "\x01\x00\x00" - end - - it "returns String instances when called on a subclass" do - StringSpecs::MyString.new("").send(@method).should.instance_of?(String) - StringSpecs::MyString.new("a").send(@method).should.instance_of?(String) - StringSpecs::MyString.new("z").send(@method).should.instance_of?(String) - end - - it "returns a String in the same encoding as self" do - "z".encode("US-ASCII").send(@method).encoding.should == Encoding::US_ASCII - end -end - -describe :string_succ_bang, shared: true do - it "is equivalent to succ, but modifies self in place (still returns self)" do - ["", "abcd", "THX1138"].each do |s| - s = +s - r = s.dup.send(@method) - s.send(@method).should.equal?(s) - s.should == r - end - end - - it "raises a FrozenError if self is frozen" do - -> { "".freeze.send(@method) }.should.raise(FrozenError) - -> { "abcd".freeze.send(@method) }.should.raise(FrozenError) - end -end diff --git a/core/string/shared/to_s.rb b/core/string/shared/to_s.rb deleted file mode 100644 index 96c59470d6..0000000000 --- a/core/string/shared/to_s.rb +++ /dev/null @@ -1,13 +0,0 @@ -describe :string_to_s, shared: true do - it "returns self when self.class == String" do - a = "a string" - a.should.equal?(a.send(@method)) - end - - it "returns a new instance of String when called on a subclass" do - a = StringSpecs::MyString.new("a string") - s = a.send(@method) - s.should == "a string" - s.should.instance_of?(String) - end -end diff --git a/core/string/shared/to_sym.rb b/core/string/shared/to_sym.rb deleted file mode 100644 index 2a8a2e3182..0000000000 --- a/core/string/shared/to_sym.rb +++ /dev/null @@ -1,72 +0,0 @@ -describe :string_to_sym, shared: true do - it "returns the symbol corresponding to self" do - "Koala".send(@method).should.equal? :Koala - 'cat'.send(@method).should.equal? :cat - '@cat'.send(@method).should.equal? :@cat - 'cat and dog'.send(@method).should.equal? :"cat and dog" - "abc=".send(@method).should.equal? :abc= - end - - it "does not special case +(binary) and -(binary)" do - "+(binary)".send(@method).should.equal? :"+(binary)" - "-(binary)".send(@method).should.equal? :"-(binary)" - end - - it "does not special case certain operators" do - "!@".send(@method).should.equal? :"!@" - "~@".send(@method).should.equal? :"~@" - "!(unary)".send(@method).should.equal? :"!(unary)" - "~(unary)".send(@method).should.equal? :"~(unary)" - "+(unary)".send(@method).should.equal? :"+(unary)" - "-(unary)".send(@method).should.equal? :"-(unary)" - end - - it "returns a US-ASCII Symbol for a UTF-8 String containing only US-ASCII characters" do - sym = "foobar".send(@method) - sym.encoding.should == Encoding::US_ASCII - sym.should.equal? :"foobar" - end - - it "returns a US-ASCII Symbol for a binary String containing only US-ASCII characters" do - sym = "foobar".b.send(@method) - sym.encoding.should == Encoding::US_ASCII - sym.should.equal? :"foobar" - end - - it "returns a UTF-8 Symbol for a UTF-8 String containing non US-ASCII characters" do - sym = "il était une fois".send(@method) - sym.encoding.should == Encoding::UTF_8 - sym.should.equal? :"il était une #{'fois'}" - end - - it "returns a UTF-16LE Symbol for a UTF-16LE String containing non US-ASCII characters" do - utf16_str = "UtéF16".encode(Encoding::UTF_16LE) - sym = utf16_str.send(@method) - sym.encoding.should == Encoding::UTF_16LE - sym.to_s.should == utf16_str - end - - it "returns a binary Symbol for a binary String containing non US-ASCII characters" do - binary_string = "binarí".b - sym = binary_string.send(@method) - sym.encoding.should == Encoding::BINARY - sym.to_s.should == binary_string - end - - it "ignores existing symbols with different encoding" do - source = "fée" - - iso_symbol = source.dup.force_encoding(Encoding::ISO_8859_1).send(@method) - iso_symbol.encoding.should == Encoding::ISO_8859_1 - binary_symbol = source.dup.force_encoding(Encoding::BINARY).send(@method) - binary_symbol.encoding.should == Encoding::BINARY - end - - it "raises an EncodingError for UTF-8 String containing invalid bytes" do - invalid_utf8 = "\xC3" - invalid_utf8.should_not.valid_encoding? - -> { - invalid_utf8.send(@method) - }.should.raise(EncodingError, 'invalid symbol in encoding UTF-8 :"\xC3"') - end -end diff --git a/core/string/size_spec.rb b/core/string/size_spec.rb index 9e1f40c5ae..6fc81480c4 100644 --- a/core/string/size_spec.rb +++ b/core/string/size_spec.rb @@ -1,7 +1,7 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' -require_relative 'shared/length' describe "String#size" do - it_behaves_like :string_length, :size + it "is an alias of String#length" do + String.instance_method(:size).should == String.instance_method(:length) + end end diff --git a/core/string/slice_spec.rb b/core/string/slice_spec.rb index 14e2251b3f..16d7665bbf 100644 --- a/core/string/slice_spec.rb +++ b/core/string/slice_spec.rb @@ -1,39 +1,12 @@ -# -*- encoding: utf-8 -*- # frozen_string_literal: false require_relative '../../spec_helper' require_relative 'fixtures/classes' require_relative 'shared/slice' describe "String#slice" do - it_behaves_like :string_slice, :slice -end - -describe "String#slice with index, length" do - it_behaves_like :string_slice_index_length, :slice -end - -describe "String#slice with Range" do - it_behaves_like :string_slice_range, :slice -end - -describe "String#slice with Regexp" do - it_behaves_like :string_slice_regexp, :slice -end - -describe "String#slice with Regexp, index" do - it_behaves_like :string_slice_regexp_index, :slice -end - -describe "String#slice with Regexp, group" do - it_behaves_like :string_slice_regexp_group, :slice -end - -describe "String#slice with String" do - it_behaves_like :string_slice_string, :slice -end - -describe "String#slice with Symbol" do - it_behaves_like :string_slice_symbol, :slice + it "is an alias of String#[]" do + String.instance_method(:slice).should == String.instance_method(:[]) + end end describe "String#slice! with index" do diff --git a/core/string/succ_spec.rb b/core/string/succ_spec.rb index 65047e0aa2..87beca8b09 100644 --- a/core/string/succ_spec.rb +++ b/core/string/succ_spec.rb @@ -1,11 +1,90 @@ +# encoding: binary require_relative '../../spec_helper' require_relative 'fixtures/classes' -require_relative 'shared/succ' describe "String#succ" do - it_behaves_like :string_succ, :succ + it "returns an empty string for empty strings" do + "".succ.should == "" + end + + it "returns the successor by increasing the rightmost alphanumeric (digit => digit, letter => letter with same case)" do + "abcd".succ.should == "abce" + "THX1138".succ.should == "THX1139" + + "<>".succ.should == "<>" + "==A??".succ.should == "==B??" + end + + it "increases non-alphanumerics (via ascii rules) if there are no alphanumerics" do + "***".succ.should == "**+" + "**`".succ.should == "**a" + end + + it "increases the next best alphanumeric (jumping over non-alphanumerics) if there is a carry" do + "dz".succ.should == "ea" + "HZ".succ.should == "IA" + "49".succ.should == "50" + + "izz".succ.should == "jaa" + "IZZ".succ.should == "JAA" + "699".succ.should == "700" + + "6Z99z99Z".succ.should == "7A00a00A" + + "1999zzz".succ.should == "2000aaa" + "NZ/[]ZZZ9999".succ.should == "OA/[]AAA0000" + end + + it "increases the next best character if there is a carry for non-alphanumerics" do + "(\xFF".succ.should == ")\x00" + "`\xFF".succ.should == "a\x00" + "<\xFF\xFF".succ.should == "=\x00\x00" + end + + it "adds an additional character (just left to the last increased one) if there is a carry and no character left to increase" do + "z".succ.should == "aa" + "Z".succ.should == "AA" + "9".succ.should == "10" + + "zz".succ.should == "aaa" + "ZZ".succ.should == "AAA" + "99".succ.should == "100" + + "9Z99z99Z".succ.should == "10A00a00A" + + "ZZZ9999".succ.should == "AAAA0000" + "/[]9999".succ.should == "/[]10000" + "/[]ZZZ9999".succ.should == "/[]AAAA0000" + "Z/[]ZZZ9999".succ.should == "AA/[]AAA0000" + + # non-alphanumeric cases + "\xFF".succ.should == "\x01\x00" + "\xFF\xFF".succ.should == "\x01\x00\x00" + end + + it "returns String instances when called on a subclass" do + StringSpecs::MyString.new("").succ.should.instance_of?(String) + StringSpecs::MyString.new("a").succ.should.instance_of?(String) + StringSpecs::MyString.new("z").succ.should.instance_of?(String) + end + + it "returns a String in the same encoding as self" do + "z".encode("US-ASCII").succ.encoding.should == Encoding::US_ASCII + end end describe "String#succ!" do - it_behaves_like :string_succ_bang, :"succ!" + it "is equivalent to succ, but modifies self in place (still returns self)" do + ["", "abcd", "THX1138"].each do |s| + s = +s + r = s.dup.succ! + s.succ!.should.equal?(s) + s.should == r + end + end + + it "raises a FrozenError if self is frozen" do + -> { "".freeze.succ! }.should.raise(FrozenError) + -> { "abcd".freeze.succ! }.should.raise(FrozenError) + end end diff --git a/core/string/to_s_spec.rb b/core/string/to_s_spec.rb index e5872745a8..c48c7f89ac 100644 --- a/core/string/to_s_spec.rb +++ b/core/string/to_s_spec.rb @@ -1,7 +1,16 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -require_relative 'shared/to_s' describe "String#to_s" do - it_behaves_like :string_to_s, :to_s + it "returns self when self.class == String" do + a = "a string" + a.should.equal?(a.to_s) + end + + it "returns a new instance of String when called on a subclass" do + a = StringSpecs::MyString.new("a string") + s = a.to_s + s.should == "a string" + s.should.instance_of?(String) + end end diff --git a/core/string/to_str_spec.rb b/core/string/to_str_spec.rb index e24262a7ae..8253b3d8a3 100644 --- a/core/string/to_str_spec.rb +++ b/core/string/to_str_spec.rb @@ -1,7 +1,7 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' -require_relative 'shared/to_s' describe "String#to_str" do - it_behaves_like :string_to_s, :to_str + it "is an alias of String#to_s" do + String.instance_method(:to_str).should == String.instance_method(:to_s) + end end diff --git a/core/string/to_sym_spec.rb b/core/string/to_sym_spec.rb index f9135211ce..f0ffe58674 100644 --- a/core/string/to_sym_spec.rb +++ b/core/string/to_sym_spec.rb @@ -1,7 +1,74 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' -require_relative 'shared/to_sym' describe "String#to_sym" do - it_behaves_like :string_to_sym, :to_sym + it "returns the symbol corresponding to self" do + "Koala".to_sym.should.equal? :Koala + 'cat'.to_sym.should.equal? :cat + '@cat'.to_sym.should.equal? :@cat + 'cat and dog'.to_sym.should.equal? :"cat and dog" + "abc=".to_sym.should.equal? :abc= + end + + it "does not special case +(binary) and -(binary)" do + "+(binary)".to_sym.should.equal? :"+(binary)" + "-(binary)".to_sym.should.equal? :"-(binary)" + end + + it "does not special case certain operators" do + "!@".to_sym.should.equal? :"!@" + "~@".to_sym.should.equal? :"~@" + "!(unary)".to_sym.should.equal? :"!(unary)" + "~(unary)".to_sym.should.equal? :"~(unary)" + "+(unary)".to_sym.should.equal? :"+(unary)" + "-(unary)".to_sym.should.equal? :"-(unary)" + end + + it "returns a US-ASCII Symbol for a UTF-8 String containing only US-ASCII characters" do + sym = "foobar".to_sym + sym.encoding.should == Encoding::US_ASCII + sym.should.equal? :"foobar" + end + + it "returns a US-ASCII Symbol for a binary String containing only US-ASCII characters" do + sym = "foobar".b.to_sym + sym.encoding.should == Encoding::US_ASCII + sym.should.equal? :"foobar" + end + + it "returns a UTF-8 Symbol for a UTF-8 String containing non US-ASCII characters" do + sym = "il était une fois".to_sym + sym.encoding.should == Encoding::UTF_8 + sym.should.equal? :"il était une fois" + end + + it "returns a UTF-16LE Symbol for a UTF-16LE String containing non US-ASCII characters" do + utf16_str = "UtéF16".encode(Encoding::UTF_16LE) + sym = utf16_str.to_sym + sym.encoding.should == Encoding::UTF_16LE + sym.to_s.should == utf16_str + end + + it "returns a binary Symbol for a binary String containing non US-ASCII characters" do + binary_string = "binarí".b + sym = binary_string.to_sym + sym.encoding.should == Encoding::BINARY + sym.to_s.should == binary_string + end + + it "ignores existing symbols with different encoding" do + source = "fée" + + iso_symbol = source.dup.force_encoding(Encoding::ISO_8859_1).to_sym + iso_symbol.encoding.should == Encoding::ISO_8859_1 + binary_symbol = source.dup.force_encoding(Encoding::BINARY).to_sym + binary_symbol.encoding.should == Encoding::BINARY + end + + it "raises an EncodingError for UTF-8 String containing invalid bytes" do + invalid_utf8 = "\xC3" + invalid_utf8.should_not.valid_encoding? + -> { + invalid_utf8.to_sym + }.should.raise(EncodingError, 'invalid symbol in encoding UTF-8 :"\xC3"') + end end diff --git a/core/string/uminus_spec.rb b/core/string/uminus_spec.rb index 46d88f6704..43abf71d50 100644 --- a/core/string/uminus_spec.rb +++ b/core/string/uminus_spec.rb @@ -1,6 +1,53 @@ +# frozen_string_literal: false require_relative '../../spec_helper' -require_relative 'shared/dedup' describe 'String#-@' do - it_behaves_like :string_dedup, :-@ + it 'returns self if the String is frozen' do + input = 'foo'.freeze + output = -input + + output.should.equal?(input) + output.should.frozen? + end + + it 'returns a frozen copy if the String is not frozen' do + input = 'foo' + output = -input + + output.should.frozen? + output.should_not.equal?(input) + output.should == 'foo' + end + + it "returns the same object for equal unfrozen strings" do + origin = "this is a string" + dynamic = %w(this is a string).join(' ') + + origin.should_not.equal?(dynamic) + (-origin).should.equal?(-dynamic) + end + + it "returns the same object when it's called on the same String literal" do + (-"unfrozen string").should.equal?(-"unfrozen string") + (-"unfrozen string").should_not.equal?(-"another unfrozen string") + end + + it "deduplicates frozen strings" do + dynamic = %w(this string is frozen).join(' ').freeze + + dynamic.should_not.equal?("this string is frozen".freeze) + + (-dynamic).should.equal?("this string is frozen".freeze) + (-dynamic).should.equal?((-"this string is frozen").freeze) + end + + it "does not deduplicate a frozen string when it has instance variables" do + dynamic = %w(this string is frozen).join(' ') + dynamic.instance_variable_set(:@a, 1) + dynamic.freeze + + (-dynamic).should_not.equal?("this string is frozen".freeze) + (-dynamic).should_not.equal?((-"this string is frozen").freeze) + (-dynamic).should.equal?(-dynamic) + end end diff --git a/core/struct/deconstruct_spec.rb b/core/struct/deconstruct_spec.rb index 32d4f6bac4..848012091f 100644 --- a/core/struct/deconstruct_spec.rb +++ b/core/struct/deconstruct_spec.rb @@ -1,10 +1,7 @@ require_relative '../../spec_helper' describe "Struct#deconstruct" do - it "returns an array of attribute values" do - struct = Struct.new(:x, :y) - s = struct.new(1, 2) - - s.deconstruct.should == [1, 2] + it "is an alias for Struct#to_a" do + Struct.instance_method(:deconstruct).should == Struct.instance_method(:to_a) end end diff --git a/core/struct/filter_spec.rb b/core/struct/filter_spec.rb index 0ccd8ad6b2..5d11f47e6b 100644 --- a/core/struct/filter_spec.rb +++ b/core/struct/filter_spec.rb @@ -1,10 +1,8 @@ require_relative '../../spec_helper' -require_relative 'shared/select' -require_relative 'shared/accessor' -require_relative '../enumerable/shared/enumeratorized' +require_relative 'fixtures/classes' describe "Struct#filter" do - it_behaves_like :struct_select, :filter - it_behaves_like :struct_accessor, :filter - it_behaves_like :enumeratorized_with_origin_size, :filter, Struct.new(:foo).new + it "is an alias of Struct#select" do + StructClasses::Car.instance_method(:filter).should == StructClasses::Car.instance_method(:select) + end end diff --git a/core/struct/inspect_spec.rb b/core/struct/inspect_spec.rb index 657b06abc1..13fd0bef41 100644 --- a/core/struct/inspect_spec.rb +++ b/core/struct/inspect_spec.rb @@ -1,7 +1,8 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -require_relative 'shared/inspect' describe "Struct#inspect" do - it_behaves_like :struct_inspect, :inspect + it "is an alias of Struct#to_s" do + StructClasses::Car.instance_method(:inspect).should == StructClasses::Car.instance_method(:to_s) + end end diff --git a/core/struct/length_spec.rb b/core/struct/length_spec.rb index 1143676122..8d48f4118d 100644 --- a/core/struct/length_spec.rb +++ b/core/struct/length_spec.rb @@ -1,12 +1,8 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -require_relative 'shared/accessor' describe "Struct#length" do - it "returns the number of attributes" do - StructClasses::Car.new('Cadillac', 'DeVille').length.should == 3 - StructClasses::Car.new.length.should == 3 + it "is an alias of Struct#size" do + StructClasses::Car.instance_method(:length).should == StructClasses::Car.instance_method(:size) end - - it_behaves_like :struct_accessor, :length end diff --git a/core/struct/select_spec.rb b/core/struct/select_spec.rb index ee846ec45f..5f26a177eb 100644 --- a/core/struct/select_spec.rb +++ b/core/struct/select_spec.rb @@ -1,10 +1,31 @@ require_relative '../../spec_helper' -require_relative 'shared/select' +require_relative 'fixtures/classes' require_relative 'shared/accessor' require_relative '../enumerable/shared/enumeratorized' describe "Struct#select" do - it_behaves_like :struct_select, :select it_behaves_like :struct_accessor, :select it_behaves_like :enumeratorized_with_origin_size, :select, Struct.new(:foo).new + + it "raises an ArgumentError if given any non-block arguments" do + struct = StructClasses::Car.new + -> { struct.select(1) { } }.should.raise(ArgumentError) + end + + it "returns a new array of elements for which block is true" do + struct = StructClasses::Car.new("Toyota", "Tercel", "2000") + struct.select { |i| i == "2000" }.should == [ "2000" ] + end + + it "returns an instance of Array" do + struct = StructClasses::Car.new("Ford", "Escort", "1995") + struct.select { true }.should.instance_of?(Array) + end + + describe "without block" do + it "returns an instance of Enumerator" do + struct = Struct.new(:foo).new + struct.select.should.instance_of?(Enumerator) + end + end end diff --git a/core/struct/shared/inspect.rb b/core/struct/shared/inspect.rb deleted file mode 100644 index 1a0fb6a6b2..0000000000 --- a/core/struct/shared/inspect.rb +++ /dev/null @@ -1,40 +0,0 @@ -describe :struct_inspect, shared: true do - it "returns a string representation showing members and values" do - car = StructClasses::Car.new('Ford', 'Ranger') - car.send(@method).should == '#' - end - - it "returns a string representation without the class name for anonymous structs" do - Struct.new(:a).new("").send(@method).should == '#' - end - - it "returns a string representation without the class name for structs nested in anonymous classes" do - c = Class.new - c.class_eval <<~DOC - class Foo < Struct.new(:a); end - DOC - - c::Foo.new("").send(@method).should == '#' - end - - it "returns a string representation without the class name for structs nested in anonymous modules" do - m = Module.new - m.module_eval <<~DOC - class Foo < Struct.new(:a); end - DOC - - m::Foo.new("").send(@method).should == '#' - end - - it "does not call #name method" do - struct = StructClasses::StructWithOverriddenName.new("") - struct.send(@method).should == '#' - end - - it "does not call #name method when struct is anonymous" do - struct = Struct.new(:a) - def struct.name; "A"; end - - struct.new("").send(@method).should == '#' - end -end diff --git a/core/struct/shared/select.rb b/core/struct/shared/select.rb deleted file mode 100644 index dfa1a809fe..0000000000 --- a/core/struct/shared/select.rb +++ /dev/null @@ -1,26 +0,0 @@ -require_relative '../../../spec_helper' -require_relative '../fixtures/classes' - -describe :struct_select, shared: true do - it "raises an ArgumentError if given any non-block arguments" do - struct = StructClasses::Car.new - -> { struct.send(@method, 1) { } }.should.raise(ArgumentError) - end - - it "returns a new array of elements for which block is true" do - struct = StructClasses::Car.new("Toyota", "Tercel", "2000") - struct.send(@method) { |i| i == "2000" }.should == [ "2000" ] - end - - it "returns an instance of Array" do - struct = StructClasses::Car.new("Ford", "Escort", "1995") - struct.send(@method) { true }.should.instance_of?(Array) - end - - describe "without block" do - it "returns an instance of Enumerator" do - struct = Struct.new(:foo).new - struct.send(@method).should.instance_of?(Enumerator) - end - end -end diff --git a/core/struct/to_s_spec.rb b/core/struct/to_s_spec.rb index 94c672d3d5..9648b8af9b 100644 --- a/core/struct/to_s_spec.rb +++ b/core/struct/to_s_spec.rb @@ -1,12 +1,43 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -require_relative 'shared/inspect' describe "Struct#to_s" do - it "is a synonym for inspect" do + it "returns a string representation showing members and values" do car = StructClasses::Car.new('Ford', 'Ranger') - car.inspect.should == car.to_s + car.to_s.should == '#' end - it_behaves_like :struct_inspect, :to_s + it "returns a string representation without the class name for anonymous structs" do + Struct.new(:a).new("").to_s.should == '#' + end + + it "returns a string representation without the class name for structs nested in anonymous classes" do + c = Class.new + c.class_eval <<~DOC + class Foo < Struct.new(:a); end + DOC + + c::Foo.new("").to_s.should == '#' + end + + it "returns a string representation without the class name for structs nested in anonymous modules" do + m = Module.new + m.module_eval <<~DOC + class Foo < Struct.new(:a); end + DOC + + m::Foo.new("").to_s.should == '#' + end + + it "does not call #name method" do + struct = StructClasses::StructWithOverriddenName.new("") + struct.to_s.should == '#' + end + + it "does not call #name method when struct is anonymous" do + struct = Struct.new(:a) + def struct.name; "A"; end + + struct.new("").to_s.should == '#' + end end diff --git a/core/struct/values_spec.rb b/core/struct/values_spec.rb index b2d11725b9..16583253d7 100644 --- a/core/struct/values_spec.rb +++ b/core/struct/values_spec.rb @@ -2,10 +2,7 @@ require_relative 'fixtures/classes' describe "Struct#values" do - it "is a synonym for to_a" do - car = StructClasses::Car.new('Nissan', 'Maxima') - car.values.should == car.to_a - - StructClasses::Car.new.values.should == StructClasses::Car.new.to_a + it "is an alias of Struct#to_a" do + StructClasses::Car.instance_method(:values).should == StructClasses::Car.instance_method(:to_a) end end diff --git a/core/symbol/case_compare_spec.rb b/core/symbol/case_compare_spec.rb index 0c6bc1eda5..a296132c04 100644 --- a/core/symbol/case_compare_spec.rb +++ b/core/symbol/case_compare_spec.rb @@ -1,11 +1,7 @@ require_relative '../../spec_helper' describe "Symbol#===" do - it "returns true when the argument is a Symbol" do - (Symbol === :ruby).should == true - end - - it "returns false when the argument is a String" do - (Symbol === 'ruby').should == false + it "is an alias of Symbol#==" do + Symbol.instance_method(:===).should == Symbol.instance_method(:==) end end diff --git a/core/symbol/element_reference_spec.rb b/core/symbol/element_reference_spec.rb index df6bc15ddb..360a661891 100644 --- a/core/symbol/element_reference_spec.rb +++ b/core/symbol/element_reference_spec.rb @@ -1,6 +1,263 @@ require_relative '../../spec_helper' -require_relative 'shared/slice' +require_relative 'fixtures/classes' describe "Symbol#[]" do - it_behaves_like :symbol_slice, :[] + describe "with an Integer index" do + it "returns the character code of the element at the index" do + :symbol[1].should == ?y + end + + it "returns nil if the index starts from the end and is greater than the length" do + :symbol[-10].should == nil + end + + it "returns nil if the index is greater than the length" do + :symbol[42].should == nil + end + end + + describe "with an Integer index and length" do + describe "and a positive index and length" do + it "returns a slice" do + :symbol[1, 3].should == "ymb" + end + + it "returns a blank slice if the length is 0" do + :symbol[0, 0].should == "" + :symbol[1, 0].should == "" + end + + it "returns a slice of all remaining characters if the given length is greater than the actual length" do + :symbol[1, 100].should == "ymbol" + end + + it "returns nil if the index is greater than the length" do + :symbol[10, 1].should == nil + end + end + + describe "and a positive index and negative length" do + it "returns nil" do + :symbol[0, -1].should == nil + :symbol[1, -1].should == nil + end + end + + describe "and a negative index and positive length" do + it "returns a slice starting from the end upto the length" do + :symbol[-3, 2].should == "bo" + end + + it "returns a blank slice if the length is 0" do + :symbol[-1, 0].should == "" + end + + it "returns a slice of all remaining characters if the given length is larger than the actual length" do + :symbol[-4, 100].should == "mbol" + end + + it "returns nil if the index is past the start" do + :symbol[-10, 1].should == nil + end + end + + describe "and a negative index and negative length" do + it "returns nil" do + :symbol[-1, -1].should == nil + end + end + + describe "and a Float length" do + it "converts the length to an Integer" do + :symbol[2, 2.5].should == "mb" + end + end + + describe "and a nil length" do + it "raises a TypeError" do + -> { :symbol[1, nil] }.should.raise(TypeError) + end + end + + describe "and a length that cannot be converted into an Integer" do + it "raises a TypeError when given an Array" do + -> { :symbol[1, Array.new] }.should.raise(TypeError) + end + + it "raises a TypeError when given an Hash" do + -> { :symbol[1, Hash.new] }.should.raise(TypeError) + end + + it "raises a TypeError when given an Object" do + -> { :symbol[1, Object.new] }.should.raise(TypeError) + end + end + end + + describe "with a Float index" do + it "converts the index to an Integer" do + :symbol[1.5].should == ?y + end + end + + describe "with a nil index" do + it "raises a TypeError" do + -> { :symbol[nil] }.should.raise(TypeError) + end + end + + describe "with an index that cannot be converted into an Integer" do + it "raises a TypeError when given an Array" do + -> { :symbol[Array.new] }.should.raise(TypeError) + end + + it "raises a TypeError when given an Hash" do + -> { :symbol[Hash.new] }.should.raise(TypeError) + end + + it "raises a TypeError when given an Object" do + -> { :symbol[Object.new] }.should.raise(TypeError) + end + end + + describe "with a Range slice" do + describe "that is within bounds" do + it "returns a slice if both range values begin at the start and are within bounds" do + :symbol[1..4].should == "ymbo" + end + + it "returns a slice if the first range value begins at the start and the last begins at the end" do + :symbol[1..-1].should == "ymbol" + end + + it "returns a slice if the first range value begins at the end and the last begins at the end" do + :symbol[-4..-1].should == "mbol" + end + end + + describe "that is out of bounds" do + it "returns nil if the first range value begins past the end" do + :symbol[10..12].should == nil + end + + it "returns a blank string if the first range value is within bounds and the last range value is not" do + :symbol[-2..-10].should == "" + :symbol[2..-10].should == "" + end + + it "returns nil if the first range value starts from the end and is within bounds and the last value starts from the end and is greater than the length" do + :symbol[-10..-12].should == nil + end + + it "returns nil if the first range value starts from the end and is out of bounds and the last value starts from the end and is less than the length" do + :symbol[-10..-2].should == nil + end + end + + describe "with Float values" do + it "converts the first value to an Integer" do + :symbol[0.5..2].should == "sym" + end + + it "converts the last value to an Integer" do + :symbol[0..2.5].should == "sym" + end + end + end + + describe "with a Range subclass slice" do + it "returns a slice" do + range = SymbolSpecs::MyRange.new(1, 4) + :symbol[range].should == "ymbo" + end + end + + describe "with a Regex slice" do + describe "without a capture index" do + it "returns a string of the match" do + :symbol[/[^bol]+/].should == "sym" + end + + it "returns nil if the expression does not match" do + :symbol[/0-9/].should == nil + end + + it "sets $~ to the MatchData if there is a match" do + :symbol[/[^bol]+/] + $~[0].should == "sym" + end + + it "does not set $~ if there if there is not a match" do + :symbol[/[0-9]+/] + $~.should == nil + end + end + + describe "with a capture index" do + it "returns a string of the complete match if the capture index is 0" do + :symbol[/(sy)(mb)(ol)/, 0].should == "symbol" + end + + it "returns a string for the matched capture at the given index" do + :symbol[/(sy)(mb)(ol)/, 1].should == "sy" + :symbol[/(sy)(mb)(ol)/, -1].should == "ol" + end + + it "returns nil if there is no capture for the index" do + :symbol[/(sy)(mb)(ol)/, 4].should == nil + :symbol[/(sy)(mb)(ol)/, -4].should == nil + end + + it "converts the index to an Integer" do + :symbol[/(sy)(mb)(ol)/, 1.5].should == "sy" + end + + describe "and an index that cannot be converted to an Integer" do + it "raises a TypeError when given an Hash" do + -> { :symbol[/(sy)(mb)(ol)/, Hash.new] }.should.raise(TypeError) + end + + it "raises a TypeError when given an Array" do + -> { :symbol[/(sy)(mb)(ol)/, Array.new] }.should.raise(TypeError) + end + + it "raises a TypeError when given an Object" do + -> { :symbol[/(sy)(mb)(ol)/, Object.new] }.should.raise(TypeError) + end + end + + it "raises a TypeError if the index is nil" do + -> { :symbol[/(sy)(mb)(ol)/, nil] }.should.raise(TypeError) + end + + it "sets $~ to the MatchData if there is a match" do + :symbol[/(sy)(mb)(ol)/, 0] + $~[0].should == "symbol" + $~[1].should == "sy" + $~[2].should == "mb" + $~[3].should == "ol" + end + + it "does not set $~ to the MatchData if there is not a match" do + :symbol[/0-9/, 0] + $~.should == nil + end + end + end + + describe "with a String slice" do + it "does not set $~" do + $~ = nil + :symbol["sym"] + $~.should == nil + end + + it "returns a string if there is match" do + :symbol["ymb"].should == "ymb" + end + + it "returns nil if there is not a match" do + :symbol["foo"].should == nil + end + end end diff --git a/core/symbol/id2name_spec.rb b/core/symbol/id2name_spec.rb index 2caa89fc37..abcbff65f4 100644 --- a/core/symbol/id2name_spec.rb +++ b/core/symbol/id2name_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/id2name' describe "Symbol#id2name" do - it_behaves_like :symbol_id2name, :id2name + it "is an alias of Symbol#to_s" do + Symbol.instance_method(:id2name).should == Symbol.instance_method(:to_s) + end end diff --git a/core/symbol/intern_spec.rb b/core/symbol/intern_spec.rb index 9d0914c7fb..746d313d40 100644 --- a/core/symbol/intern_spec.rb +++ b/core/symbol/intern_spec.rb @@ -1,11 +1,7 @@ require_relative '../../spec_helper' describe "Symbol#intern" do - it "returns self" do - :foo.intern.should == :foo - end - - it "returns a Symbol" do - :foo.intern.should.is_a?(Symbol) + it "is an alias of Symbol#to_sym" do + Symbol.instance_method(:intern).should == Symbol.instance_method(:to_sym) end end diff --git a/core/symbol/length_spec.rb b/core/symbol/length_spec.rb index 27bee575ef..29dd4ad46b 100644 --- a/core/symbol/length_spec.rb +++ b/core/symbol/length_spec.rb @@ -1,6 +1,23 @@ require_relative '../../spec_helper' -require_relative 'shared/length' describe "Symbol#length" do - it_behaves_like :symbol_length, :length + it "returns 0 for empty name" do + :''.length.should == 0 + end + + it "returns 1 for name formed by a NUL character" do + :"\x00".length.should == 1 + end + + it "returns 3 for name formed by 3 ASCII characters" do + :one.length.should == 3 + end + + it "returns 4 for name formed by 4 ASCII characters" do + :four.length.should == 4 + end + + it "returns 4 for name formed by 1 multibyte and 3 ASCII characters" do + :"\xC3\x9Cber".length.should == 4 + end end diff --git a/core/symbol/next_spec.rb b/core/symbol/next_spec.rb index 97fe913739..e80bbaa508 100644 --- a/core/symbol/next_spec.rb +++ b/core/symbol/next_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/succ' describe "Symbol#next" do - it_behaves_like :symbol_succ, :next + it "is an alias of Symbol#succ" do + Symbol.instance_method(:next).should == Symbol.instance_method(:succ) + end end diff --git a/core/symbol/shared/id2name.rb b/core/symbol/shared/id2name.rb deleted file mode 100644 index 00a9c7d7dc..0000000000 --- a/core/symbol/shared/id2name.rb +++ /dev/null @@ -1,30 +0,0 @@ -describe :symbol_id2name, shared: true do - it "returns the string corresponding to self" do - :rubinius.send(@method).should == "rubinius" - :squash.send(@method).should == "squash" - :[].send(@method).should == "[]" - :@ruby.send(@method).should == "@ruby" - :@@ruby.send(@method).should == "@@ruby" - end - - it "returns a String in the same encoding as self" do - string = "ruby".encode("US-ASCII") - symbol = string.to_sym - - symbol.send(@method).encoding.should == Encoding::US_ASCII - end - - ruby_version_is "3.4" do - it "warns about mutating returned string" do - -> { :bad!.send(@method).upcase! }.should complain(/warning: string returned by :bad!.to_s will be frozen in the future/) - end - - it "does not warn about mutation when Warning[:deprecated] is false" do - deprecated = Warning[:deprecated] - Warning[:deprecated] = false - -> { :bad!.send(@method).upcase! }.should_not complain - ensure - Warning[:deprecated] = deprecated - end - end -end diff --git a/core/symbol/shared/length.rb b/core/symbol/shared/length.rb deleted file mode 100644 index 692e8c57e3..0000000000 --- a/core/symbol/shared/length.rb +++ /dev/null @@ -1,23 +0,0 @@ -# -*- encoding: utf-8 -*- - -describe :symbol_length, shared: true do - it "returns 0 for empty name" do - :''.send(@method).should == 0 - end - - it "returns 1 for name formed by a NUL character" do - :"\x00".send(@method).should == 1 - end - - it "returns 3 for name formed by 3 ASCII characters" do - :one.send(@method).should == 3 - end - - it "returns 4 for name formed by 4 ASCII characters" do - :four.send(@method).should == 4 - end - - it "returns 4 for name formed by 1 multibyte and 3 ASCII characters" do - :"\xC3\x9Cber".send(@method).should == 4 - end -end diff --git a/core/symbol/shared/slice.rb b/core/symbol/shared/slice.rb deleted file mode 100644 index 4e3a35240c..0000000000 --- a/core/symbol/shared/slice.rb +++ /dev/null @@ -1,262 +0,0 @@ -require_relative '../fixtures/classes' - -describe :symbol_slice, shared: true do - describe "with an Integer index" do - it "returns the character code of the element at the index" do - :symbol.send(@method, 1).should == ?y - end - - it "returns nil if the index starts from the end and is greater than the length" do - :symbol.send(@method, -10).should == nil - end - - it "returns nil if the index is greater than the length" do - :symbol.send(@method, 42).should == nil - end - end - - describe "with an Integer index and length" do - describe "and a positive index and length" do - it "returns a slice" do - :symbol.send(@method, 1,3).should == "ymb" - end - - it "returns a blank slice if the length is 0" do - :symbol.send(@method, 0,0).should == "" - :symbol.send(@method, 1,0).should == "" - end - - it "returns a slice of all remaining characters if the given length is greater than the actual length" do - :symbol.send(@method, 1,100).should == "ymbol" - end - - it "returns nil if the index is greater than the length" do - :symbol.send(@method, 10,1).should == nil - end - end - - describe "and a positive index and negative length" do - it "returns nil" do - :symbol.send(@method, 0,-1).should == nil - :symbol.send(@method, 1,-1).should == nil - end - end - - describe "and a negative index and positive length" do - it "returns a slice starting from the end upto the length" do - :symbol.send(@method, -3,2).should == "bo" - end - - it "returns a blank slice if the length is 0" do - :symbol.send(@method, -1,0).should == "" - end - - it "returns a slice of all remaining characters if the given length is larger than the actual length" do - :symbol.send(@method, -4,100).should == "mbol" - end - - it "returns nil if the index is past the start" do - :symbol.send(@method, -10,1).should == nil - end - end - - describe "and a negative index and negative length" do - it "returns nil" do - :symbol.send(@method, -1,-1).should == nil - end - end - - describe "and a Float length" do - it "converts the length to an Integer" do - :symbol.send(@method, 2,2.5).should == "mb" - end - end - - describe "and a nil length" do - it "raises a TypeError" do - -> { :symbol.send(@method, 1,nil) }.should.raise(TypeError) - end - end - - describe "and a length that cannot be converted into an Integer" do - it "raises a TypeError when given an Array" do - -> { :symbol.send(@method, 1,Array.new) }.should.raise(TypeError) - end - - it "raises a TypeError when given an Hash" do - -> { :symbol.send(@method, 1,Hash.new) }.should.raise(TypeError) - end - - it "raises a TypeError when given an Object" do - -> { :symbol.send(@method, 1,Object.new) }.should.raise(TypeError) - end - end - end - - describe "with a Float index" do - it "converts the index to an Integer" do - :symbol.send(@method, 1.5).should == ?y - end - end - - describe "with a nil index" do - it "raises a TypeError" do - -> { :symbol.send(@method, nil) }.should.raise(TypeError) - end - end - - describe "with an index that cannot be converted into an Integer" do - it "raises a TypeError when given an Array" do - -> { :symbol.send(@method, Array.new) }.should.raise(TypeError) - end - - it "raises a TypeError when given an Hash" do - -> { :symbol.send(@method, Hash.new) }.should.raise(TypeError) - end - - it "raises a TypeError when given an Object" do - -> { :symbol.send(@method, Object.new) }.should.raise(TypeError) - end - end - - describe "with a Range slice" do - describe "that is within bounds" do - it "returns a slice if both range values begin at the start and are within bounds" do - :symbol.send(@method, 1..4).should == "ymbo" - end - - it "returns a slice if the first range value begins at the start and the last begins at the end" do - :symbol.send(@method, 1..-1).should == "ymbol" - end - - it "returns a slice if the first range value begins at the end and the last begins at the end" do - :symbol.send(@method, -4..-1).should == "mbol" - end - end - - describe "that is out of bounds" do - it "returns nil if the first range value begins past the end" do - :symbol.send(@method, 10..12).should == nil - end - - it "returns a blank string if the first range value is within bounds and the last range value is not" do - :symbol.send(@method, -2..-10).should == "" - :symbol.send(@method, 2..-10).should == "" - end - - it "returns nil if the first range value starts from the end and is within bounds and the last value starts from the end and is greater than the length" do - :symbol.send(@method, -10..-12).should == nil - end - - it "returns nil if the first range value starts from the end and is out of bounds and the last value starts from the end and is less than the length" do - :symbol.send(@method, -10..-2).should == nil - end - end - - describe "with Float values" do - it "converts the first value to an Integer" do - :symbol.send(@method, 0.5..2).should == "sym" - end - - it "converts the last value to an Integer" do - :symbol.send(@method, 0..2.5).should == "sym" - end - end - end - - describe "with a Range subclass slice" do - it "returns a slice" do - range = SymbolSpecs::MyRange.new(1, 4) - :symbol.send(@method, range).should == "ymbo" - end - end - - describe "with a Regex slice" do - describe "without a capture index" do - it "returns a string of the match" do - :symbol.send(@method, /[^bol]+/).should == "sym" - end - - it "returns nil if the expression does not match" do - :symbol.send(@method, /0-9/).should == nil - end - - it "sets $~ to the MatchData if there is a match" do - :symbol.send(@method, /[^bol]+/) - $~[0].should == "sym" - end - - it "does not set $~ if there if there is not a match" do - :symbol.send(@method, /[0-9]+/) - $~.should == nil - end - end - - describe "with a capture index" do - it "returns a string of the complete match if the capture index is 0" do - :symbol.send(@method, /(sy)(mb)(ol)/, 0).should == "symbol" - end - - it "returns a string for the matched capture at the given index" do - :symbol.send(@method, /(sy)(mb)(ol)/, 1).should == "sy" - :symbol.send(@method, /(sy)(mb)(ol)/, -1).should == "ol" - end - - it "returns nil if there is no capture for the index" do - :symbol.send(@method, /(sy)(mb)(ol)/, 4).should == nil - :symbol.send(@method, /(sy)(mb)(ol)/, -4).should == nil - end - - it "converts the index to an Integer" do - :symbol.send(@method, /(sy)(mb)(ol)/, 1.5).should == "sy" - end - - describe "and an index that cannot be converted to an Integer" do - it "raises a TypeError when given an Hash" do - -> { :symbol.send(@method, /(sy)(mb)(ol)/, Hash.new) }.should.raise(TypeError) - end - - it "raises a TypeError when given an Array" do - -> { :symbol.send(@method, /(sy)(mb)(ol)/, Array.new) }.should.raise(TypeError) - end - - it "raises a TypeError when given an Object" do - -> { :symbol.send(@method, /(sy)(mb)(ol)/, Object.new) }.should.raise(TypeError) - end - end - - it "raises a TypeError if the index is nil" do - -> { :symbol.send(@method, /(sy)(mb)(ol)/, nil) }.should.raise(TypeError) - end - - it "sets $~ to the MatchData if there is a match" do - :symbol.send(@method, /(sy)(mb)(ol)/, 0) - $~[0].should == "symbol" - $~[1].should == "sy" - $~[2].should == "mb" - $~[3].should == "ol" - end - - it "does not set $~ to the MatchData if there is not a match" do - :symbol.send(@method, /0-9/, 0) - $~.should == nil - end - end - end - - describe "with a String slice" do - it "does not set $~" do - $~ = nil - :symbol.send(@method, "sym") - $~.should == nil - end - - it "returns a string if there is match" do - :symbol.send(@method, "ymb").should == "ymb" - end - - it "returns nil if there is not a match" do - :symbol.send(@method, "foo").should == nil - end - end -end diff --git a/core/symbol/shared/succ.rb b/core/symbol/shared/succ.rb deleted file mode 100644 index dde298207e..0000000000 --- a/core/symbol/shared/succ.rb +++ /dev/null @@ -1,18 +0,0 @@ -require_relative '../../../spec_helper' - -describe :symbol_succ, shared: true do - it "returns a successor" do - :abcd.send(@method).should == :abce - :THX1138.send(@method).should == :THX1139 - end - - it "propagates a 'carry'" do - :"1999zzz".send(@method).should == :"2000aaa" - :ZZZ9999.send(@method).should == :AAAA0000 - end - - it "increments non-alphanumeric characters when no alphanumeric characters are present" do - :"<>".send(@method).should == :"<>" - :"***".send(@method).should == :"**+" - end -end diff --git a/core/symbol/size_spec.rb b/core/symbol/size_spec.rb index 5e2aa8d4d2..b5d375b3aa 100644 --- a/core/symbol/size_spec.rb +++ b/core/symbol/size_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/length' describe "Symbol#size" do - it_behaves_like :symbol_length, :size + it "is an alias of Symbol#length" do + Symbol.instance_method(:size).should == Symbol.instance_method(:length) + end end diff --git a/core/symbol/slice_spec.rb b/core/symbol/slice_spec.rb index d2421c474c..050a2cf38c 100644 --- a/core/symbol/slice_spec.rb +++ b/core/symbol/slice_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/slice' describe "Symbol#slice" do - it_behaves_like :symbol_slice, :slice + it "is an alias of Symbol#[]" do + Symbol.instance_method(:slice).should == Symbol.instance_method(:[]) + end end diff --git a/core/symbol/succ_spec.rb b/core/symbol/succ_spec.rb index 694bfff862..893164a2a6 100644 --- a/core/symbol/succ_spec.rb +++ b/core/symbol/succ_spec.rb @@ -1,6 +1,18 @@ require_relative '../../spec_helper' -require_relative 'shared/succ' describe "Symbol#succ" do - it_behaves_like :symbol_succ, :succ + it "returns a successor" do + :abcd.succ.should == :abce + :THX1138.succ.should == :THX1139 + end + + it "propagates a 'carry'" do + :"1999zzz".succ.should == :"2000aaa" + :ZZZ9999.succ.should == :AAAA0000 + end + + it "increments non-alphanumeric characters when no alphanumeric characters are present" do + :"<>".succ.should == :"<>" + :"***".succ.should == :"**+" + end end diff --git a/core/symbol/to_s_spec.rb b/core/symbol/to_s_spec.rb index cd963faa28..2cb57c4cbc 100644 --- a/core/symbol/to_s_spec.rb +++ b/core/symbol/to_s_spec.rb @@ -1,6 +1,32 @@ require_relative '../../spec_helper' -require_relative 'shared/id2name' describe "Symbol#to_s" do - it_behaves_like :symbol_id2name, :to_s + it "returns the string corresponding to self" do + :rubinius.to_s.should == "rubinius" + :squash.to_s.should == "squash" + :[].to_s.should == "[]" + :@ruby.to_s.should == "@ruby" + :@@ruby.to_s.should == "@@ruby" + end + + it "returns a String in the same encoding as self" do + string = "ruby".encode("US-ASCII") + symbol = string.to_sym + + symbol.to_s.encoding.should == Encoding::US_ASCII + end + + ruby_version_is "3.4" do + it "warns about mutating returned string" do + -> { :bad!.to_s.upcase! }.should complain(/warning: string returned by :bad!.to_s will be frozen in the future/) + end + + it "does not warn about mutation when Warning[:deprecated] is false" do + deprecated = Warning[:deprecated] + Warning[:deprecated] = false + -> { :bad!.to_s.upcase! }.should_not complain + ensure + Warning[:deprecated] = deprecated + end + end end diff --git a/core/thread/exit_spec.rb b/core/thread/exit_spec.rb index b2e923c680..dbcd889898 100644 --- a/core/thread/exit_spec.rb +++ b/core/thread/exit_spec.rb @@ -1,6 +1,11 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -require_relative 'shared/exit' + +describe "Thread#exit" do + it "is an alias of Thread#kill" do + Thread.instance_method(:exit).should == Thread.instance_method(:kill) + end +end describe "Thread#exit!" do it "needs to be reviewed for spec completeness" diff --git a/core/thread/fork_spec.rb b/core/thread/fork_spec.rb index a2f4181298..60d574a185 100644 --- a/core/thread/fork_spec.rb +++ b/core/thread/fork_spec.rb @@ -1,9 +1,7 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' -require_relative 'shared/start' describe "Thread.fork" do - describe "Thread.start" do - it_behaves_like :thread_start, :fork + it "is an alias of Thread.start" do + Thread.method(:fork).should == Thread.method(:start) end end diff --git a/core/thread/inspect_spec.rb b/core/thread/inspect_spec.rb index bd6e0c31fc..fee401830a 100644 --- a/core/thread/inspect_spec.rb +++ b/core/thread/inspect_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/to_s' describe "Thread#inspect" do - it_behaves_like :thread_to_s, :inspect + it "is an alias of Thread#to_s" do + Thread.instance_method(:inspect).should == Thread.instance_method(:to_s) + end end diff --git a/core/thread/kill_spec.rb b/core/thread/kill_spec.rb index f9f1f46744..907cc5c4d8 100644 --- a/core/thread/kill_spec.rb +++ b/core/thread/kill_spec.rb @@ -1,12 +1,221 @@ require_relative '../../spec_helper' require_relative 'fixtures/classes' -require_relative 'shared/exit' # This spec randomly kills mspec worker like: https://ci.appveyor.com/project/ruby/ruby/builds/19473223/job/f69derxnlo09xhuj # TODO: Investigate the cause or at least print helpful logs, and remove this `platform_is_not` guard. platform_is_not :mingw do describe "Thread#kill" do - it_behaves_like :thread_exit, :kill + before :each do + ScratchPad.clear + end + + it "kills sleeping thread" do + sleeping_thread = Thread.new do + sleep + ScratchPad.record :after_sleep + end + Thread.pass while sleeping_thread.status and sleeping_thread.status != "sleep" + sleeping_thread.kill + sleeping_thread.join + ScratchPad.recorded.should == nil + end + + it "kills current thread" do + thread = Thread.new do + Thread.current.kill + ScratchPad.record :after_sleep + end + thread.join + ScratchPad.recorded.should == nil + end + + it "runs ensure clause" do + thread = ThreadSpecs.dying_thread_ensures(:kill) { ScratchPad.record :in_ensure_clause } + thread.join + ScratchPad.recorded.should == :in_ensure_clause + end + + it "runs nested ensure clauses" do + ScratchPad.record [] + @outer = Thread.new do + begin + @inner = Thread.new do + begin + sleep + ensure + ScratchPad << :inner_ensure_clause + end + end + sleep + ensure + ScratchPad << :outer_ensure_clause + @inner.kill + @inner.join + end + end + Thread.pass while @outer.status and @outer.status != "sleep" + Thread.pass until @inner + Thread.pass while @inner.status and @inner.status != "sleep" + @outer.kill + @outer.join + ScratchPad.recorded.should.include?(:inner_ensure_clause) + ScratchPad.recorded.should.include?(:outer_ensure_clause) + end + + it "does not set $!" do + thread = ThreadSpecs.dying_thread_ensures(:kill) { ScratchPad.record $! } + thread.join + ScratchPad.recorded.should == nil + end + + it "does not reset $!" do + ScratchPad.record [] + + exc = RuntimeError.new("foo") + thread = Thread.new do + begin + raise exc + ensure + ScratchPad << $! + begin + Thread.current.kill + ensure + ScratchPad << $! + end + end + end + thread.join + ScratchPad.recorded.should == [exc, exc] + end + + it "cannot be rescued" do + thread = Thread.new do + begin + Thread.current.kill + rescue Exception + ScratchPad.record :in_rescue + end + ScratchPad.record :end_of_thread_block + end + + thread.join + ScratchPad.recorded.should == nil + end + + it "kills the entire thread when a fiber is active" do + t = Thread.new do + Fiber.new do + sleep + end.resume + ScratchPad.record :fiber_resumed + end + Thread.pass while t.status and t.status != "sleep" + t.kill + t.join + ScratchPad.recorded.should == nil + end + + it "kills other fibers of that thread without running their ensure clauses" do + t = Thread.new do + f = Fiber.new do + ScratchPad.record :fiber_resumed + begin + Fiber.yield + ensure + ScratchPad.record :fiber_ensure + end + end + f.resume + sleep + end + Thread.pass until t.stop? + t.kill + t.join + ScratchPad.recorded.should == :fiber_resumed + end + + # This spec is a mess. It fails randomly, it hangs on MRI, it needs to be removed + quarantine! do + it "killing dying running does nothing" do + in_ensure_clause = false + exit_loop = true + t = ThreadSpecs.dying_thread_ensures do + in_ensure_clause = true + loop { if exit_loop then break end } + ScratchPad.record :after_stop + end + + Thread.pass until in_ensure_clause == true + 10.times { t.kill; Thread.pass } + exit_loop = true + t.join + ScratchPad.recorded.should == :after_stop + end + end + + quarantine! do + + it "propagates inner exception to Thread.join if there is an outer ensure clause" do + thread = ThreadSpecs.dying_thread_with_outer_ensure(:kill) { } + -> { thread.join }.should.raise(RuntimeError, "In dying thread") + end + + it "runs all outer ensure clauses even if inner ensure clause raises exception" do + ThreadSpecs.join_dying_thread_with_outer_ensure(:kill) { ScratchPad.record :in_outer_ensure_clause } + ScratchPad.recorded.should == :in_outer_ensure_clause + end + + it "sets $! in outer ensure clause if inner ensure clause raises exception" do + ThreadSpecs.join_dying_thread_with_outer_ensure(:kill) { ScratchPad.record $! } + ScratchPad.recorded.to_s.should == "In dying thread" + end + end + + it "can be rescued by outer rescue clause when inner ensure clause raises exception" do + thread = Thread.new do + begin + begin + Thread.current.kill + ensure + raise "In dying thread" + end + rescue Exception + ScratchPad.record $! + end + :end_of_thread_block + end + + thread.value.should == :end_of_thread_block + ScratchPad.recorded.to_s.should == "In dying thread" + end + + it "is deferred if ensure clause does Thread.stop" do + ThreadSpecs.wakeup_dying_sleeping_thread(:kill) { Thread.stop; ScratchPad.record :after_sleep } + ScratchPad.recorded.should == :after_sleep + end + + # Hangs on 1.8.6.114 OS X, possibly also on Linux + quarantine! do + it "is deferred if ensure clause sleeps" do + ThreadSpecs.wakeup_dying_sleeping_thread(:kill) { sleep; ScratchPad.record :after_sleep } + ScratchPad.recorded.should == :after_sleep + end + end + + # This case occurred in JRuby where native threads are used to provide + # the same behavior as MRI green threads. Key to this issue was the fact + # that the thread which called #exit in its block was also being explicitly + # sent #join from outside the thread. The 100.times provides a certain + # probability that the deadlock will occur. It was sufficient to reliably + # reproduce the deadlock in JRuby. + it "does not deadlock when called from within the thread while being joined from without" do + 100.times do + t = Thread.new { Thread.stop; Thread.current.kill } + Thread.pass while t.status and t.status != "sleep" + t.wakeup.should == t + t.join.should == t + end + end end describe "Thread.kill" do diff --git a/core/thread/shared/exit.rb b/core/thread/shared/exit.rb deleted file mode 100644 index a294c3a4d6..0000000000 --- a/core/thread/shared/exit.rb +++ /dev/null @@ -1,219 +0,0 @@ -describe :thread_exit, shared: true do - before :each do - ScratchPad.clear - end - - # This spec randomly kills mspec worker like: https://ci.appveyor.com/project/ruby/ruby/builds/19390874/job/wv1bsm8skd4e1pxl - # TODO: Investigate the cause or at least print helpful logs, and remove this `platform_is_not` guard. - platform_is_not :mingw do - - it "kills sleeping thread" do - sleeping_thread = Thread.new do - sleep - ScratchPad.record :after_sleep - end - Thread.pass while sleeping_thread.status and sleeping_thread.status != "sleep" - sleeping_thread.send(@method) - sleeping_thread.join - ScratchPad.recorded.should == nil - end - - it "kills current thread" do - thread = Thread.new do - Thread.current.send(@method) - ScratchPad.record :after_sleep - end - thread.join - ScratchPad.recorded.should == nil - end - - it "runs ensure clause" do - thread = ThreadSpecs.dying_thread_ensures(@method) { ScratchPad.record :in_ensure_clause } - thread.join - ScratchPad.recorded.should == :in_ensure_clause - end - - it "runs nested ensure clauses" do - ScratchPad.record [] - @outer = Thread.new do - begin - @inner = Thread.new do - begin - sleep - ensure - ScratchPad << :inner_ensure_clause - end - end - sleep - ensure - ScratchPad << :outer_ensure_clause - @inner.send(@method) - @inner.join - end - end - Thread.pass while @outer.status and @outer.status != "sleep" - Thread.pass until @inner - Thread.pass while @inner.status and @inner.status != "sleep" - @outer.send(@method) - @outer.join - ScratchPad.recorded.should.include?(:inner_ensure_clause) - ScratchPad.recorded.should.include?(:outer_ensure_clause) - end - - it "does not set $!" do - thread = ThreadSpecs.dying_thread_ensures(@method) { ScratchPad.record $! } - thread.join - ScratchPad.recorded.should == nil - end - - it "does not reset $!" do - ScratchPad.record [] - - exc = RuntimeError.new("foo") - thread = Thread.new do - begin - raise exc - ensure - ScratchPad << $! - begin - Thread.current.send(@method) - ensure - ScratchPad << $! - end - end - end - thread.join - ScratchPad.recorded.should == [exc, exc] - end - - it "cannot be rescued" do - thread = Thread.new do - begin - Thread.current.send(@method) - rescue Exception - ScratchPad.record :in_rescue - end - ScratchPad.record :end_of_thread_block - end - - thread.join - ScratchPad.recorded.should == nil - end - - it "kills the entire thread when a fiber is active" do - t = Thread.new do - Fiber.new do - sleep - end.resume - ScratchPad.record :fiber_resumed - end - Thread.pass while t.status and t.status != "sleep" - t.send(@method) - t.join - ScratchPad.recorded.should == nil - end - - it "kills other fibers of that thread without running their ensure clauses" do - t = Thread.new do - f = Fiber.new do - ScratchPad.record :fiber_resumed - begin - Fiber.yield - ensure - ScratchPad.record :fiber_ensure - end - end - f.resume - sleep - end - Thread.pass until t.stop? - t.send(@method) - t.join - ScratchPad.recorded.should == :fiber_resumed - end - - # This spec is a mess. It fails randomly, it hangs on MRI, it needs to be removed - quarantine! do - it "killing dying running does nothing" do - in_ensure_clause = false - exit_loop = true - t = ThreadSpecs.dying_thread_ensures do - in_ensure_clause = true - loop { if exit_loop then break end } - ScratchPad.record :after_stop - end - - Thread.pass until in_ensure_clause == true - 10.times { t.send(@method); Thread.pass } - exit_loop = true - t.join - ScratchPad.recorded.should == :after_stop - end - end - - quarantine! do - - it "propagates inner exception to Thread.join if there is an outer ensure clause" do - thread = ThreadSpecs.dying_thread_with_outer_ensure(@method) { } - -> { thread.join }.should.raise(RuntimeError, "In dying thread") - end - - it "runs all outer ensure clauses even if inner ensure clause raises exception" do - ThreadSpecs.join_dying_thread_with_outer_ensure(@method) { ScratchPad.record :in_outer_ensure_clause } - ScratchPad.recorded.should == :in_outer_ensure_clause - end - - it "sets $! in outer ensure clause if inner ensure clause raises exception" do - ThreadSpecs.join_dying_thread_with_outer_ensure(@method) { ScratchPad.record $! } - ScratchPad.recorded.to_s.should == "In dying thread" - end - end - - it "can be rescued by outer rescue clause when inner ensure clause raises exception" do - thread = Thread.new do - begin - begin - Thread.current.send(@method) - ensure - raise "In dying thread" - end - rescue Exception - ScratchPad.record $! - end - :end_of_thread_block - end - - thread.value.should == :end_of_thread_block - ScratchPad.recorded.to_s.should == "In dying thread" - end - - it "is deferred if ensure clause does Thread.stop" do - ThreadSpecs.wakeup_dying_sleeping_thread(@method) { Thread.stop; ScratchPad.record :after_sleep } - ScratchPad.recorded.should == :after_sleep - end - - # Hangs on 1.8.6.114 OS X, possibly also on Linux - quarantine! do - it "is deferred if ensure clause sleeps" do - ThreadSpecs.wakeup_dying_sleeping_thread(@method) { sleep; ScratchPad.record :after_sleep } - ScratchPad.recorded.should == :after_sleep - end - end - - # This case occurred in JRuby where native threads are used to provide - # the same behavior as MRI green threads. Key to this issue was the fact - # that the thread which called #exit in its block was also being explicitly - # sent #join from outside the thread. The 100.times provides a certain - # probability that the deadlock will occur. It was sufficient to reliably - # reproduce the deadlock in JRuby. - it "does not deadlock when called from within the thread while being joined from without" do - 100.times do - t = Thread.new { Thread.stop; Thread.current.send(@method) } - Thread.pass while t.status and t.status != "sleep" - t.wakeup.should == t - t.join.should == t - end - end - - end # platform_is_not :mingw -end diff --git a/core/thread/shared/start.rb b/core/thread/shared/start.rb deleted file mode 100644 index c5d62ab098..0000000000 --- a/core/thread/shared/start.rb +++ /dev/null @@ -1,41 +0,0 @@ -describe :thread_start, shared: true do - before :each do - ScratchPad.clear - end - - it "raises an ArgumentError if not passed a block" do - -> { - Thread.send(@method) - }.should.raise(ArgumentError) - end - - it "spawns a new Thread running the block" do - run = false - t = Thread.send(@method) { run = true } - t.should.is_a?(Thread) - t.join - - run.should == true - end - - it "respects Thread subclasses" do - c = Class.new(Thread) - t = c.send(@method) { } - t.should.is_a?(c) - - t.join - end - - it "does not call #initialize" do - c = Class.new(Thread) do - def initialize - ScratchPad.record :bad - end - end - - t = c.send(@method) { } - t.join - - ScratchPad.recorded.should == nil - end -end diff --git a/core/thread/shared/to_s.rb b/core/thread/shared/to_s.rb deleted file mode 100644 index 27e53ba4b8..0000000000 --- a/core/thread/shared/to_s.rb +++ /dev/null @@ -1,53 +0,0 @@ -require_relative '../fixtures/classes' - -describe :thread_to_s, shared: true do - it "returns a description including file and line number" do - thread, line = Thread.new { "hello" }, __LINE__ - thread.join - thread.send(@method).should =~ /^#$/ - end - - it "has a binary encoding" do - ThreadSpecs.status_of_current_thread.send(@method).encoding.should == Encoding::BINARY - end - - it "can check it's own status" do - ThreadSpecs.status_of_current_thread.send(@method).should.include?('run') - end - - it "describes a running thread" do - ThreadSpecs.status_of_running_thread.send(@method).should.include?('run') - end - - it "describes a sleeping thread" do - ThreadSpecs.status_of_sleeping_thread.send(@method).should.include?('sleep') - end - - it "describes a blocked thread" do - ThreadSpecs.status_of_blocked_thread.send(@method).should.include?('sleep') - end - - it "describes a completed thread" do - ThreadSpecs.status_of_completed_thread.send(@method).should.include?('dead') - end - - it "describes a killed thread" do - ThreadSpecs.status_of_killed_thread.send(@method).should.include?('dead') - end - - it "describes a thread with an uncaught exception" do - ThreadSpecs.status_of_thread_with_uncaught_exception.send(@method).should.include?('dead') - end - - it "describes a dying sleeping thread" do - ThreadSpecs.status_of_dying_sleeping_thread.send(@method).should.include?('sleep') - end - - it "reports aborting on a killed thread" do - ThreadSpecs.status_of_dying_running_thread.send(@method).should.include?('aborting') - end - - it "reports aborting on a killed thread after sleep" do - ThreadSpecs.status_of_dying_thread_after_sleep.send(@method).should.include?('aborting') - end -end diff --git a/core/thread/start_spec.rb b/core/thread/start_spec.rb index 3dd040f98b..a2ee52180b 100644 --- a/core/thread/start_spec.rb +++ b/core/thread/start_spec.rb @@ -1,9 +1,43 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' -require_relative 'shared/start' describe "Thread.start" do - describe "Thread.start" do - it_behaves_like :thread_start, :start + before :each do + ScratchPad.clear + end + + it "raises an ArgumentError if not passed a block" do + -> { + Thread.start + }.should.raise(ArgumentError) + end + + it "spawns a new Thread running the block" do + run = false + t = Thread.start { run = true } + t.should.is_a?(Thread) + t.join + + run.should == true + end + + it "respects Thread subclasses" do + c = Class.new(Thread) + t = c.start { } + t.should.is_a?(c) + + t.join + end + + it "does not call #initialize" do + c = Class.new(Thread) do + def initialize + ScratchPad.record :bad + end + end + + t = c.start { } + t.join + + ScratchPad.recorded.should == nil end end diff --git a/core/thread/terminate_spec.rb b/core/thread/terminate_spec.rb index cf6cab472b..68c431a0c0 100644 --- a/core/thread/terminate_spec.rb +++ b/core/thread/terminate_spec.rb @@ -1,7 +1,7 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' -require_relative 'shared/exit' describe "Thread#terminate" do - it_behaves_like :thread_exit, :terminate + it "is an alias of Thread#kill" do + Thread.instance_method(:terminate).should == Thread.instance_method(:kill) + end end diff --git a/core/thread/to_s_spec.rb b/core/thread/to_s_spec.rb index cb182a017f..2aef426de8 100644 --- a/core/thread/to_s_spec.rb +++ b/core/thread/to_s_spec.rb @@ -1,6 +1,54 @@ require_relative '../../spec_helper' -require_relative 'shared/to_s' +require_relative 'fixtures/classes' describe "Thread#to_s" do - it_behaves_like :thread_to_s, :to_s + it "returns a description including file and line number" do + thread, line = Thread.new { "hello" }, __LINE__ + thread.join + thread.to_s.should =~ /^#$/ + end + + it "has a binary encoding" do + ThreadSpecs.status_of_current_thread.to_s.encoding.should == Encoding::BINARY + end + + it "can check it's own status" do + ThreadSpecs.status_of_current_thread.to_s.should.include?('run') + end + + it "describes a running thread" do + ThreadSpecs.status_of_running_thread.to_s.should.include?('run') + end + + it "describes a sleeping thread" do + ThreadSpecs.status_of_sleeping_thread.to_s.should.include?('sleep') + end + + it "describes a blocked thread" do + ThreadSpecs.status_of_blocked_thread.to_s.should.include?('sleep') + end + + it "describes a completed thread" do + ThreadSpecs.status_of_completed_thread.to_s.should.include?('dead') + end + + it "describes a killed thread" do + ThreadSpecs.status_of_killed_thread.to_s.should.include?('dead') + end + + it "describes a thread with an uncaught exception" do + ThreadSpecs.status_of_thread_with_uncaught_exception.to_s.should.include?('dead') + end + + it "describes a dying sleeping thread" do + ThreadSpecs.status_of_dying_sleeping_thread.to_s.should.include?('sleep') + end + + it "reports aborting on a killed thread" do + ThreadSpecs.status_of_dying_running_thread.to_s.should.include?('aborting') + end + + it "reports aborting on a killed thread after sleep" do + ThreadSpecs.status_of_dying_thread_after_sleep.to_s.should.include?('aborting') + end end diff --git a/core/time/asctime_spec.rb b/core/time/asctime_spec.rb index a41ee531e4..d62565c984 100644 --- a/core/time/asctime_spec.rb +++ b/core/time/asctime_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/asctime' describe "Time#asctime" do - it_behaves_like :time_asctime, :asctime + it "is an alias of Time#ctime" do + Time.instance_method(:asctime).should == Time.instance_method(:ctime) + end end diff --git a/core/time/ctime_spec.rb b/core/time/ctime_spec.rb index 57e7cfd9ce..a99dbcc3d3 100644 --- a/core/time/ctime_spec.rb +++ b/core/time/ctime_spec.rb @@ -1,6 +1,8 @@ require_relative '../../spec_helper' -require_relative 'shared/asctime' describe "Time#ctime" do - it_behaves_like :time_asctime, :ctime + it "returns a canonical string representation of time" do + t = Time.now + t.ctime.should == t.strftime("%a %b %e %H:%M:%S %Y") + end end diff --git a/core/time/day_spec.rb b/core/time/day_spec.rb index 895bcd7a86..3dec17644c 100644 --- a/core/time/day_spec.rb +++ b/core/time/day_spec.rb @@ -1,6 +1,17 @@ require_relative '../../spec_helper' -require_relative 'shared/day' describe "Time#day" do - it_behaves_like :time_day, :day + it "returns the day of the month (1..n) for a local Time" do + with_timezone("CET", 1) do + Time.local(1970, 1, 1).day.should == 1 + end + end + + it "returns the day of the month for a UTC Time" do + Time.utc(1970, 1, 1).day.should == 1 + end + + it "returns the day of the month for a Time with a fixed offset" do + Time.new(2012, 1, 1, 0, 0, 0, -3600).day.should == 1 + end end diff --git a/core/time/dst_spec.rb b/core/time/dst_spec.rb index 436240aae5..42daf86875 100644 --- a/core/time/dst_spec.rb +++ b/core/time/dst_spec.rb @@ -1,6 +1,10 @@ require_relative '../../spec_helper' -require_relative 'shared/isdst' describe "Time#dst?" do - it_behaves_like :time_isdst, :dst? + it "returns whether time is during daylight saving time" do + with_timezone("America/Los_Angeles") do + Time.local(2007, 9, 9, 0, 0, 0).dst?.should == true + Time.local(2007, 1, 9, 0, 0, 0).dst?.should == false + end + end end diff --git a/core/time/getgm_spec.rb b/core/time/getgm_spec.rb index b5d45b1d9f..7698156c8c 100644 --- a/core/time/getgm_spec.rb +++ b/core/time/getgm_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/getgm' describe "Time#getgm" do - it_behaves_like :time_getgm, :getgm + it "is an alias of Time#getutc" do + Time.instance_method(:getgm).should == Time.instance_method(:getutc) + end end diff --git a/core/time/getutc_spec.rb b/core/time/getutc_spec.rb index 0cd9c17b00..1d49059a71 100644 --- a/core/time/getutc_spec.rb +++ b/core/time/getutc_spec.rb @@ -1,6 +1,11 @@ require_relative '../../spec_helper' -require_relative 'shared/getgm' describe "Time#getutc" do - it_behaves_like :time_getgm, :getutc + it "returns a new time which is the utc representation of time" do + # Testing with America/Regina here because it doesn't have DST. + with_timezone("CST", -6) do + t = Time.local(2007, 1, 9, 6, 0, 0) + t.getutc.should == Time.gm(2007, 1, 9, 12, 0, 0) + end + end end diff --git a/core/time/gm_spec.rb b/core/time/gm_spec.rb index 26dffbcedc..fbabede6ba 100644 --- a/core/time/gm_spec.rb +++ b/core/time/gm_spec.rb @@ -1,10 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/gm' -require_relative 'shared/time_params' describe "Time.gm" do - it_behaves_like :time_gm, :gm - it_behaves_like :time_params, :gm - it_behaves_like :time_params_10_arg, :gm - it_behaves_like :time_params_microseconds, :gm + it "is an alias of Time.utc" do + Time.method(:gm).should == Time.method(:utc) + end end diff --git a/core/time/gmt_offset_spec.rb b/core/time/gmt_offset_spec.rb index df417e6e4e..1769981753 100644 --- a/core/time/gmt_offset_spec.rb +++ b/core/time/gmt_offset_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/gmt_offset' describe "Time#gmt_offset" do - it_behaves_like :time_gmt_offset, :gmt_offset + it "is an alias of Time#utc_offset" do + Time.instance_method(:gmt_offset).should == Time.instance_method(:utc_offset) + end end diff --git a/core/time/gmt_spec.rb b/core/time/gmt_spec.rb index 840f59e0e8..38e98cc43c 100644 --- a/core/time/gmt_spec.rb +++ b/core/time/gmt_spec.rb @@ -1,8 +1,7 @@ require_relative '../../spec_helper' describe "Time#gmt?" do - it "returns true if time represents a time in UTC (GMT)" do - Time.now.should_not.gmt? - Time.now.gmtime.should.gmt? + it "is an alias of Time#utc?" do + Time.instance_method(:gmt?).should == Time.instance_method(:utc?) end end diff --git a/core/time/gmtime_spec.rb b/core/time/gmtime_spec.rb index d965cd541d..e7e1d4ffb2 100644 --- a/core/time/gmtime_spec.rb +++ b/core/time/gmtime_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/gmtime' describe "Time#gmtime" do - it_behaves_like :time_gmtime, :gmtime + it "is an alias of Time#utc" do + Time.instance_method(:gmtime).should == Time.instance_method(:utc) + end end diff --git a/core/time/gmtoff_spec.rb b/core/time/gmtoff_spec.rb index fa28520e9e..c7d801a681 100644 --- a/core/time/gmtoff_spec.rb +++ b/core/time/gmtoff_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/gmt_offset' describe "Time#gmtoff" do - it_behaves_like :time_gmt_offset, :gmtoff + it "is an alias of Time#utc_offset" do + Time.instance_method(:gmtoff).should == Time.instance_method(:utc_offset) + end end diff --git a/core/time/isdst_spec.rb b/core/time/isdst_spec.rb index 173230ca07..759953cca7 100644 --- a/core/time/isdst_spec.rb +++ b/core/time/isdst_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/isdst' describe "Time#isdst" do - it_behaves_like :time_isdst, :isdst + it "is an alias of Time#dst?" do + Time.instance_method(:isdst).should == Time.instance_method(:dst?) + end end diff --git a/core/time/iso8601_spec.rb b/core/time/iso8601_spec.rb index ad60c3bb32..cfd44a24db 100644 --- a/core/time/iso8601_spec.rb +++ b/core/time/iso8601_spec.rb @@ -1,6 +1,9 @@ require_relative '../../spec_helper' -require_relative 'shared/xmlschema' describe "Time#iso8601" do - it_behaves_like :time_xmlschema, :iso8601 + ruby_version_is "3.4" do + it "is an alias of Time#xmlschema" do + Time.instance_method(:iso8601).should == Time.instance_method(:xmlschema) + end + end end diff --git a/core/time/mday_spec.rb b/core/time/mday_spec.rb index 3c21939890..78021785f9 100644 --- a/core/time/mday_spec.rb +++ b/core/time/mday_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/day' describe "Time#mday" do - it_behaves_like :time_day, :mday + it "is an alias of Time#day" do + Time.instance_method(:mday).should == Time.instance_method(:day) + end end diff --git a/core/time/mktime_spec.rb b/core/time/mktime_spec.rb index 78a6a6e772..83bf12293a 100644 --- a/core/time/mktime_spec.rb +++ b/core/time/mktime_spec.rb @@ -1,11 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/local' -require_relative 'shared/time_params' describe "Time.mktime" do - it_behaves_like :time_local, :mktime - it_behaves_like :time_local_10_arg, :mktime - it_behaves_like :time_params, :mktime - it_behaves_like :time_params_10_arg, :mktime - it_behaves_like :time_params_microseconds, :mktime + it "is an alias of Time.local" do + Time.method(:mktime).should == Time.method(:local) + end end diff --git a/core/time/mon_spec.rb b/core/time/mon_spec.rb index f41b39648b..d57549dadd 100644 --- a/core/time/mon_spec.rb +++ b/core/time/mon_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/month' describe "Time#mon" do - it_behaves_like :time_month, :mon + it "is an alias of Time#month" do + Time.instance_method(:mon).should == Time.instance_method(:month) + end end diff --git a/core/time/month_spec.rb b/core/time/month_spec.rb index 81e20384ab..eae0e85acd 100644 --- a/core/time/month_spec.rb +++ b/core/time/month_spec.rb @@ -1,6 +1,17 @@ require_relative '../../spec_helper' -require_relative 'shared/month' describe "Time#month" do - it_behaves_like :time_month, :month + it "returns the month of the year for a local Time" do + with_timezone("CET", 1) do + Time.local(1970, 1).month.should == 1 + end + end + + it "returns the month of the year for a UTC Time" do + Time.utc(1970, 1).month.should == 1 + end + + it "returns the four digit year for a Time with a fixed offset" do + Time.new(2012, 1, 1, 0, 0, 0, -3600).month.should == 1 + end end diff --git a/core/time/shared/asctime.rb b/core/time/shared/asctime.rb deleted file mode 100644 index d096666863..0000000000 --- a/core/time/shared/asctime.rb +++ /dev/null @@ -1,6 +0,0 @@ -describe :time_asctime, shared: true do - it "returns a canonical string representation of time" do - t = Time.now - t.send(@method).should == t.strftime("%a %b %e %H:%M:%S %Y") - end -end diff --git a/core/time/shared/day.rb b/core/time/shared/day.rb deleted file mode 100644 index 472dc959c1..0000000000 --- a/core/time/shared/day.rb +++ /dev/null @@ -1,15 +0,0 @@ -describe :time_day, shared: true do - it "returns the day of the month (1..n) for a local Time" do - with_timezone("CET", 1) do - Time.local(1970, 1, 1).send(@method).should == 1 - end - end - - it "returns the day of the month for a UTC Time" do - Time.utc(1970, 1, 1).send(@method).should == 1 - end - - it "returns the day of the month for a Time with a fixed offset" do - Time.new(2012, 1, 1, 0, 0, 0, -3600).send(@method).should == 1 - end -end diff --git a/core/time/shared/getgm.rb b/core/time/shared/getgm.rb deleted file mode 100644 index 3576365772..0000000000 --- a/core/time/shared/getgm.rb +++ /dev/null @@ -1,9 +0,0 @@ -describe :time_getgm, shared: true do - it "returns a new time which is the utc representation of time" do - # Testing with America/Regina here because it doesn't have DST. - with_timezone("CST", -6) do - t = Time.local(2007, 1, 9, 6, 0, 0) - t.send(@method).should == Time.gm(2007, 1, 9, 12, 0, 0) - end - end -end diff --git a/core/time/shared/gm.rb b/core/time/shared/gm.rb deleted file mode 100644 index 0ee602c837..0000000000 --- a/core/time/shared/gm.rb +++ /dev/null @@ -1,70 +0,0 @@ -describe :time_gm, shared: true do - it "creates a time based on given values, interpreted as UTC (GMT)" do - Time.send(@method, 2000,"jan",1,20,15,1).inspect.should == "2000-01-01 20:15:01 UTC" - end - - it "creates a time based on given C-style gmtime arguments, interpreted as UTC (GMT)" do - time = Time.send(@method, 1, 15, 20, 1, 1, 2000, :ignored, :ignored, :ignored, :ignored) - time.inspect.should == "2000-01-01 20:15:01 UTC" - end - - it "interprets pre-Gregorian reform dates using Gregorian proleptic calendar" do - Time.send(@method, 1582, 10, 4, 12).to_i.should == -12220200000 # 2299150j - end - - it "interprets Julian-Gregorian gap dates using Gregorian proleptic calendar" do - Time.send(@method, 1582, 10, 14, 12).to_i.should == -12219336000 # 2299160j - end - - it "interprets post-Gregorian reform dates using Gregorian calendar" do - Time.send(@method, 1582, 10, 15, 12).to_i.should == -12219249600 # 2299161j - end - - it "handles fractional usec close to rounding limit" do - time = Time.send(@method, 2000, 1, 1, 12, 30, 0, 9999r/10000) - - time.usec.should == 0 - time.nsec.should == 999 - end - - guard -> { - with_timezone 'right/UTC' do - (Time.gm(1972, 6, 30, 23, 59, 59) + 1).sec == 60 - end - } do - it "handles real leap seconds in zone 'right/UTC'" do - with_timezone 'right/UTC' do - time = Time.send(@method, 1972, 6, 30, 23, 59, 60) - - time.sec.should == 60 - time.min.should == 59 - time.hour.should == 23 - time.day.should == 30 - time.month.should == 6 - end - end - end - - it "handles bad leap seconds by carrying values forward" do - with_timezone 'UTC' do - time = Time.send(@method, 2017, 7, 5, 23, 59, 60) - time.sec.should == 0 - time.min.should == 0 - time.hour.should == 0 - time.day.should == 6 - time.month.should == 7 - end - end - - it "handles a value of 60 for seconds by carrying values forward in zone 'UTC'" do - with_timezone 'UTC' do - time = Time.send(@method, 1972, 6, 30, 23, 59, 60) - - time.sec.should == 0 - time.min.should == 0 - time.hour.should == 0 - time.day.should == 1 - time.month.should == 7 - end - end -end diff --git a/core/time/shared/gmt_offset.rb b/core/time/shared/gmt_offset.rb deleted file mode 100644 index 839566c249..0000000000 --- a/core/time/shared/gmt_offset.rb +++ /dev/null @@ -1,59 +0,0 @@ -describe :time_gmt_offset, shared: true do - it "returns the offset in seconds between the timezone of time and UTC" do - with_timezone("AST", 3) do - Time.new.send(@method).should == 10800 - end - end - - it "returns 0 when the date is UTC" do - with_timezone("AST", 3) do - Time.new.utc.send(@method).should == 0 - end - end - - platform_is_not :windows do - it "returns the correct offset for US Eastern time zone around daylight savings time change" do - # "2010-03-14 01:59:59 -0500" + 1 ==> "2010-03-14 03:00:00 -0400" - with_timezone("EST5EDT") do - t = Time.local(2010,3,14,1,59,59) - t.send(@method).should == -5*60*60 - (t + 1).send(@method).should == -4*60*60 - end - end - - it "returns the correct offset for Hawaii around daylight savings time change" do - # "2010-03-14 01:59:59 -1000" + 1 ==> "2010-03-14 02:00:00 -1000" - with_timezone("Pacific/Honolulu") do - t = Time.local(2010,3,14,1,59,59) - t.send(@method).should == -10*60*60 - (t + 1).send(@method).should == -10*60*60 - end - end - - it "returns the correct offset for New Zealand around daylight savings time change" do - # "2010-04-04 02:59:59 +1300" + 1 ==> "2010-04-04 02:00:00 +1200" - with_timezone("Pacific/Auckland") do - t = Time.local(2010,4,4,1,59,59) + (60 * 60) - t.send(@method).should == 13*60*60 - (t + 1).send(@method).should == 12*60*60 - end - end - end - - it "returns offset as Rational" do - Time.new(2010,4,4,1,59,59,7245).send(@method).should == 7245 - Time.new(2010,4,4,1,59,59,7245.5).send(@method).should == Rational(14491,2) - end - - context 'given positive offset' do - it 'returns a positive offset' do - Time.new(2013,3,17,nil,nil,nil,"+03:00").send(@method).should == 10800 - end - end - - context 'given negative offset' do - it 'returns a negative offset' do - Time.new(2013,3,17,nil,nil,nil,"-03:00").send(@method).should == -10800 - end - end -end diff --git a/core/time/shared/gmtime.rb b/core/time/shared/gmtime.rb deleted file mode 100644 index aa76b436cc..0000000000 --- a/core/time/shared/gmtime.rb +++ /dev/null @@ -1,40 +0,0 @@ -describe :time_gmtime, shared: true do - it "converts self to UTC, modifying the receiver" do - # Testing with America/Regina here because it doesn't have DST. - with_timezone("CST", -6) do - t = Time.local(2007, 1, 9, 6, 0, 0) - t.send(@method) - # Time#== compensates for time zones, so check all parts separately - t.year.should == 2007 - t.month.should == 1 - t.mday.should == 9 - t.hour.should == 12 - t.min.should == 0 - t.sec.should == 0 - t.zone.should == "UTC" - end - end - - it "returns self" do - with_timezone("CST", -6) do - t = Time.local(2007, 1, 9, 12, 0, 0) - t.send(@method).should.equal?(t) - end - end - - describe "on a frozen time" do - it "does not raise an error if already in UTC" do - time = Time.gm(2007, 1, 9, 12, 0, 0) - time.freeze - time.send(@method).should.equal?(time) - end - - it "raises a FrozenError if the time is not UTC" do - with_timezone("CST", -6) do - time = Time.now - time.freeze - -> { time.send(@method) }.should.raise(FrozenError) - end - end - end -end diff --git a/core/time/shared/isdst.rb b/core/time/shared/isdst.rb deleted file mode 100644 index bc6d139230..0000000000 --- a/core/time/shared/isdst.rb +++ /dev/null @@ -1,8 +0,0 @@ -describe :time_isdst, shared: true do - it "dst? returns whether time is during daylight saving time" do - with_timezone("America/Los_Angeles") do - Time.local(2007, 9, 9, 0, 0, 0).send(@method).should == true - Time.local(2007, 1, 9, 0, 0, 0).send(@method).should == false - end - end -end diff --git a/core/time/shared/month.rb b/core/time/shared/month.rb deleted file mode 100644 index 31ca679557..0000000000 --- a/core/time/shared/month.rb +++ /dev/null @@ -1,15 +0,0 @@ -describe :time_month, shared: true do - it "returns the month of the year for a local Time" do - with_timezone("CET", 1) do - Time.local(1970, 1).send(@method).should == 1 - end - end - - it "returns the month of the year for a UTC Time" do - Time.utc(1970, 1).send(@method).should == 1 - end - - it "returns the four digit year for a Time with a fixed offset" do - Time.new(2012, 1, 1, 0, 0, 0, -3600).send(@method).should == 1 - end -end diff --git a/core/time/shared/to_i.rb b/core/time/shared/to_i.rb deleted file mode 100644 index 06c966b708..0000000000 --- a/core/time/shared/to_i.rb +++ /dev/null @@ -1,16 +0,0 @@ -describe :time_to_i, shared: true do - it "returns the value of time as an integer number of seconds since epoch" do - Time.at(0).send(@method).should == 0 - end - - it "doesn't return an actual number of seconds in time" do - Time.at(65.5).send(@method).should == 65 - end - - it "rounds fractional seconds toward zero" do - t = Time.utc(1960, 1, 1, 0, 0, 0, 999_999) - - t.to_f.to_i.should == -315619199 - t.to_i.should == -315619200 - end -end diff --git a/core/time/shared/xmlschema.rb b/core/time/shared/xmlschema.rb deleted file mode 100644 index d68c18df36..0000000000 --- a/core/time/shared/xmlschema.rb +++ /dev/null @@ -1,31 +0,0 @@ -describe :time_xmlschema, shared: true do - ruby_version_is "3.4" do - it "generates ISO-8601 strings in Z for UTC times" do - t = Time.utc(1985, 4, 12, 23, 20, 50, 521245) - t.send(@method).should == "1985-04-12T23:20:50Z" - t.send(@method, 2).should == "1985-04-12T23:20:50.52Z" - t.send(@method, 9).should == "1985-04-12T23:20:50.521245000Z" - end - - it "generates ISO-8601 string with timeone offset for non-UTC times" do - t = Time.new(1985, 4, 12, 23, 20, 50, "+02:00") - t.send(@method).should == "1985-04-12T23:20:50+02:00" - t.send(@method, 2).should == "1985-04-12T23:20:50.00+02:00" - end - - it "year is always at least 4 digits" do - t = Time.utc(12, 4, 12) - t.send(@method).should == "0012-04-12T00:00:00Z" - end - - it "year can be more than 4 digits" do - t = Time.utc(40_000, 4, 12) - t.send(@method).should == "40000-04-12T00:00:00Z" - end - - it "year can be negative" do - t = Time.utc(-2000, 4, 12) - t.send(@method).should == "-2000-04-12T00:00:00Z" - end - end -end diff --git a/core/time/to_i_spec.rb b/core/time/to_i_spec.rb index 54929d1e18..00c4215d31 100644 --- a/core/time/to_i_spec.rb +++ b/core/time/to_i_spec.rb @@ -1,6 +1,18 @@ require_relative '../../spec_helper' -require_relative 'shared/to_i' describe "Time#to_i" do - it_behaves_like :time_to_i, :to_i + it "returns the value of time as an integer number of seconds since epoch" do + Time.at(0).to_i.should == 0 + end + + it "doesn't return an actual number of seconds in time" do + Time.at(65.5).to_i.should == 65 + end + + it "rounds fractional seconds toward zero" do + t = Time.utc(1960, 1, 1, 0, 0, 0, 999_999) + + t.to_f.to_i.should == -315619199 + t.to_i.should == -315619200 + end end diff --git a/core/time/tv_nsec_spec.rb b/core/time/tv_nsec_spec.rb index feb7998b16..802138bf3a 100644 --- a/core/time/tv_nsec_spec.rb +++ b/core/time/tv_nsec_spec.rb @@ -1,5 +1,7 @@ require_relative '../../spec_helper' describe "Time#tv_nsec" do - it "needs to be reviewed for spec completeness" + it "is an alias of Time#nsec" do + Time.instance_method(:tv_nsec).should == Time.instance_method(:nsec) + end end diff --git a/core/time/tv_sec_spec.rb b/core/time/tv_sec_spec.rb index f83e1fbfdd..21bdb53ee6 100644 --- a/core/time/tv_sec_spec.rb +++ b/core/time/tv_sec_spec.rb @@ -1,6 +1,7 @@ require_relative '../../spec_helper' -require_relative 'shared/to_i' describe "Time#tv_sec" do - it_behaves_like :time_to_i, :tv_sec + it "is an alias of Time#to_i" do + Time.instance_method(:tv_sec).should == Time.instance_method(:to_i) + end end diff --git a/core/time/tv_usec_spec.rb b/core/time/tv_usec_spec.rb index f0de4f4a9c..e922ee5625 100644 --- a/core/time/tv_usec_spec.rb +++ b/core/time/tv_usec_spec.rb @@ -1,5 +1,7 @@ require_relative '../../spec_helper' describe "Time#tv_usec" do - it "needs to be reviewed for spec completeness" + it "is an alias of Time#usec" do + Time.instance_method(:tv_usec).should == Time.instance_method(:usec) + end end diff --git a/core/time/utc_offset_spec.rb b/core/time/utc_offset_spec.rb index 17c031b8c6..8d2fff2012 100644 --- a/core/time/utc_offset_spec.rb +++ b/core/time/utc_offset_spec.rb @@ -1,6 +1,61 @@ require_relative '../../spec_helper' -require_relative 'shared/gmt_offset' describe "Time#utc_offset" do - it_behaves_like :time_gmt_offset, :utc_offset + it "returns the offset in seconds between the timezone of time and UTC" do + with_timezone("AST", 3) do + Time.new.utc_offset.should == 10800 + end + end + + it "returns 0 when the date is UTC" do + with_timezone("AST", 3) do + Time.new.utc.utc_offset.should == 0 + end + end + + platform_is_not :windows do + it "returns the correct offset for US Eastern time zone around daylight savings time change" do + # "2010-03-14 01:59:59 -0500" + 1 ==> "2010-03-14 03:00:00 -0400" + with_timezone("EST5EDT") do + t = Time.local(2010,3,14,1,59,59) + t.utc_offset.should == -5*60*60 + (t + 1).utc_offset.should == -4*60*60 + end + end + + it "returns the correct offset for Hawaii around daylight savings time change" do + # "2010-03-14 01:59:59 -1000" + 1 ==> "2010-03-14 02:00:00 -1000" + with_timezone("Pacific/Honolulu") do + t = Time.local(2010,3,14,1,59,59) + t.utc_offset.should == -10*60*60 + (t + 1).utc_offset.should == -10*60*60 + end + end + + it "returns the correct offset for New Zealand around daylight savings time change" do + # "2010-04-04 02:59:59 +1300" + 1 ==> "2010-04-04 02:00:00 +1200" + with_timezone("Pacific/Auckland") do + t = Time.local(2010,4,4,1,59,59) + (60 * 60) + t.utc_offset.should == 13*60*60 + (t + 1).utc_offset.should == 12*60*60 + end + end + end + + it "returns offset as Rational" do + Time.new(2010,4,4,1,59,59,7245).utc_offset.should == 7245 + Time.new(2010,4,4,1,59,59,7245.5).utc_offset.should == Rational(14491,2) + end + + context 'given positive offset' do + it 'returns a positive offset' do + Time.new(2013,3,17,nil,nil,nil,"+03:00").utc_offset.should == 10800 + end + end + + context 'given negative offset' do + it 'returns a negative offset' do + Time.new(2013,3,17,nil,nil,nil,"-03:00").utc_offset.should == -10800 + end + end end diff --git a/core/time/utc_spec.rb b/core/time/utc_spec.rb index ab3c0df657..35c1daa9e5 100644 --- a/core/time/utc_spec.rb +++ b/core/time/utc_spec.rb @@ -1,6 +1,4 @@ require_relative '../../spec_helper' -require_relative 'shared/gm' -require_relative 'shared/gmtime' require_relative 'shared/time_params' describe "Time#utc?" do @@ -11,7 +9,7 @@ it "treats time as UTC what was created in different ways" do Time.now.utc.utc?.should == true - Time.now.gmtime.utc?.should == true + Time.now.utc.utc?.should == true Time.now.getgm.utc?.should == true Time.now.getutc.utc?.should == true Time.utc(2022).utc?.should == true @@ -55,12 +53,117 @@ end describe "Time.utc" do - it_behaves_like :time_gm, :utc it_behaves_like :time_params, :utc it_behaves_like :time_params_10_arg, :utc it_behaves_like :time_params_microseconds, :utc + + it "creates a time based on given values, interpreted as UTC (GMT)" do + Time.utc(2000,"jan",1,20,15,1).inspect.should == "2000-01-01 20:15:01 UTC" + end + + it "creates a time based on given C-style gmtime arguments, interpreted as UTC (GMT)" do + time = Time.utc(1, 15, 20, 1, 1, 2000, :ignored, :ignored, :ignored, :ignored) + time.inspect.should == "2000-01-01 20:15:01 UTC" + end + + it "interprets pre-Gregorian reform dates using Gregorian proleptic calendar" do + Time.utc(1582, 10, 4, 12).to_i.should == -12220200000 # 2299150j + end + + it "interprets Julian-Gregorian gap dates using Gregorian proleptic calendar" do + Time.utc(1582, 10, 14, 12).to_i.should == -12219336000 # 2299160j + end + + it "interprets post-Gregorian reform dates using Gregorian calendar" do + Time.utc(1582, 10, 15, 12).to_i.should == -12219249600 # 2299161j + end + + it "handles fractional usec close to rounding limit" do + time = Time.utc(2000, 1, 1, 12, 30, 0, 9999r/10000) + + time.usec.should == 0 + time.nsec.should == 999 + end + + guard -> { + with_timezone 'right/UTC' do + (Time.utc(1972, 6, 30, 23, 59, 59) + 1).sec == 60 + end + } do + it "handles real leap seconds in zone 'right/UTC'" do + with_timezone 'right/UTC' do + time = Time.utc(1972, 6, 30, 23, 59, 60) + + time.sec.should == 60 + time.min.should == 59 + time.hour.should == 23 + time.day.should == 30 + time.month.should == 6 + end + end + end + + it "handles bad leap seconds by carrying values forward" do + with_timezone 'UTC' do + time = Time.utc(2017, 7, 5, 23, 59, 60) + time.sec.should == 0 + time.min.should == 0 + time.hour.should == 0 + time.day.should == 6 + time.month.should == 7 + end + end + + it "handles a value of 60 for seconds by carrying values forward in zone 'UTC'" do + with_timezone 'UTC' do + time = Time.utc(1972, 6, 30, 23, 59, 60) + + time.sec.should == 0 + time.min.should == 0 + time.hour.should == 0 + time.day.should == 1 + time.month.should == 7 + end + end end describe "Time#utc" do - it_behaves_like :time_gmtime, :utc + it "converts self to UTC, modifying the receiver" do + # Testing with America/Regina here because it doesn't have DST. + with_timezone("CST", -6) do + t = Time.local(2007, 1, 9, 6, 0, 0) + t.utc + # Time#== compensates for time zones, so check all parts separately + t.year.should == 2007 + t.month.should == 1 + t.mday.should == 9 + t.hour.should == 12 + t.min.should == 0 + t.sec.should == 0 + t.zone.should == "UTC" + end + end + + it "returns self" do + with_timezone("CST", -6) do + t = Time.local(2007, 1, 9, 12, 0, 0) + t.utc.should.equal?(t) + end + end + + describe "on a frozen time" do + it "does not raise an error if already in UTC" do + time = Time.gm(2007, 1, 9, 12, 0, 0) + time.freeze + time.utc.should.equal?(time) + end + + it "raises a FrozenError if the time is not UTC" do + with_timezone("CST", -6) do + time = Time.now + time.freeze + -> { time.utc }.should.raise(FrozenError) + end + end + end end diff --git a/core/time/xmlschema_spec.rb b/core/time/xmlschema_spec.rb index bdf1dc7923..026b795f58 100644 --- a/core/time/xmlschema_spec.rb +++ b/core/time/xmlschema_spec.rb @@ -1,6 +1,33 @@ require_relative '../../spec_helper' -require_relative 'shared/xmlschema' describe "Time#xmlschema" do - it_behaves_like :time_xmlschema, :xmlschema + ruby_version_is "3.4" do + it "generates ISO-8601 strings in Z for UTC times" do + t = Time.utc(1985, 4, 12, 23, 20, 50, 521245) + t.xmlschema.should == "1985-04-12T23:20:50Z" + t.xmlschema(2).should == "1985-04-12T23:20:50.52Z" + t.xmlschema(9).should == "1985-04-12T23:20:50.521245000Z" + end + + it "generates ISO-8601 string with timezone offset for non-UTC times" do + t = Time.new(1985, 4, 12, 23, 20, 50, "+02:00") + t.xmlschema.should == "1985-04-12T23:20:50+02:00" + t.xmlschema(2).should == "1985-04-12T23:20:50.00+02:00" + end + + it "year is always at least 4 digits" do + t = Time.utc(12, 4, 12) + t.xmlschema.should == "0012-04-12T00:00:00Z" + end + + it "year can be more than 4 digits" do + t = Time.utc(40_000, 4, 12) + t.xmlschema.should == "40000-04-12T00:00:00Z" + end + + it "year can be negative" do + t = Time.utc(-2000, 4, 12) + t.xmlschema.should == "-2000-04-12T00:00:00Z" + end + end end diff --git a/core/unboundmethod/inspect_spec.rb b/core/unboundmethod/inspect_spec.rb index 3abed94f7f..b0fcfd00ea 100644 --- a/core/unboundmethod/inspect_spec.rb +++ b/core/unboundmethod/inspect_spec.rb @@ -1,9 +1,7 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' -require_relative 'shared/to_s' -require_relative '../method/shared/aliased_inspect' describe "UnboundMethod#inspect" do - it_behaves_like :unboundmethod_to_s, :inspect - it_behaves_like :method_to_s_aliased, :inspect, -> meth { meth.unbind } + it "is an alias of UnboundMethod#to_s" do + UnboundMethod.instance_method(:inspect).should == UnboundMethod.instance_method(:to_s) + end end diff --git a/core/unboundmethod/shared/to_s.rb b/core/unboundmethod/shared/to_s.rb deleted file mode 100644 index 848c1eba2e..0000000000 --- a/core/unboundmethod/shared/to_s.rb +++ /dev/null @@ -1,33 +0,0 @@ -require_relative '../../../spec_helper' -require_relative '../fixtures/classes' - -describe :unboundmethod_to_s, shared: true do - before :each do - @from_module = UnboundMethodSpecs::Methods.instance_method(:from_mod) - @from_method = UnboundMethodSpecs::Methods.new.method(:from_mod).unbind - end - - it "returns a String" do - @from_module.send(@method).should.is_a?(String) - @from_method.send(@method).should.is_a?(String) - end - - it "the String reflects that this is an UnboundMethod object" do - @from_module.send(@method).should =~ /\bUnboundMethod\b/ - @from_method.send(@method).should =~ /\bUnboundMethod\b/ - end - - it "the String shows the method name, Module defined in and Module extracted from" do - @from_module.send(@method).should =~ /\bfrom_mod\b/ - @from_module.send(@method).should =~ /\bUnboundMethodSpecs::Mod\b/ - end - - it "returns a String including all details" do - @from_module.send(@method).should.start_with? "# meth { meth.unbind } + + before :each do + @from_module = UnboundMethodSpecs::Methods.instance_method(:from_mod) + @from_method = UnboundMethodSpecs::Methods.new.method(:from_mod).unbind + end + + it "returns a String" do + @from_module.to_s.should.is_a?(String) + @from_method.to_s.should.is_a?(String) + end + + it "the String reflects that this is an UnboundMethod object" do + @from_module.to_s.should =~ /\bUnboundMethod\b/ + @from_method.to_s.should =~ /\bUnboundMethod\b/ + end + + it "the String shows the method name, Module defined in and Module extracted from" do + @from_module.to_s.should =~ /\bfrom_mod\b/ + @from_module.to_s.should =~ /\bUnboundMethodSpecs::Mod\b/ + end + + it "returns a String including all details" do + @from_module.to_s.should.start_with? "#