1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63293 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
eregon 2018-04-28 19:50:06 +00:00
parent b864bd05bf
commit 4fbb9aa3cb
145 changed files with 2847 additions and 2596 deletions

View file

@ -1,6 +1,6 @@
# This configuration was generated by # This configuration was generated by
# `rubocop --auto-gen-config` # `rubocop --auto-gen-config`
# on 2017-12-15 22:14:22 +0900 using RuboCop version 0.52.0. # on 2018-04-03 22:23:59 +0900 using RuboCop version 0.54.0.
# The point is for the user to remove these configuration records # The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base. # one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new # Note that changes in the inspected code, or installation of new
@ -20,11 +20,6 @@ Lint/DuplicateMethods:
- 'core/unboundmethod/fixtures/classes.rb' - 'core/unboundmethod/fixtures/classes.rb'
- 'fixtures/class.rb' - 'fixtures/class.rb'
# Offense count: 4
Lint/EmptyWhen:
Exclude:
- 'language/case_spec.rb'
# Offense count: 5 # Offense count: 5
Lint/EnsureReturn: Lint/EnsureReturn:
Exclude: Exclude:
@ -43,7 +38,7 @@ Lint/FormatParameterMismatch:
- 'core/kernel/shared/sprintf.rb' - 'core/kernel/shared/sprintf.rb'
- 'core/string/modulo_spec.rb' - 'core/string/modulo_spec.rb'
# Offense count: 28 # Offense count: 29
Lint/HandleExceptions: Lint/HandleExceptions:
Enabled: false Enabled: false
@ -59,7 +54,7 @@ Lint/IneffectiveAccessModifier:
- 'core/module/fixtures/classes.rb' - 'core/module/fixtures/classes.rb'
- 'language/fixtures/private.rb' - 'language/fixtures/private.rb'
# Offense count: 5 # Offense count: 6
# Cop supports --auto-correct. # Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle. # Configuration parameters: EnforcedStyle.
# SupportedStyles: runtime_error, standard_error # SupportedStyles: runtime_error, standard_error
@ -69,13 +64,13 @@ Lint/InheritException:
- 'core/exception/fixtures/common.rb' - 'core/exception/fixtures/common.rb'
- 'core/module/fixtures/autoload_ex1.rb' - 'core/module/fixtures/autoload_ex1.rb'
# Offense count: 3 # Offense count: 5
# Cop supports --auto-correct. # Cop supports --auto-correct.
Lint/LiteralInInterpolation: Lint/LiteralInInterpolation:
Exclude: Exclude:
- 'core/module/refine_spec.rb'
- 'language/defined_spec.rb' - 'language/defined_spec.rb'
- 'language/fixtures/squiggly_heredoc.rb' - 'language/fixtures/squiggly_heredoc.rb'
- 'core/module/refine_spec.rb'
# Offense count: 16 # Offense count: 16
Lint/Loop: Lint/Loop:
@ -105,7 +100,7 @@ Lint/RedundantWithIndex:
Exclude: Exclude:
- 'core/enumerator/with_index_spec.rb' - 'core/enumerator/with_index_spec.rb'
# Offense count: 24 # Offense count: 26
Lint/RescueException: Lint/RescueException:
Exclude: Exclude:
- 'command_line/fixtures/debug_info.rb' - 'command_line/fixtures/debug_info.rb'
@ -200,3 +195,9 @@ Lint/UselessAccessModifier:
- 'core/module/module_function_spec.rb' - 'core/module/module_function_spec.rb'
- 'core/module/private_class_method_spec.rb' - 'core/module/private_class_method_spec.rb'
- 'language/fixtures/send.rb' - 'language/fixtures/send.rb'
# Offense count: 6186
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
# URISchemes: http, https
Metrics/LineLength:
Max: 588

View file

@ -6,18 +6,17 @@ script:
- ../mspec/bin/mspec $MSPEC_OPTS - ../mspec/bin/mspec $MSPEC_OPTS
matrix: matrix:
include: include:
- rvm: 2.5.0 - rvm: 2.5.1
env: MSPEC_OPTS="-R2 -ff" env: MSPEC_OPTS="-R2 -ff"
- rvm: 2.2.9 - rvm: 2.3.7
- rvm: 2.3.6 - rvm: 2.4.4
- rvm: 2.4.3 - rvm: 2.5.1
- rvm: 2.5.0
env: CHECK_LEAKS=true env: CHECK_LEAKS=true
- rvm: ruby-head - rvm: ruby-head
- env: RUBOCOP=true - env: RUBOCOP=true
rvm: 2.4.3 rvm: 2.4.4
script: script:
- gem install rubocop -v 0.52.0 - gem install rubocop -v 0.54.0
- rubocop - rubocop
allow_failures: allow_failures:
- rvm: ruby-head - rvm: ruby-head

View file

@ -25,16 +25,20 @@ The language specs are grouped by keyword while the core and standard library sp
ruby/spec is known to be tested in these implementations for every commit: ruby/spec is known to be tested in these implementations for every commit:
* [MRI](http://rubyci.org/) on 30 platforms and 4 versions * [MRI](http://rubyci.org/) on 30 platforms and 4 versions
* [JRuby](https://github.com/jruby/jruby/tree/master/spec/ruby) for both 1.7 and 9.x * [JRuby](https://github.com/jruby/jruby/tree/master/spec/ruby) for both 1.7 and 9.x
* [TruffleRuby](https://github.com/oracle/truffleruby) * [TruffleRuby](https://github.com/oracle/truffleruby/tree/master/spec/ruby)
* [Opal](https://github.com/opal/opal/tree/master/spec) * [Opal](https://github.com/opal/opal/tree/master/spec)
ruby/spec describes the behavior of Ruby 2.2 and more recent Ruby versions. The specs are synchronized both ways around once a month by @eregon between ruby/spec, MRI, JRuby and TruffleRuby.
Each of these repositories has a full copy of the files to ease editing specs.
ruby/spec describes the behavior of Ruby 2.3 and more recent Ruby versions.
More precisely, every latest stable MRI release [passes](https://rubyci.org/) all specs of ruby/spec More precisely, every latest stable MRI release [passes](https://rubyci.org/) all specs of ruby/spec
(latest 2.2.x, 2.3.x, 2.4.x, etc). (2.3.x, 2.4.x, 2.5.x, etc).
For older specs try these commits: For older specs try these commits:
* Ruby 2.0.0-p647 - [Suite](https://github.com/ruby/spec/commit/245862558761d5abc676843ef74f86c9bcc8ea8d) using [MSpec](https://github.com/ruby/mspec/commit/f90efa068791064f955de7a843e96e2d7d3041c2) (may encounter 2 failures) * Ruby 2.0.0-p647 - [Suite](https://github.com/ruby/spec/commit/245862558761d5abc676843ef74f86c9bcc8ea8d) using [MSpec](https://github.com/ruby/mspec/commit/f90efa068791064f955de7a843e96e2d7d3041c2) (may encounter 2 failures)
* Ruby 2.1.9 - [Suite](https://github.com/ruby/spec/commit/f029e65241374386077ac500add557ae65069b55) using [MSpec](https://github.com/ruby/mspec/commit/55568ea3918c6380e64db8c567d732fa5781efed) * Ruby 2.1.9 - [Suite](https://github.com/ruby/spec/commit/f029e65241374386077ac500add557ae65069b55) using [MSpec](https://github.com/ruby/mspec/commit/55568ea3918c6380e64db8c567d732fa5781efed)
* Ruby 2.2.10 - [Suite](https://github.com/ruby/spec/commit/cbaa0e412270c944df0c2532fc500c920dba0e92) using [MSpec](https://github.com/ruby/mspec/commit/d84d7668449e96856c5f6bac8cb1526b6d357ce3)
### Running the specs ### Running the specs

View file

@ -8,4 +8,42 @@ describe "The -I command line option" do
it "adds the path to the load path ($:)" do it "adds the path to the load path ($:)" do
ruby_exe(@script, options: "-I fixtures").should include("fixtures") ruby_exe(@script, options: "-I fixtures").should include("fixtures")
end end
it "adds the path at the front of $LOAD_PATH" do
lines = ruby_exe(@script, options: "-I fixtures").lines
if File.basename(ruby_exe[0]) == "miniruby"
# In a MRI checkout, $PWD ends up as the first entry in $LOAD_PATH.
# So just assert that it's at the beginning.
idx = lines.index { |l| l.include?("fixtures") }
idx.should < 2
idx.should < lines.size-1
else
lines[0].should include("fixtures")
end
end
it "adds the path expanded from CWD to $LOAD_PATH" do
ruby_exe(@script, options: "-I fixtures").lines.should include "#{Dir.pwd}/fixtures\n"
end
it "expands a path from CWD even if it does not exist" do
ruby_exe(@script, options: "-I not_exist/not_exist").lines.should include "#{Dir.pwd}/not_exist/not_exist\n"
end
end
describe "The -I command line option" do
before :each do
@script = fixture __FILE__, "loadpath.rb"
@fixtures = File.dirname(@script)
@symlink = tmp("loadpath_symlink")
File.symlink(@fixtures, @symlink)
end
after :each do
rm_r @symlink
end
it "does not expand symlinks" do
ruby_exe(@script, options: "-I #{@symlink}").lines.should include "#{@symlink}\n"
end
end end

View file

@ -1,30 +1,28 @@
require_relative '../spec_helper' require_relative '../spec_helper'
ruby_version_is "2.3" do describe "The --enable-frozen-string-literal flag causes string literals to" do
describe "The --enable-frozen-string-literal flag causes string literals to" do
it "produce the same object each time" do it "produce the same object each time" do
ruby_exe(fixture(__FILE__, "freeze_flag_one_literal.rb"), options: "--enable-frozen-string-literal").chomp.should == "true" ruby_exe(fixture(__FILE__, "freeze_flag_one_literal.rb"), options: "--enable-frozen-string-literal").chomp.should == "true"
end
it "produce the same object for literals with the same content" do
ruby_exe(fixture(__FILE__, "freeze_flag_two_literals.rb"), options: "--enable-frozen-string-literal").chomp.should == "true"
end
it "produce the same object for literals with the same content in different files" do
ruby_exe(fixture(__FILE__, "freeze_flag_across_files.rb"), options: "--enable-frozen-string-literal").chomp.should == "true"
end
it "produce different objects for literals with the same content in different files if they have different encodings" do
ruby_exe(fixture(__FILE__, "freeze_flag_across_files_diff_enc.rb"), options: "--enable-frozen-string-literal").chomp.should == "true"
end
end end
describe "The --debug flag produces" do it "produce the same object for literals with the same content" do
it "debugging info on attempted frozen string modification" do ruby_exe(fixture(__FILE__, "freeze_flag_two_literals.rb"), options: "--enable-frozen-string-literal").chomp.should == "true"
error_str = ruby_exe(fixture(__FILE__, 'debug_info.rb'), options: '--debug', args: "2>&1") end
error_str.should include("can't modify frozen String, created at ")
error_str.should include("command_line/fixtures/debug_info.rb:2") it "produce the same object for literals with the same content in different files" do
end ruby_exe(fixture(__FILE__, "freeze_flag_across_files.rb"), options: "--enable-frozen-string-literal").chomp.should == "true"
end
it "produce different objects for literals with the same content in different files if they have different encodings" do
ruby_exe(fixture(__FILE__, "freeze_flag_across_files_diff_enc.rb"), options: "--enable-frozen-string-literal").chomp.should == "true"
end
end
describe "The --debug flag produces" do
it "debugging info on attempted frozen string modification" do
error_str = ruby_exe(fixture(__FILE__, 'debug_info.rb'), options: '--debug', args: "2>&1")
error_str.should include("can't modify frozen String, created at ")
error_str.should include("command_line/fixtures/debug_info.rb:2")
end end
end end

View file

@ -20,21 +20,10 @@ describe "ARGF.close" do
end end
end end
ruby_version_is ""..."2.3" do it "doesn't raise an IOError if called on a closed stream" do
it "raises an IOError if called on a closed stream" do argf [@file1_name] do
argf [@file1_name] do lambda { @argf.close }.should_not raise_error
lambda { @argf.close }.should_not raise_error lambda { @argf.close }.should_not raise_error
lambda { @argf.close }.should raise_error(IOError)
end
end
end
ruby_version_is "2.3" do
it "doesn't raise an IOError if called on a closed stream" do
argf [@file1_name] do
lambda { @argf.close }.should_not raise_error
lambda { @argf.close }.should_not raise_error
end
end end
end end
end end

View file

@ -70,11 +70,9 @@ platform_is_not :windows do
end end
end end
ruby_version_is "2.3" do it 'returns :wait_readable when the :exception is set to false' do
it 'returns :wait_readable when the :exception is set to false' do argf ['-'] do
argf ['-'] do @argf.read_nonblock(4, nil, exception: false).should == :wait_readable
@argf.read_nonblock(4, nil, exception: false).should == :wait_readable
end
end end
end end
end end

View file

@ -54,15 +54,13 @@ describe "ARGF.readpartial" do
end end
end end
ruby_version_is "2.3" do it "raises an EOFError if the exception was raised while reading the last file" do
it "raises an EOFError if the exception was raised while reading the last file" do argf [@file1_name, @file2_name] do
argf [@file1_name, @file2_name] do @argf.readpartial(@file1.size)
@argf.readpartial(@file1.size) @argf.readpartial(1)
@argf.readpartial(1) @argf.readpartial(@file2.size)
@argf.readpartial(@file2.size) lambda { @argf.readpartial(1) }.should raise_error(EOFError)
lambda { @argf.readpartial(1) }.should raise_error(EOFError) lambda { @argf.readpartial(1) }.should raise_error(EOFError)
lambda { @argf.readpartial(1) }.should raise_error(EOFError)
end
end end
end end

View file

@ -1,86 +1,84 @@
require_relative '../../spec_helper' require_relative '../../spec_helper'
require_relative '../enumerable/shared/enumeratorized' require_relative '../enumerable/shared/enumeratorized'
ruby_version_is "2.3" do describe "Array#bsearch_index" do
describe "Array#bsearch_index" do context "when not passed a block" do
context "when not passed a block" do before :each do
before :each do @enum = [1, 2, 42, 100, 666].bsearch_index
@enum = [1, 2, 42, 100, 666].bsearch_index
end
it "returns an Enumerator" do
@enum.should be_an_instance_of(Enumerator)
end
it "returns an Enumerator with unknown size" do
@enum.size.should be_nil
end
it "returns index of element when block condition is satisfied" do
@enum.each { |x| x >= 33 }.should == 2
end
end end
it "raises a TypeError when block returns a String" do it "returns an Enumerator" do
lambda { [1, 2, 3].bsearch_index { "not ok" } }.should raise_error(TypeError) @enum.should be_an_instance_of(Enumerator)
end end
it "returns nil when block is empty" do it "returns an Enumerator with unknown size" do
[1, 2, 3].bsearch_index {}.should be_nil @enum.size.should be_nil
end end
context "minimum mode" do it "returns index of element when block condition is satisfied" do
before :each do @enum.each { |x| x >= 33 }.should == 2
@array = [0, 4, 7, 10, 12] end
end end
it "returns index of first element which satisfies the block" do it "raises a TypeError when block returns a String" do
@array.bsearch_index { |x| x >= 4 }.should == 1 lambda { [1, 2, 3].bsearch_index { "not ok" } }.should raise_error(TypeError)
@array.bsearch_index { |x| x >= 6 }.should == 2 end
@array.bsearch_index { |x| x >= -1 }.should == 0
end
it "returns nil when block condition is never satisfied" do it "returns nil when block is empty" do
@array.bsearch_index { false }.should be_nil [1, 2, 3].bsearch_index {}.should be_nil
@array.bsearch_index { |x| x >= 100 }.should be_nil end
end
context "minimum mode" do
before :each do
@array = [0, 4, 7, 10, 12]
end end
context "find any mode" do it "returns index of first element which satisfies the block" do
before :each do @array.bsearch_index { |x| x >= 4 }.should == 1
@array = [0, 4, 7, 10, 12] @array.bsearch_index { |x| x >= 6 }.should == 2
end @array.bsearch_index { |x| x >= -1 }.should == 0
end
it "returns the index of any matched elements where element is between 4 <= x < 8" do it "returns nil when block condition is never satisfied" do
[1, 2].should include(@array.bsearch_index { |x| 1 - x / 4 }) @array.bsearch_index { false }.should be_nil
end @array.bsearch_index { |x| x >= 100 }.should be_nil
end
end
it "returns the index of any matched elements where element is between 8 <= x < 10" do context "find any mode" do
@array.bsearch_index { |x| 4 - x / 2 }.should be_nil before :each do
@array = [0, 4, 7, 10, 12]
end
it "returns the index of any matched elements where element is between 4 <= x < 8" do
[1, 2].should include(@array.bsearch_index { |x| 1 - x / 4 })
end
it "returns the index of any matched elements where element is between 8 <= x < 10" do
@array.bsearch_index { |x| 4 - x / 2 }.should be_nil
end
it "returns nil when block never returns 0" do
@array.bsearch_index { |x| 1 }.should be_nil
@array.bsearch_index { |x| -1 }.should be_nil
end
it "returns the middle element when block always returns zero" do
@array.bsearch_index { |x| 0 }.should == 2
end
context "magnitude does not effect the result" do
it "returns the index of any matched elements where element is between 4n <= xn < 8n" do
[1, 2].should include(@array.bsearch_index { |x| (1 - x / 4) * (2**100) })
end end
it "returns nil when block never returns 0" do it "returns nil when block never returns 0" do
@array.bsearch_index { |x| 1 }.should be_nil @array.bsearch_index { |x| 1 * (2**100) }.should be_nil
@array.bsearch_index { |x| -1 }.should be_nil @array.bsearch_index { |x| (-1) * (2**100) }.should be_nil
end end
it "returns the middle element when block always returns zero" do it "handles values from Bignum#coerce" do
@array.bsearch_index { |x| 0 }.should == 2 [1, 2].should include(@array.bsearch_index { |x| (2**100).coerce((1 - x / 4) * (2**100)).first })
end
context "magnitude does not effect the result" do
it "returns the index of any matched elements where element is between 4n <= xn < 8n" do
[1, 2].should include(@array.bsearch_index { |x| (1 - x / 4) * (2**100) })
end
it "returns nil when block never returns 0" do
@array.bsearch_index { |x| 1 * (2**100) }.should be_nil
@array.bsearch_index { |x| (-1) * (2**100) }.should be_nil
end
it "handles values from Bignum#coerce" do
[1, 2].should include(@array.bsearch_index { |x| (2**100).coerce((1 - x / 4) * (2**100)).first })
end
end end
end end
end end

View file

@ -1,54 +1,52 @@
require_relative '../../spec_helper' require_relative '../../spec_helper'
ruby_version_is '2.3' do describe "Array#dig" do
describe "Array#dig" do
it "returns #at with one arg" do
['a'].dig(0).should == 'a'
['a'].dig(1).should be_nil
end
it "recurses array elements" do
a = [ [ 1, [2, '3'] ] ]
a.dig(0, 0).should == 1
a.dig(0, 1, 1).should == '3'
a.dig(0, -1, 0).should == 2
end
it "returns the nested value specified if the sequence includes a key" do
a = [42, { foo: :bar }]
a.dig(1, :foo).should == :bar
end
it "raises a TypeError for a non-numeric index" do
lambda {
['a'].dig(:first)
}.should raise_error(TypeError)
end
it "raises a TypeError if any intermediate step does not respond to #dig" do
a = [1, 2]
lambda {
a.dig(0, 1)
}.should raise_error(TypeError)
end
it "raises an ArgumentError if no arguments provided" do
lambda {
[10].dig()
}.should raise_error(ArgumentError)
end
it "returns nil if any intermediate step is nil" do
a = [[1, [2, 3]]]
a.dig(1, 2, 3).should == nil
end
it "calls #dig on the result of #at with the remaining arguments" do
h = [[nil, [nil, nil, 42]]]
h[0].should_receive(:dig).with(1, 2).and_return(42)
h.dig(0, 1, 2).should == 42
end
it "returns #at with one arg" do
['a'].dig(0).should == 'a'
['a'].dig(1).should be_nil
end end
it "recurses array elements" do
a = [ [ 1, [2, '3'] ] ]
a.dig(0, 0).should == 1
a.dig(0, 1, 1).should == '3'
a.dig(0, -1, 0).should == 2
end
it "returns the nested value specified if the sequence includes a key" do
a = [42, { foo: :bar }]
a.dig(1, :foo).should == :bar
end
it "raises a TypeError for a non-numeric index" do
lambda {
['a'].dig(:first)
}.should raise_error(TypeError)
end
it "raises a TypeError if any intermediate step does not respond to #dig" do
a = [1, 2]
lambda {
a.dig(0, 1)
}.should raise_error(TypeError)
end
it "raises an ArgumentError if no arguments provided" do
lambda {
[10].dig()
}.should raise_error(ArgumentError)
end
it "returns nil if any intermediate step is nil" do
a = [[1, [2, 3]]]
a.dig(1, 2, 3).should == nil
end
it "calls #dig on the result of #at with the remaining arguments" do
h = [[nil, [nil, nil, 42]]]
h[0].should_receive(:dig).with(1, 2).and_return(42)
h.dig(0, 1, 2).should == 42
end
end end

View file

@ -69,12 +69,10 @@ describe "Array#flatten" do
[1, z, 6].flatten.should == [1, 2, 3, 4, 5, 6] [1, z, 6].flatten.should == [1, 2, 3, 4, 5, 6]
end end
ruby_version_is "2.3" do it "does not call #to_ary on elements beyond the given level" do
it "does not call #to_ary on elements beyond the given level" do obj = mock("1")
obj = mock("1") obj.should_not_receive(:to_ary)
obj.should_not_receive(:to_ary) [[obj]].flatten(1)
[[obj]].flatten(1)
end
end end
it "returns subclass instance for Array subclasses" do it "returns subclass instance for Array subclasses" do

View file

@ -4,216 +4,214 @@ require_relative 'shared/basic'
require_relative 'shared/numeric_basic' require_relative 'shared/numeric_basic'
require_relative 'shared/integer' require_relative 'shared/integer'
ruby_version_is '2.3' do platform_is pointer_size: 64 do
platform_is pointer_size: 64 do describe "Array#pack with format 'J'" do
it_behaves_like :array_pack_basic, 'J'
it_behaves_like :array_pack_basic_non_float, 'J'
it_behaves_like :array_pack_arguments, 'J'
it_behaves_like :array_pack_numeric_basic, 'J'
it_behaves_like :array_pack_integer, 'J'
end
describe "Array#pack with format 'j'" do
it_behaves_like :array_pack_basic, 'j'
it_behaves_like :array_pack_basic_non_float, 'j'
it_behaves_like :array_pack_arguments, 'j'
it_behaves_like :array_pack_numeric_basic, 'j'
it_behaves_like :array_pack_integer, 'j'
end
little_endian do
describe "Array#pack with format 'J'" do describe "Array#pack with format 'J'" do
it_behaves_like :array_pack_basic, 'J' describe "with modifier '_'" do
it_behaves_like :array_pack_basic_non_float, 'J' it_behaves_like :array_pack_64bit_le, 'J_'
it_behaves_like :array_pack_arguments, 'J'
it_behaves_like :array_pack_numeric_basic, 'J'
it_behaves_like :array_pack_integer, 'J'
end
describe "Array#pack with format 'j'" do
it_behaves_like :array_pack_basic, 'j'
it_behaves_like :array_pack_basic_non_float, 'j'
it_behaves_like :array_pack_arguments, 'j'
it_behaves_like :array_pack_numeric_basic, 'j'
it_behaves_like :array_pack_integer, 'j'
end
little_endian do
describe "Array#pack with format 'J'" do
describe "with modifier '_'" do
it_behaves_like :array_pack_64bit_le, 'J_'
end
describe "with modifier '!'" do
it_behaves_like :array_pack_64bit_le, 'J!'
end
end end
describe "Array#pack with format 'j'" do describe "with modifier '!'" do
describe "with modifier '_'" do it_behaves_like :array_pack_64bit_le, 'J!'
it_behaves_like :array_pack_64bit_le, 'j_'
end
describe "with modifier '!'" do
it_behaves_like :array_pack_64bit_le, 'j!'
end
end
end
big_endian do
describe "Array#pack with format 'J'" do
describe "with modifier '_'" do
it_behaves_like :array_pack_64bit_be, 'J_'
end
describe "with modifier '!'" do
it_behaves_like :array_pack_64bit_be, 'J!'
end
end
describe "Array#pack with format 'j'" do
describe "with modifier '_'" do
it_behaves_like :array_pack_64bit_be, 'j_'
end
describe "with modifier '!'" do
it_behaves_like :array_pack_64bit_be, 'j!'
end
end
end
describe "Array#pack with format 'J'" do
describe "with modifier '<' and '_'" do
it_behaves_like :array_pack_64bit_le, 'J<_'
it_behaves_like :array_pack_64bit_le, 'J_<'
end
describe "with modifier '<' and '!'" do
it_behaves_like :array_pack_64bit_le, 'J<!'
it_behaves_like :array_pack_64bit_le, 'J!<'
end
describe "with modifier '>' and '_'" do
it_behaves_like :array_pack_64bit_be, 'J>_'
it_behaves_like :array_pack_64bit_be, 'J_>'
end
describe "with modifier '>' and '!'" do
it_behaves_like :array_pack_64bit_be, 'J>!'
it_behaves_like :array_pack_64bit_be, 'J!>'
end end
end end
describe "Array#pack with format 'j'" do describe "Array#pack with format 'j'" do
describe "with modifier '<' and '_'" do describe "with modifier '_'" do
it_behaves_like :array_pack_64bit_le, 'j<_' it_behaves_like :array_pack_64bit_le, 'j_'
it_behaves_like :array_pack_64bit_le, 'j_<'
end end
describe "with modifier '<' and '!'" do describe "with modifier '!'" do
it_behaves_like :array_pack_64bit_le, 'j<!' it_behaves_like :array_pack_64bit_le, 'j!'
it_behaves_like :array_pack_64bit_le, 'j!<'
end
describe "with modifier '>' and '_'" do
it_behaves_like :array_pack_64bit_be, 'j>_'
it_behaves_like :array_pack_64bit_be, 'j_>'
end
describe "with modifier '>' and '!'" do
it_behaves_like :array_pack_64bit_be, 'j>!'
it_behaves_like :array_pack_64bit_be, 'j!>'
end end
end end
end end
platform_is pointer_size: 32 do big_endian do
describe "Array#pack with format 'J'" do describe "Array#pack with format 'J'" do
it_behaves_like :array_pack_basic, 'J' describe "with modifier '_'" do
it_behaves_like :array_pack_basic_non_float, 'J' it_behaves_like :array_pack_64bit_be, 'J_'
it_behaves_like :array_pack_arguments, 'J'
it_behaves_like :array_pack_numeric_basic, 'J'
it_behaves_like :array_pack_integer, 'J'
end
describe "Array#pack with format 'j'" do
it_behaves_like :array_pack_basic, 'j'
it_behaves_like :array_pack_basic_non_float, 'j'
it_behaves_like :array_pack_arguments, 'j'
it_behaves_like :array_pack_numeric_basic, 'j'
it_behaves_like :array_pack_integer, 'j'
end
big_endian do
describe "Array#pack with format 'J'" do
describe "with modifier '_'" do
it_behaves_like :array_pack_32bit_be, 'J_'
end
describe "with modifier '!'" do
it_behaves_like :array_pack_32bit_be, 'J!'
end
end end
describe "Array#pack with format 'j'" do describe "with modifier '!'" do
describe "with modifier '_'" do it_behaves_like :array_pack_64bit_be, 'J!'
it_behaves_like :array_pack_32bit_be, 'j_'
end
describe "with modifier '!'" do
it_behaves_like :array_pack_32bit_be, 'j!'
end
end
end
little_endian do
describe "Array#pack with format 'J'" do
describe "with modifier '_'" do
it_behaves_like :array_pack_32bit_le, 'J_'
end
describe "with modifier '!'" do
it_behaves_like :array_pack_32bit_le, 'J!'
end
end
describe "Array#pack with format 'j'" do
describe "with modifier '_'" do
it_behaves_like :array_pack_32bit_le, 'j_'
end
describe "with modifier '!'" do
it_behaves_like :array_pack_32bit_le, 'j!'
end
end
end
describe "Array#pack with format 'J'" do
describe "with modifier '<' and '_'" do
it_behaves_like :array_pack_32bit_le, 'J<_'
it_behaves_like :array_pack_32bit_le, 'J_<'
end
describe "with modifier '<' and '!'" do
it_behaves_like :array_pack_32bit_le, 'J<!'
it_behaves_like :array_pack_32bit_le, 'J!<'
end
describe "with modifier '>' and '_'" do
it_behaves_like :array_pack_32bit_be, 'J>_'
it_behaves_like :array_pack_32bit_be, 'J_>'
end
describe "with modifier '>' and '!'" do
it_behaves_like :array_pack_32bit_be, 'J>!'
it_behaves_like :array_pack_32bit_be, 'J!>'
end end
end end
describe "Array#pack with format 'j'" do describe "Array#pack with format 'j'" do
describe "with modifier '<' and '_'" do describe "with modifier '_'" do
it_behaves_like :array_pack_32bit_le, 'j<_' it_behaves_like :array_pack_64bit_be, 'j_'
it_behaves_like :array_pack_32bit_le, 'j_<'
end end
describe "with modifier '<' and '!'" do describe "with modifier '!'" do
it_behaves_like :array_pack_32bit_le, 'j<!' it_behaves_like :array_pack_64bit_be, 'j!'
it_behaves_like :array_pack_32bit_le, 'j!<'
end end
end
end
describe "with modifier '>' and '_'" do describe "Array#pack with format 'J'" do
it_behaves_like :array_pack_32bit_be, 'j>_' describe "with modifier '<' and '_'" do
it_behaves_like :array_pack_32bit_be, 'j_>' it_behaves_like :array_pack_64bit_le, 'J<_'
end it_behaves_like :array_pack_64bit_le, 'J_<'
end
describe "with modifier '>' and '!'" do describe "with modifier '<' and '!'" do
it_behaves_like :array_pack_32bit_be, 'j>!' it_behaves_like :array_pack_64bit_le, 'J<!'
it_behaves_like :array_pack_32bit_be, 'j!>' it_behaves_like :array_pack_64bit_le, 'J!<'
end end
describe "with modifier '>' and '_'" do
it_behaves_like :array_pack_64bit_be, 'J>_'
it_behaves_like :array_pack_64bit_be, 'J_>'
end
describe "with modifier '>' and '!'" do
it_behaves_like :array_pack_64bit_be, 'J>!'
it_behaves_like :array_pack_64bit_be, 'J!>'
end
end
describe "Array#pack with format 'j'" do
describe "with modifier '<' and '_'" do
it_behaves_like :array_pack_64bit_le, 'j<_'
it_behaves_like :array_pack_64bit_le, 'j_<'
end
describe "with modifier '<' and '!'" do
it_behaves_like :array_pack_64bit_le, 'j<!'
it_behaves_like :array_pack_64bit_le, 'j!<'
end
describe "with modifier '>' and '_'" do
it_behaves_like :array_pack_64bit_be, 'j>_'
it_behaves_like :array_pack_64bit_be, 'j_>'
end
describe "with modifier '>' and '!'" do
it_behaves_like :array_pack_64bit_be, 'j>!'
it_behaves_like :array_pack_64bit_be, 'j!>'
end
end
end
platform_is pointer_size: 32 do
describe "Array#pack with format 'J'" do
it_behaves_like :array_pack_basic, 'J'
it_behaves_like :array_pack_basic_non_float, 'J'
it_behaves_like :array_pack_arguments, 'J'
it_behaves_like :array_pack_numeric_basic, 'J'
it_behaves_like :array_pack_integer, 'J'
end
describe "Array#pack with format 'j'" do
it_behaves_like :array_pack_basic, 'j'
it_behaves_like :array_pack_basic_non_float, 'j'
it_behaves_like :array_pack_arguments, 'j'
it_behaves_like :array_pack_numeric_basic, 'j'
it_behaves_like :array_pack_integer, 'j'
end
big_endian do
describe "Array#pack with format 'J'" do
describe "with modifier '_'" do
it_behaves_like :array_pack_32bit_be, 'J_'
end
describe "with modifier '!'" do
it_behaves_like :array_pack_32bit_be, 'J!'
end
end
describe "Array#pack with format 'j'" do
describe "with modifier '_'" do
it_behaves_like :array_pack_32bit_be, 'j_'
end
describe "with modifier '!'" do
it_behaves_like :array_pack_32bit_be, 'j!'
end
end
end
little_endian do
describe "Array#pack with format 'J'" do
describe "with modifier '_'" do
it_behaves_like :array_pack_32bit_le, 'J_'
end
describe "with modifier '!'" do
it_behaves_like :array_pack_32bit_le, 'J!'
end
end
describe "Array#pack with format 'j'" do
describe "with modifier '_'" do
it_behaves_like :array_pack_32bit_le, 'j_'
end
describe "with modifier '!'" do
it_behaves_like :array_pack_32bit_le, 'j!'
end
end
end
describe "Array#pack with format 'J'" do
describe "with modifier '<' and '_'" do
it_behaves_like :array_pack_32bit_le, 'J<_'
it_behaves_like :array_pack_32bit_le, 'J_<'
end
describe "with modifier '<' and '!'" do
it_behaves_like :array_pack_32bit_le, 'J<!'
it_behaves_like :array_pack_32bit_le, 'J!<'
end
describe "with modifier '>' and '_'" do
it_behaves_like :array_pack_32bit_be, 'J>_'
it_behaves_like :array_pack_32bit_be, 'J_>'
end
describe "with modifier '>' and '!'" do
it_behaves_like :array_pack_32bit_be, 'J>!'
it_behaves_like :array_pack_32bit_be, 'J!>'
end
end
describe "Array#pack with format 'j'" do
describe "with modifier '<' and '_'" do
it_behaves_like :array_pack_32bit_le, 'j<_'
it_behaves_like :array_pack_32bit_le, 'j_<'
end
describe "with modifier '<' and '!'" do
it_behaves_like :array_pack_32bit_le, 'j<!'
it_behaves_like :array_pack_32bit_le, 'j!<'
end
describe "with modifier '>' and '_'" do
it_behaves_like :array_pack_32bit_be, 'j>_'
it_behaves_like :array_pack_32bit_be, 'j_>'
end
describe "with modifier '>' and '!'" do
it_behaves_like :array_pack_32bit_be, 'j>!'
it_behaves_like :array_pack_32bit_be, 'j!>'
end end
end end
end end

View file

@ -3,25 +3,11 @@ describe :delete_if, shared: true do
@object = [1,2,3] @object = [1,2,3]
end end
ruby_version_is "2.3" do it "updates the receiver after all blocks" do
it "updates the receiver after all blocks" do @object.send(@method) do |e|
@object.send(@method) do |e| @object.length.should == 3
@object.length.should == 3 true
true
end
@object.length.should == 0
end
end
ruby_version_is ""..."2.3" do
it "updates the receiver after each true block" do
count = 0
@object.send(@method) do |e|
@object.length.should == (3 - count)
count += 1
true
end
@object.length.should == 0
end end
@object.length.should == 0
end end
end end

View file

@ -121,24 +121,11 @@ describe :array_inspect, shared: true do
array.send(@method).encoding.name.should == "US-ASCII" array.send(@method).encoding.name.should == "US-ASCII"
end end
ruby_version_is ''...'2.3' do it "does not raise if inspected result is not default external encoding" do
it "raises if inspected result is not default external encoding" do utf_16be = mock("utf_16be")
utf_16be = mock("utf_16be") utf_16be.should_receive(:inspect).and_return(%<"utf_16be \u3042">.encode!(Encoding::UTF_16BE))
utf_16be.should_receive(:inspect).and_return(%<"utf_16be \u3042">.encode!(Encoding::UTF_16BE))
lambda { [utf_16be].send(@method).should == '["utf_16be \u3042"]'
[utf_16be].send(@method)
}.should raise_error(Encoding::CompatibilityError)
end
end
ruby_version_is '2.3' do
it "does not raise if inspected result is not default external encoding" do
utf_16be = mock("utf_16be")
utf_16be.should_receive(:inspect).and_return(%<"utf_16be \u3042">.encode!(Encoding::UTF_16BE))
[utf_16be].send(@method).should == '["utf_16be \u3042"]'
end
end end
end end
end end

View file

@ -48,16 +48,8 @@ describe "Comparable#==" do
a.should_receive(:<=>).once.and_return("abc") a.should_receive(:<=>).once.and_return("abc")
end end
ruby_version_is ""..."2.3" do it "raises an ArgumentError" do
it "returns false" do lambda { (a == b) }.should raise_error(ArgumentError)
(a == b).should be_false
end
end
ruby_version_is "2.3" do
it "raises an ArgumentError" do
lambda { (a == b) }.should raise_error(ArgumentError)
end
end end
end end
@ -67,17 +59,8 @@ describe "Comparable#==" do
a.should_receive(:<=>).once.and_raise(StandardError) a.should_receive(:<=>).once.and_raise(StandardError)
end end
ruby_version_is ""..."2.3" do it "lets it go through" do
# Behaviour confirmed by MRI test suite lambda { (a == b) }.should raise_error(StandardError)
it "returns false" do
(a == b).should be_false
end
end
ruby_version_is "2.3" do
it "lets it go through" do
lambda { (a == b) }.should raise_error(StandardError)
end
end end
end end
@ -87,16 +70,8 @@ describe "Comparable#==" do
a.should_receive(:<=>).once.and_raise(TypeError) a.should_receive(:<=>).once.and_raise(TypeError)
end end
ruby_version_is ""..."2.3" do it "lets it go through" do
it "returns false" do lambda { (a == b) }.should raise_error(TypeError)
(a == b).should be_false
end
end
ruby_version_is "2.3" do
it "lets it go through" do
lambda { (a == b) }.should raise_error(TypeError)
end
end end
end end

View file

@ -1,9 +1,5 @@
require_relative '../../spec_helper' require_relative '../../spec_helper'
require_relative 'fixtures/common' require_relative 'fixtures/common'
ruby_version_is ''...'2.3' do
require_relative 'shared/closed'
end
describe "Dir#close" do describe "Dir#close" do
before :all do before :all do
DirSpecs.create_mock_dirs DirSpecs.create_mock_dirs
@ -13,17 +9,11 @@ describe "Dir#close" do
DirSpecs.delete_mock_dirs DirSpecs.delete_mock_dirs
end end
ruby_version_is ''...'2.3' do it "does not raise an IOError even if the Dir instance is closed" do
it_behaves_like :dir_closed, :close dir = Dir.open DirSpecs.mock_dir
end dir.close
lambda {
ruby_version_is '2.3' do
it "does not raise an IOError even if the Dir instance is closed" do
dir = Dir.open DirSpecs.mock_dir
dir.close dir.close
lambda { }.should_not raise_error(IOError)
dir.close
}.should_not raise_error(IOError)
end
end end
end end

View file

@ -32,6 +32,15 @@ describe :dir_glob, shared: true do
end end
end end
ruby_version_is "2.6" do
it "splits the string on \\0 if there is only one string given and warns" do
-> {
Dir.send(@method, "file_o*\0file_t*").should ==
%w!file_one.ext file_two.ext!
}.should complain(/warning: use glob patterns list instead of nul-separated patterns/)
end
end
it "matches non-dotfiles with '*'" do it "matches non-dotfiles with '*'" do
expected = %w[ expected = %w[
brace brace

View file

@ -62,34 +62,11 @@ describe "Enumerable#chunk" do
lambda { e.chunk { |x| :_arbitrary }.to_a }.should raise_error(RuntimeError) lambda { e.chunk { |x| :_arbitrary }.to_a }.should raise_error(RuntimeError)
end end
ruby_version_is ""..."2.3" do it "does not accept arguments" do
describe "with [initial_state]" do e = EnumerableSpecs::Numerous.new(1, 2, 3)
it "yields an element and an object value-equal but not identical to the object passed to #chunk" do lambda {
e = EnumerableSpecs::Numerous.new(1) e.chunk(1) {}
value = "value" }.should raise_error(ArgumentError)
e.chunk(value) do |x, v|
x.should == 1
v.should == value
v.should_not equal(value)
end.to_a
end
it "does not yield the object passed to #chunk if it is nil" do
e = EnumerableSpecs::Numerous.new(1)
e.chunk(nil) { |*x| ScratchPad << x }.to_a
ScratchPad.recorded.should == [[1]]
end
end
end
ruby_version_is "2.3" do
it "does not accept arguments" do
e = EnumerableSpecs::Numerous.new(1, 2, 3)
lambda {
e.chunk(1) {}
}.should raise_error(ArgumentError)
end
end end
it 'returned Enumerator size returns nil' do it 'returned Enumerator size returns nil' do

View file

@ -1,44 +1,42 @@
require_relative '../../spec_helper' require_relative '../../spec_helper'
require_relative 'fixtures/classes' require_relative 'fixtures/classes'
ruby_version_is "2.3" do describe "Enumerable#chunk_while" do
describe "Enumerable#chunk_while" do before :each do
before :each do ary = [10, 9, 7, 6, 4, 3, 2, 1]
ary = [10, 9, 7, 6, 4, 3, 2, 1] @enum = EnumerableSpecs::Numerous.new(*ary)
@enum = EnumerableSpecs::Numerous.new(*ary) @result = @enum.chunk_while { |i, j| i - 1 == j }
@result = @enum.chunk_while { |i, j| i - 1 == j } @enum_length = ary.length
@enum_length = ary.length end
context "when given a block" do
it "returns an enumerator" do
@result.should be_an_instance_of(Enumerator)
end end
context "when given a block" do it "splits chunks between adjacent elements i and j where the block returns false" do
it "returns an enumerator" do @result.to_a.should == [[10, 9], [7, 6], [4, 3, 2, 1]]
@result.should be_an_instance_of(Enumerator)
end
it "splits chunks between adjacent elements i and j where the block returns false" do
@result.to_a.should == [[10, 9], [7, 6], [4, 3, 2, 1]]
end
it "calls the block for length of the receiver enumerable minus one times" do
times_called = 0
@enum.chunk_while do |i, j|
times_called += 1
i - 1 == j
end.to_a
times_called.should == (@enum_length - 1)
end
end end
context "when not given a block" do it "calls the block for length of the receiver enumerable minus one times" do
it "raises an ArgumentError" do times_called = 0
lambda { @enum.chunk_while }.should raise_error(ArgumentError) @enum.chunk_while do |i, j|
end times_called += 1
i - 1 == j
end.to_a
times_called.should == (@enum_length - 1)
end end
end
context "on a single-element array" do context "when not given a block" do
it "ignores the block and returns an enumerator that yields [element]" do it "raises an ArgumentError" do
[1].chunk_while {|x| x.even?}.to_a.should == [[1]] lambda { @enum.chunk_while }.should raise_error(ArgumentError)
end end
end
context "on a single-element array" do
it "ignores the block and returns an enumerator that yields [element]" do
[1].chunk_while {|x| x.even?}.to_a.should == [[1]]
end end
end end
end end

View file

@ -1,43 +1,41 @@
require_relative '../../spec_helper' require_relative '../../spec_helper'
require_relative 'fixtures/classes' require_relative 'fixtures/classes'
ruby_version_is "2.3" do describe "Enumerable#grep_v" do
describe "Enumerable#grep_v" do before :each do
before :each do @numerous = EnumerableSpecs::Numerous.new(*(0..9).to_a)
@numerous = EnumerableSpecs::Numerous.new(*(0..9).to_a) def (@odd_matcher = BasicObject.new).===(obj)
def (@odd_matcher = BasicObject.new).===(obj) obj.odd?
obj.odd? end
end end
describe "without block" do
it "returns an Array of matched elements" do
@numerous.grep_v(@odd_matcher).should == [0, 2, 4, 6, 8]
end end
describe "without block" do it "compares pattern with gathered array when yielded with multiple arguments" do
it "returns an Array of matched elements" do (unmatcher = Object.new).stub!(:===).and_return(false)
@numerous.grep_v(@odd_matcher).should == [0, 2, 4, 6, 8] EnumerableSpecs::YieldsMixed2.new.grep_v(unmatcher).should == EnumerableSpecs::YieldsMixed2.gathered_yields
end
it "compares pattern with gathered array when yielded with multiple arguments" do
(unmatcher = Object.new).stub!(:===).and_return(false)
EnumerableSpecs::YieldsMixed2.new.grep_v(unmatcher).should == EnumerableSpecs::YieldsMixed2.gathered_yields
end
it "raises an ArgumentError when not given a pattern" do
-> { @numerous.grep_v }.should raise_error(ArgumentError)
end
end end
describe "with block" do it "raises an ArgumentError when not given a pattern" do
it "returns an Array of matched elements that mapped by the block" do -> { @numerous.grep_v }.should raise_error(ArgumentError)
@numerous.grep_v(@odd_matcher) { |n| n * 2 }.should == [0, 4, 8, 12, 16] end
end end
it "calls the block with gathered array when yielded with multiple arguments" do describe "with block" do
(unmatcher = Object.new).stub!(:===).and_return(false) it "returns an Array of matched elements that mapped by the block" do
EnumerableSpecs::YieldsMixed2.new.grep_v(unmatcher){ |e| e }.should == EnumerableSpecs::YieldsMixed2.gathered_yields @numerous.grep_v(@odd_matcher) { |n| n * 2 }.should == [0, 4, 8, 12, 16]
end end
it "raises an ArgumentError when not given a pattern" do it "calls the block with gathered array when yielded with multiple arguments" do
-> { @numerous.grep_v { |e| e } }.should raise_error(ArgumentError) (unmatcher = Object.new).stub!(:===).and_return(false)
end EnumerableSpecs::YieldsMixed2.new.grep_v(unmatcher){ |e| e }.should == EnumerableSpecs::YieldsMixed2.gathered_yields
end
it "raises an ArgumentError when not given a pattern" do
-> { @numerous.grep_v { |e| e } }.should raise_error(ArgumentError)
end end
end end
end end

View file

@ -40,33 +40,10 @@ describe "Enumerable#slice_before" do
end end
end end
ruby_version_is ""..."2.3" do it "does not accept arguments" do
describe "and an argument" do lambda {
it "calls the block with a copy of that argument" do @enum.slice_before(1) {}
arg = [:foo] }.should raise_error(ArgumentError)
first = nil
e = @enum.slice_before(arg) do |i, init|
init.should == arg
init.should_not equal(arg)
first = init
i == 6 || i == 2
end
e.should be_an_instance_of(Enumerator)
e.to_a.should == [[7], [6, 5, 4, 3], [2, 1]]
e = @enum.slice_before(arg) do |i, init|
init.should_not equal(first)
end
e.to_a
end
end
end
ruby_version_is "2.3" do
it "does not accept arguments" do
lambda {
@enum.slice_before(1) {}
}.should raise_error(ArgumentError)
end
end end
end end

View file

@ -1,86 +1,84 @@
require_relative '../../../spec_helper' require_relative '../../../spec_helper'
require_relative 'fixtures/classes' require_relative 'fixtures/classes'
ruby_version_is "2.3" do describe "Enumerator::Lazy#grep_v" do
describe "Enumerator::Lazy#grep_v" do before(:each) do
before(:each) do @yieldsmixed = EnumeratorLazySpecs::YieldsMixed.new.to_enum.lazy
@yieldsmixed = EnumeratorLazySpecs::YieldsMixed.new.to_enum.lazy @eventsmixed = EnumeratorLazySpecs::EventsMixed.new.to_enum.lazy
@eventsmixed = EnumeratorLazySpecs::EventsMixed.new.to_enum.lazy ScratchPad.record []
ScratchPad.record [] end
after(:each) do
ScratchPad.clear
end
it "requires an argument" do
Enumerator::Lazy.instance_method(:grep_v).arity.should == 1
end
it "returns a new instance of Enumerator::Lazy" do
ret = @yieldsmixed.grep_v(Object) {}
ret.should be_an_instance_of(Enumerator::Lazy)
ret.should_not equal(@yieldsmixed)
ret = @yieldsmixed.grep_v(Object)
ret.should be_an_instance_of(Enumerator::Lazy)
ret.should_not equal(@yieldsmixed)
end
it "sets #size to nil" do
Enumerator::Lazy.new(Object.new, 100) {}.grep_v(Object) {}.size.should == nil
Enumerator::Lazy.new(Object.new, 100) {}.grep_v(Object).size.should == nil
end
describe "when the returned lazy enumerator is evaluated by Enumerable#first" do
it "stops after specified times when not given a block" do
(0..Float::INFINITY).lazy.grep_v(3..5).first(3).should == [0, 1, 2]
@eventsmixed.grep_v(Symbol).first(1)
ScratchPad.recorded.should == [:before_yield]
end end
after(:each) do it "stops after specified times when given a block" do
ScratchPad.clear (0..Float::INFINITY).lazy.grep_v(4..8, &:succ).first(3).should == [1, 2, 3]
@eventsmixed.grep_v(Symbol) {}.first(1)
ScratchPad.recorded.should == [:before_yield]
end end
end
it "requires an argument" do it "calls the block with a gathered array when yield with multiple arguments" do
Enumerator::Lazy.instance_method(:grep_v).arity.should == 1 yields = []
end @yieldsmixed.grep_v(Array) { |v| yields << v }.force
yields.should == EnumeratorLazySpecs::YieldsMixed.gathered_non_array_yields
it "returns a new instance of Enumerator::Lazy" do @yieldsmixed.grep_v(Array).force.should == yields
ret = @yieldsmixed.grep_v(Object) {} end
ret.should be_an_instance_of(Enumerator::Lazy)
ret.should_not equal(@yieldsmixed)
ret = @yieldsmixed.grep_v(Object)
ret.should be_an_instance_of(Enumerator::Lazy)
ret.should_not equal(@yieldsmixed)
end
describe "on a nested Lazy" do
it "sets #size to nil" do it "sets #size to nil" do
Enumerator::Lazy.new(Object.new, 100) {}.grep_v(Object) {}.size.should == nil Enumerator::Lazy.new(Object.new, 100) {}.grep_v(Object).grep_v(Object) {}.size.should == nil
Enumerator::Lazy.new(Object.new, 100) {}.grep_v(Object).size.should == nil Enumerator::Lazy.new(Object.new, 100) {}.grep_v(Object).grep_v(Object).size.should == nil
end end
describe "when the returned lazy enumerator is evaluated by Enumerable#first" do describe "when the returned lazy enumerator is evaluated by Enumerable#first" do
it "stops after specified times when not given a block" do it "stops after specified times when not given a block" do
(0..Float::INFINITY).lazy.grep_v(3..5).first(3).should == [0, 1, 2] (0..Float::INFINITY).lazy.grep_v(3..5).grep_v(6..10).first(3).should == [0, 1, 2]
@eventsmixed.grep_v(Symbol).first(1) @eventsmixed.grep_v(Symbol).grep_v(String).first(1)
ScratchPad.recorded.should == [:before_yield] ScratchPad.recorded.should == [:before_yield]
end end
it "stops after specified times when given a block" do it "stops after specified times when given a block" do
(0..Float::INFINITY).lazy.grep_v(4..8, &:succ).first(3).should == [1, 2, 3] (0..Float::INFINITY).lazy
.grep_v(1..2) { |n| n > 3 ? n : false }
.grep_v(false) { |n| n.even? ? n : false }
.first(3)
.should == [4, false, 6]
@eventsmixed.grep_v(Symbol) {}.first(1) @eventsmixed.grep_v(Symbol) {}.grep_v(String) {}.first(1)
ScratchPad.recorded.should == [:before_yield] ScratchPad.recorded.should == [:before_yield]
end end
end end
it "calls the block with a gathered array when yield with multiple arguments" do
yields = []
@yieldsmixed.grep_v(Array) { |v| yields << v }.force
yields.should == EnumeratorLazySpecs::YieldsMixed.gathered_non_array_yields
@yieldsmixed.grep_v(Array).force.should == yields
end
describe "on a nested Lazy" do
it "sets #size to nil" do
Enumerator::Lazy.new(Object.new, 100) {}.grep_v(Object).grep_v(Object) {}.size.should == nil
Enumerator::Lazy.new(Object.new, 100) {}.grep_v(Object).grep_v(Object).size.should == nil
end
describe "when the returned lazy enumerator is evaluated by Enumerable#first" do
it "stops after specified times when not given a block" do
(0..Float::INFINITY).lazy.grep_v(3..5).grep_v(6..10).first(3).should == [0, 1, 2]
@eventsmixed.grep_v(Symbol).grep_v(String).first(1)
ScratchPad.recorded.should == [:before_yield]
end
it "stops after specified times when given a block" do
(0..Float::INFINITY).lazy
.grep_v(1..2) { |n| n > 3 ? n : false }
.grep_v(false) { |n| n.even? ? n : false }
.first(3)
.should == [4, false, 6]
@eventsmixed.grep_v(Symbol) {}.grep_v(String) {}.first(1)
ScratchPad.recorded.should == [:before_yield]
end
end
end
end end
end end

View file

@ -13,7 +13,7 @@ ruby_version_is '2.4' do
@lazy.force.should == [0, 1] @lazy.force.should == [0, 1]
end end
ruby_bug "#14495", "2.4"..."2.5.1" do ruby_bug "#14495", "2.4"..."2.5.2" do
it 'return same value after rewind' do it 'return same value after rewind' do
@lazy.force.should == [0, 1] @lazy.force.should == [0, 1]
@lazy.force.should == [0, 1] @lazy.force.should == [0, 1]
@ -35,7 +35,7 @@ ruby_version_is '2.4' do
@lazy.force.should == [0, 1] @lazy.force.should == [0, 1]
end end
ruby_bug "#14495", "2.4"..."2.5.1" do ruby_bug "#14495", "2.4"..."2.5.2" do
it 'return same value after rewind' do it 'return same value after rewind' do
@lazy.force.should == [0, 1] @lazy.force.should == [0, 1]
@lazy.force.should == [0, 1] @lazy.force.should == [0, 1]
@ -60,7 +60,7 @@ ruby_version_is '2.4' do
@lazy = enum.lazy @lazy = enum.lazy
end end
ruby_bug "#14495", "2.4"..."2.5.1" do ruby_bug "#14495", "2.4"..."2.5.2" do
it 'return same value after rewind' do it 'return same value after rewind' do
enum = @lazy.uniq { |_, label| label.downcase } enum = @lazy.uniq { |_, label| label.downcase }
enum.force.should == [[0, 'foo'], [2, 'bar']] enum.force.should == [[0, 'foo'], [2, 'bar']]

View file

@ -0,0 +1,39 @@
require_relative '../../spec_helper'
require_relative 'fixtures/common'
describe "Exception#backtrace_locations" do
before :each do
@backtrace = ExceptionSpecs::Backtrace.backtrace_locations
end
it "returns nil if no backtrace was set" do
Exception.new.backtrace_locations.should be_nil
end
it "returns an Array" do
@backtrace.should be_an_instance_of(Array)
end
it "sets each element to a Thread::Backtrace::Location" do
@backtrace.each {|l| l.should be_an_instance_of(Thread::Backtrace::Location)}
end
it "produces a backtrace for an exception captured using $!" do
exception = begin
raise
rescue RuntimeError
$!
end
exception.backtrace_locations.first.path.should =~ /backtrace_locations_spec/
end
it "returns an Array that can be updated" do
begin
raise
rescue RuntimeError => e
e.backtrace_locations.unshift "backtrace first"
e.backtrace_locations[0].should == "backtrace first"
end
end
end

View file

@ -4,11 +4,19 @@ module ExceptionSpecs
class Backtrace class Backtrace
def self.backtrace def self.backtrace
begin begin
raise # Do not move this line or update backtrace_spec.rb raise # If you move this line, update backtrace_spec.rb
rescue RuntimeError => e rescue RuntimeError => e
e.backtrace e.backtrace
end end
end end
def self.backtrace_locations
begin
raise
rescue RuntimeError => e
e.backtrace_locations
end
end
end end
class UnExceptional < Exception class UnExceptional < Exception

View file

@ -0,0 +1,38 @@
require_relative '../../spec_helper'
ruby_version_is "2.5" do
describe "Exception#full_message" do
it "returns formatted string of exception using the same format that is used to print an uncaught exceptions to stderr" do
e = RuntimeError.new("Some runtime error")
e.set_backtrace(["a.rb:1", "b.rb:2"])
full_message = e.full_message
full_message.should include "RuntimeError"
full_message.should include "Some runtime error"
full_message.should include "a.rb:1"
full_message.should include "b.rb:2"
end
ruby_version_is "2.5.1" do
it "supports :highlight option and adds escape sequences to highlight some strings" do
e = RuntimeError.new("Some runtime error")
full_message = e.full_message(highlight: true, order: :bottom)
full_message.should include "\e[1mTraceback\e[m (most recent call last)"
full_message.should include "\e[1mSome runtime error (\e[1;4mRuntimeError\e[m\e[1m)"
full_message = e.full_message(highlight: false, order: :bottom)
full_message.should include "Traceback (most recent call last)"
full_message.should include "Some runtime error (RuntimeError)"
end
it "supports :order option and places the error message and the backtrace at the top or the bottom" do
e = RuntimeError.new("Some runtime error")
e.set_backtrace(["a.rb:1", "b.rb:2"])
e.full_message(order: :top, highlight: false).should =~ /a.rb:1.*b.rb:2/m
e.full_message(order: :bottom, highlight: false).should =~ /b.rb:2.*a.rb:1/m
end
end
end
end

View file

@ -27,35 +27,19 @@ describe "NameError#name" do
}.should raise_error(NameError) { |e| e.name.should == :@@doesnt_exist } }.should raise_error(NameError) { |e| e.name.should == :@@doesnt_exist }
end end
ruby_version_is ""..."2.3" do it "returns the first argument passed to the method when a NameError is raised from #instance_variable_get" do
it "always returns a symbol when a NameError is raised from #instance_variable_get" do invalid_ivar_name = "invalid_ivar_name"
-> {
Object.new.instance_variable_get("invalid_ivar_name")
}.should raise_error(NameError) { |e| e.name.should == :invalid_ivar_name }
end
it "always returns a symbol when a NameError is raised from #class_variable_get" do -> {
-> { Object.new.instance_variable_get(invalid_ivar_name)
Object.class_variable_get("invalid_cvar_name") }.should raise_error(NameError) {|e| e.name.should equal(invalid_ivar_name) }
}.should raise_error(NameError) { |e| e.name.should == :invalid_cvar_name }
end
end end
ruby_version_is "2.3" do it "returns the first argument passed to the method when a NameError is raised from #class_variable_get" do
it "returns the first argument passed to the method when a NameError is raised from #instance_variable_get" do invalid_cvar_name = "invalid_cvar_name"
invalid_ivar_name = "invalid_ivar_name"
-> { -> {
Object.new.instance_variable_get(invalid_ivar_name) Object.class_variable_get(invalid_cvar_name)
}.should raise_error(NameError) {|e| e.name.should equal(invalid_ivar_name) } }.should raise_error(NameError) {|e| e.name.should equal(invalid_cvar_name) }
end
it "returns the first argument passed to the method when a NameError is raised from #class_variable_get" do
invalid_cvar_name = "invalid_cvar_name"
-> {
Object.class_variable_get(invalid_cvar_name)
}.should raise_error(NameError) {|e| e.name.should equal(invalid_cvar_name) }
end
end end
end end

View file

@ -1,62 +1,60 @@
require_relative '../../spec_helper' require_relative '../../spec_helper'
require_relative 'fixtures/common' require_relative 'fixtures/common'
ruby_version_is "2.3" do describe "NameError#receiver" do
describe "NameError#receiver" do class ::ReceiverClass
class ::ReceiverClass def call_undefined_class_variable; @@doesnt_exist end
def call_undefined_class_variable; @@doesnt_exist end end
end
it "returns the object that raised the exception" do it "returns the object that raised the exception" do
receiver = Object.new receiver = Object.new
-> {
receiver.doesnt_exist
}.should raise_error(NameError) {|e| e.receiver.should equal(receiver) }
end
it "returns the Object class when an undefined constant is called without namespace" do
-> {
DoesntExist
}.should raise_error(NameError) {|e| e.receiver.should equal(Object) }
end
it "returns a class when an undefined constant is called" do
-> {
NameErrorSpecs::ReceiverClass::DoesntExist
}.should raise_error(NameError) {|e| e.receiver.should equal(NameErrorSpecs::ReceiverClass) }
end
it "returns the Object class when an undefined class variable is called" do
-> {
-> { -> {
receiver.doesnt_exist @@doesnt_exist
}.should raise_error(NameError) {|e| e.receiver.should equal(receiver) } }.should complain(/class variable access from toplevel/)
end }.should raise_error(NameError) {|e| e.receiver.should equal(Object) }
end
it "returns the Object class when an undefined constant is called without namespace" do it "returns a class when an undefined class variable is called in a subclass' namespace" do
-> { -> {
DoesntExist NameErrorSpecs::ReceiverClass.new.call_undefined_class_variable
}.should raise_error(NameError) {|e| e.receiver.should equal(Object) } }.should raise_error(NameError) {|e| e.receiver.should equal(NameErrorSpecs::ReceiverClass) }
end end
it "returns a class when an undefined constant is called" do it "returns the receiver when raised from #instance_variable_get" do
-> { receiver = Object.new
NameErrorSpecs::ReceiverClass::DoesntExist
}.should raise_error(NameError) {|e| e.receiver.should equal(NameErrorSpecs::ReceiverClass) }
end
it "returns the Object class when an undefined class variable is called" do -> {
-> { receiver.instance_variable_get("invalid_ivar_name")
-> { }.should raise_error(NameError) {|e| e.receiver.should equal(receiver) }
@@doesnt_exist end
}.should complain(/class variable access from toplevel/)
}.should raise_error(NameError) {|e| e.receiver.should equal(Object) }
end
it "returns a class when an undefined class variable is called in a subclass' namespace" do it "returns the receiver when raised from #class_variable_get" do
-> { -> {
NameErrorSpecs::ReceiverClass.new.call_undefined_class_variable Object.class_variable_get("invalid_cvar_name")
}.should raise_error(NameError) {|e| e.receiver.should equal(NameErrorSpecs::ReceiverClass) } }.should raise_error(NameError) {|e| e.receiver.should equal(Object) }
end end
it "returns the receiver when raised from #instance_variable_get" do it "raises an ArgumentError when the receiver is none" do
receiver = Object.new -> { NameError.new.receiver }.should raise_error(ArgumentError)
-> {
receiver.instance_variable_get("invalid_ivar_name")
}.should raise_error(NameError) {|e| e.receiver.should equal(receiver) }
end
it "returns the receiver when raised from #class_variable_get" do
-> {
Object.class_variable_get("invalid_cvar_name")
}.should raise_error(NameError) {|e| e.receiver.should equal(Object) }
end
it "raises an ArgumentError when the receiver is none" do
-> { NameError.new.receiver }.should raise_error(ArgumentError)
end
end end
end end

View file

@ -1,53 +1,51 @@
require_relative '../../spec_helper' require_relative '../../spec_helper'
ruby_version_is "2.3" do describe "File.mkfifo" do
describe "File.mkfifo" do platform_is_not :windows do
platform_is_not :windows do before do
before do @path = tmp('fifo')
@path = tmp('fifo') end
end
after do after do
rm_r(@path) rm_r(@path)
end end
context "when path passed responds to :to_path" do context "when path passed responds to :to_path" do
it "creates a FIFO file at the path specified" do it "creates a FIFO file at the path specified" do
File.mkfifo(@path) File.mkfifo(@path)
File.ftype(@path).should == "fifo"
end
end
context "when path passed is not a String value" do
it "raises a TypeError" do
lambda { File.mkfifo(:"/tmp/fifo") }.should raise_error(TypeError)
end
end
context "when path does not exist" do
it "raises an Errno::ENOENT exception" do
lambda { File.mkfifo("/bogus/path") }.should raise_error(Errno::ENOENT)
end
end
it "creates a FIFO file at the passed path" do
File.mkfifo(@path.to_s)
File.ftype(@path).should == "fifo" File.ftype(@path).should == "fifo"
end end
end
it "creates a FIFO file with passed mode & ~umask" do context "when path passed is not a String value" do
File.mkfifo(@path, 0755) it "raises a TypeError" do
File.stat(@path).mode.should == 010755 & ~File.umask lambda { File.mkfifo(:"/tmp/fifo") }.should raise_error(TypeError)
end end
end
it "creates a FIFO file with a default mode of 0666 & ~umask" do context "when path does not exist" do
File.mkfifo(@path) it "raises an Errno::ENOENT exception" do
File.stat(@path).mode.should == 010666 & ~File.umask lambda { File.mkfifo("/bogus/path") }.should raise_error(Errno::ENOENT)
end end
end
it "returns 0 after creating the FIFO file" do it "creates a FIFO file at the passed path" do
File.mkfifo(@path).should == 0 File.mkfifo(@path.to_s)
end File.ftype(@path).should == "fifo"
end
it "creates a FIFO file with passed mode & ~umask" do
File.mkfifo(@path, 0755)
File.stat(@path).mode.should == 010755 & ~File.umask
end
it "creates a FIFO file with a default mode of 0666 & ~umask" do
File.mkfifo(@path)
File.stat(@path).mode.should == 010666 & ~File.umask
end
it "returns 0 after creating the FIFO file" do
File.mkfifo(@path).should == 0
end end
end end
end end

View file

@ -524,28 +524,26 @@ describe "File.open" do
File.size(@file).should == 0 File.size(@file).should == 0
end end
ruby_version_is "2.3" do platform_is :linux do
platform_is :linux do guard -> { defined?(File::TMPFILE) } do
guard -> { defined?(File::TMPFILE) } do it "creates an unnamed temporary file with File::TMPFILE" do
it "creates an unnamed temporary file with File::TMPFILE" do dir = tmp("tmpfilespec")
dir = tmp("tmpfilespec") mkdir_p dir
mkdir_p dir begin
begin Dir["#{dir}/*"].should == []
File.open(dir, "r+", flags: File::TMPFILE) do |io|
io.write("ruby")
io.flush
io.rewind
io.read.should == "ruby"
Dir["#{dir}/*"].should == [] Dir["#{dir}/*"].should == []
File.open(dir, "r+", flags: File::TMPFILE) do |io|
io.write("ruby")
io.flush
io.rewind
io.read.should == "ruby"
Dir["#{dir}/*"].should == []
end
rescue Errno::EOPNOTSUPP, Errno::EINVAL
# EOPNOTSUPP: no support from the filesystem
# EINVAL: presumably bug in glibc
1.should == 1
ensure
rm_r dir
end end
rescue Errno::EOPNOTSUPP, Errno::EINVAL
# EOPNOTSUPP: no support from the filesystem
# EINVAL: presumably bug in glibc
1.should == 1
ensure
rm_r dir
end end
end end
end end
@ -586,22 +584,20 @@ describe "File.open" do
@fh = File.open(@file, options) @fh = File.open(@file, options)
end end
ruby_version_is "2.3" do it "accepts extra flags as a keyword argument and combine with a string mode" do
it "accepts extra flags as a keyword argument and combine with a string mode" do lambda {
lambda { File.open(@file, "w", flags: File::EXCL) { }
File.open(@file, "w", flags: File::EXCL) { } }.should raise_error(Errno::EEXIST)
}.should raise_error(Errno::EEXIST)
lambda { lambda {
File.open(@file, mode: "w", flags: File::EXCL) { } File.open(@file, mode: "w", flags: File::EXCL) { }
}.should raise_error(Errno::EEXIST) }.should raise_error(Errno::EEXIST)
end end
it "accepts extra flags as a keyword argument and combine with an integer mode" do it "accepts extra flags as a keyword argument and combine with an integer mode" do
lambda { lambda {
File.open(@file, File::WRONLY | File::CREAT, flags: File::EXCL) { } File.open(@file, File::WRONLY | File::CREAT, flags: File::EXCL) { }
}.should raise_error(Errno::EEXIST) }.should raise_error(Errno::EEXIST)
end
end end
platform_is_not :windows do platform_is_not :windows do

View file

@ -48,16 +48,14 @@ describe :file_unlink, shared: true do
File.send(@method, mock_to_path(@file1)).should == 1 File.send(@method, mock_to_path(@file1)).should == 1
end end
ruby_version_is "2.3" do platform_is :windows do
platform_is :windows do it "allows deleting an open file with File::SHARE_DELETE" do
it "allows deleting an open file with File::SHARE_DELETE" do path = tmp("share_delete.txt")
path = tmp("share_delete.txt") File.open(path, mode: File::CREAT | File::WRONLY | File::BINARY | File::SHARE_DELETE) do |f|
File.open(path, mode: File::CREAT | File::WRONLY | File::BINARY | File::SHARE_DELETE) do |f| File.exist?(path).should be_true
File.exist?(path).should be_true File.send(@method, path)
File.send(@method, path)
end
File.exist?(path).should be_false
end end
File.exist?(path).should be_false
end end
end end
end end

View file

@ -19,20 +19,10 @@ describe "File::Stat#ino" do
end end
platform_is :windows do platform_is :windows do
ruby_version_is ""..."2.3" do it "returns BY_HANDLE_FILE_INFORMATION.nFileIndexHigh/Low of a File::Stat object" do
it "returns 0" do st = File.stat(@file)
st = File.stat(@file) st.ino.should be_kind_of(Integer)
st.ino.should be_kind_of(Integer) st.ino.should > 0
st.ino.should == 0
end
end
ruby_version_is "2.3" do
it "returns BY_HANDLE_FILE_INFORMATION.nFileIndexHigh/Low of a File::Stat object" do
st = File.stat(@file)
st.ino.should be_kind_of(Integer)
st.ino.should > 0
end
end end
end end
end end

View file

@ -108,7 +108,7 @@ describe "Hash#compare_by_identity" do
@idh.keys.first.should equal foo @idh.keys.first.should equal foo
end end
ruby_bug "#12855", "2.2.0"..."2.4.1" do ruby_bug "#12855", ""..."2.4.1" do
it "gives different identity for string literals" do it "gives different identity for string literals" do
@idh['foo'] = 1 @idh['foo'] = 1
@idh['foo'] = 2 @idh['foo'] = 2

View file

@ -1,68 +1,66 @@
require_relative '../../spec_helper' require_relative '../../spec_helper'
ruby_version_is '2.3' do describe "Hash#dig" do
describe "Hash#dig" do
it "returns #[] with one arg" do it "returns #[] with one arg" do
h = { 0 => false, a: 1 } h = { 0 => false, a: 1 }
h.dig(:a).should == 1 h.dig(:a).should == 1
h.dig(0).should be_false h.dig(0).should be_false
h.dig(1).should be_nil h.dig(1).should be_nil
end end
it "returns the nested value specified by the sequence of keys" do it "returns the nested value specified by the sequence of keys" do
h = { foo: { bar: { baz: 1 } } } h = { foo: { bar: { baz: 1 } } }
h.dig(:foo, :bar, :baz).should == 1 h.dig(:foo, :bar, :baz).should == 1
h.dig(:foo, :bar, :nope).should be_nil h.dig(:foo, :bar, :nope).should be_nil
h.dig(:foo, :baz).should be_nil h.dig(:foo, :baz).should be_nil
h.dig(:bar, :baz, :foo).should be_nil h.dig(:bar, :baz, :foo).should be_nil
end end
it "returns the nested value specified if the sequence includes an index" do it "returns the nested value specified if the sequence includes an index" do
h = { foo: [1, 2, 3] } h = { foo: [1, 2, 3] }
h.dig(:foo, 2).should == 3 h.dig(:foo, 2).should == 3
end end
it "returns nil if any intermediate step is nil" do it "returns nil if any intermediate step is nil" do
h = { foo: { bar: { baz: 1 } } } h = { foo: { bar: { baz: 1 } } }
h.dig(:foo, :zot, :xyz).should == nil h.dig(:foo, :zot, :xyz).should == nil
end end
it "raises an ArgumentError if no arguments provided" do it "raises an ArgumentError if no arguments provided" do
lambda { { the: 'borg' }.dig() }.should raise_error(ArgumentError) lambda { { the: 'borg' }.dig() }.should raise_error(ArgumentError)
end end
it "handles type-mixed deep digging" do it "handles type-mixed deep digging" do
h = {} h = {}
h[:foo] = [ { bar: [ 1 ] }, [ obj = Object.new, 'str' ] ] h[:foo] = [ { bar: [ 1 ] }, [ obj = Object.new, 'str' ] ]
def obj.dig(*args); [ 42 ] end def obj.dig(*args); [ 42 ] end
h.dig(:foo, 0, :bar).should == [ 1 ] h.dig(:foo, 0, :bar).should == [ 1 ]
h.dig(:foo, 0, :bar, 0).should == 1 h.dig(:foo, 0, :bar, 0).should == 1
h.dig(:foo, 1, 1).should == 'str' h.dig(:foo, 1, 1).should == 'str'
# MRI does not recurse values returned from `obj.dig` # MRI does not recurse values returned from `obj.dig`
h.dig(:foo, 1, 0, 0).should == [ 42 ] h.dig(:foo, 1, 0, 0).should == [ 42 ]
h.dig(:foo, 1, 0, 0, 10).should == [ 42 ] h.dig(:foo, 1, 0, 0, 10).should == [ 42 ]
end end
it "raises TypeError if an intermediate element does not respond to #dig" do it "raises TypeError if an intermediate element does not respond to #dig" do
h = {} h = {}
h[:foo] = [ { bar: [ 1 ] }, [ nil, 'str' ] ] h[:foo] = [ { bar: [ 1 ] }, [ nil, 'str' ] ]
lambda { h.dig(:foo, 0, :bar, 0, 0) }.should raise_error(TypeError) lambda { h.dig(:foo, 0, :bar, 0, 0) }.should raise_error(TypeError)
lambda { h.dig(:foo, 1, 1, 0) }.should raise_error(TypeError) lambda { h.dig(:foo, 1, 1, 0) }.should raise_error(TypeError)
end end
it "calls #dig on the result of #[] with the remaining arguments" do it "calls #dig on the result of #[] with the remaining arguments" do
h = { foo: { bar: { baz: 42 } } } h = { foo: { bar: { baz: 42 } } }
h[:foo].should_receive(:dig).with(:bar, :baz).and_return(42) h[:foo].should_receive(:dig).with(:bar, :baz).and_return(42)
h.dig(:foo, :bar, :baz).should == 42 h.dig(:foo, :bar, :baz).should == 42
end end
it "respects Hash's default" do it "respects Hash's default" do
default = {bar: 42} default = {bar: 42}
h = Hash.new(default) h = Hash.new(default)
h.dig(:foo).should equal default h.dig(:foo).should equal default
h.dig(:foo, :bar).should == 42 h.dig(:foo, :bar).should == 42
end
end end
end end

View file

@ -2,32 +2,30 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes' require_relative 'fixtures/classes'
require_relative '../../shared/hash/key_error' require_relative '../../shared/hash/key_error'
ruby_version_is "2.3" do describe "Hash#fetch_values" do
describe "Hash#fetch_values" do before :each do
before :each do @hash = { a: 1, b: 2, c: 3 }
@hash = { a: 1, b: 2, c: 3 } end
describe "with matched keys" do
it "returns the values for keys" do
@hash.fetch_values(:a).should == [1]
@hash.fetch_values(:a, :c).should == [1, 3]
end end
end
describe "with matched keys" do describe "with unmatched keys" do
it "returns the values for keys" do it_behaves_like :key_error, ->(obj, key) { obj.fetch_values(key) }, Hash.new(a: 5)
@hash.fetch_values(:a).should == [1]
@hash.fetch_values(:a, :c).should == [1, 3] it "returns the default value from block" do
end @hash.fetch_values(:z) { |key| "`#{key}' is not found" }.should == ["`z' is not found"]
@hash.fetch_values(:a, :z) { |key| "`#{key}' is not found" }.should == [1, "`z' is not found"]
end end
end
describe "with unmatched keys" do describe "without keys" do
it_behaves_like :key_error, ->(obj, key) { obj.fetch_values(key) }, Hash.new(a: 5) it "returns an empty Array" do
@hash.fetch_values.should == []
it "returns the default value from block" do
@hash.fetch_values(:z) { |key| "`#{key}' is not found" }.should == ["`z' is not found"]
@hash.fetch_values(:a, :z) { |key| "`#{key}' is not found" }.should == [1, "`z' is not found"]
end
end
describe "without keys" do
it "returns an empty Array" do
@hash.fetch_values.should == []
end
end end
end end
end end

View file

@ -17,6 +17,13 @@ module HashSpecs
end end
end end
class SubHashSettingInInitialize < Hash
def initialize(*args, &block)
self[:foo] = :bar
super(*args, &block)
end
end
class DefaultHash < Hash class DefaultHash < Hash
def default(key) def default(key)
100 100

View file

@ -2,43 +2,41 @@ require_relative '../../spec_helper'
require_relative 'shared/comparison' require_relative 'shared/comparison'
require_relative 'shared/greater_than' require_relative 'shared/greater_than'
ruby_version_is "2.3" do describe "Hash#>" do
describe "Hash#>" do it_behaves_like :hash_comparison, :>
it_behaves_like :hash_comparison, :> it_behaves_like :hash_greater_than, :>
it_behaves_like :hash_greater_than, :>
it "returns false if both hashes are identical" do it "returns false if both hashes are identical" do
h = { a: 1, b: 2 } h = { a: 1, b: 2 }
(h > h).should be_false (h > h).should be_false
end end
end end
describe "Hash#>" do describe "Hash#>" do
before :each do before :each do
@hash = {a:1, b:2} @hash = {a:1, b:2}
@bigger = {a:1, b:2, c:3} @bigger = {a:1, b:2, c:3}
@unrelated = {c:3, d:4} @unrelated = {c:3, d:4}
@similar = {a:2, b:3} @similar = {a:2, b:3}
end end
it "returns false when receiver size is smaller than argument" do it "returns false when receiver size is smaller than argument" do
(@hash > @bigger).should == false (@hash > @bigger).should == false
(@unrelated > @bigger).should == false (@unrelated > @bigger).should == false
end end
it "returns false when receiver size is the same as argument" do it "returns false when receiver size is the same as argument" do
(@hash > @hash).should == false (@hash > @hash).should == false
(@hash > @unrelated).should == false (@hash > @unrelated).should == false
(@unrelated > @hash).should == false (@unrelated > @hash).should == false
end end
it "returns true when argument is a subset of receiver" do it "returns true when argument is a subset of receiver" do
(@bigger > @hash).should == true (@bigger > @hash).should == true
end end
it "returns false when keys match but values don't" do it "returns false when keys match but values don't" do
(@hash > @similar).should == false (@hash > @similar).should == false
(@similar > @hash).should == false (@similar > @hash).should == false
end
end end
end end

View file

@ -2,43 +2,41 @@ require_relative '../../spec_helper'
require_relative 'shared/comparison' require_relative 'shared/comparison'
require_relative 'shared/greater_than' require_relative 'shared/greater_than'
ruby_version_is "2.3" do describe "Hash#>=" do
describe "Hash#>=" do it_behaves_like :hash_comparison, :>=
it_behaves_like :hash_comparison, :>= it_behaves_like :hash_greater_than, :>=
it_behaves_like :hash_greater_than, :>=
it "returns true if both hashes are identical" do it "returns true if both hashes are identical" do
h = { a: 1, b: 2 } h = { a: 1, b: 2 }
(h >= h).should be_true (h >= h).should be_true
end end
end end
describe "Hash#>=" do describe "Hash#>=" do
before :each do before :each do
@hash = {a:1, b:2} @hash = {a:1, b:2}
@bigger = {a:1, b:2, c:3} @bigger = {a:1, b:2, c:3}
@unrelated = {c:3, d:4} @unrelated = {c:3, d:4}
@similar = {a:2, b:3} @similar = {a:2, b:3}
end end
it "returns false when receiver size is smaller than argument" do it "returns false when receiver size is smaller than argument" do
(@hash >= @bigger).should == false (@hash >= @bigger).should == false
(@unrelated >= @bigger).should == false (@unrelated >= @bigger).should == false
end end
it "returns false when argument is not a subset or not equals to receiver" do it "returns false when argument is not a subset or not equals to receiver" do
(@hash >= @unrelated).should == false (@hash >= @unrelated).should == false
(@unrelated >= @hash).should == false (@unrelated >= @hash).should == false
end end
it "returns true when argument is a subset of receiver or equals to receiver" do it "returns true when argument is a subset of receiver or equals to receiver" do
(@bigger >= @hash).should == true (@bigger >= @hash).should == true
(@hash >= @hash).should == true (@hash >= @hash).should == true
end end
it "returns false when keys match but values don't" do it "returns false when keys match but values don't" do
(@hash >= @similar).should == false (@hash >= @similar).should == false
(@similar >= @hash).should == false (@similar >= @hash).should == false
end
end end
end end

View file

@ -9,16 +9,37 @@ describe "Hash#initialize" do
it "can be used to reset default_proc" do it "can be used to reset default_proc" do
h = { "foo" => 1, "bar" => 2 } h = { "foo" => 1, "bar" => 2 }
h.default_proc.should == nil h.default_proc.should == nil
h.instance_eval { initialize { |_, k| k * 2 } } h.send(:initialize) { |_, k| k * 2 }
h.default_proc.should_not == nil h.default_proc.should_not == nil
h["a"].should == "aa" h["a"].should == "aa"
end end
it "can be used to reset the default value" do
h = {}
h.default = 42
h.default.should == 42
h.send(:initialize, 1)
h.default.should == 1
h.send(:initialize)
h.default.should == nil
end
it "receives the arguments passed to Hash#new" do it "receives the arguments passed to Hash#new" do
HashSpecs::NewHash.new(:one, :two)[0].should == :one HashSpecs::NewHash.new(:one, :two)[0].should == :one
HashSpecs::NewHash.new(:one, :two)[1].should == :two HashSpecs::NewHash.new(:one, :two)[1].should == :two
end end
it "does not change the storage, only the default value or proc" do
h = HashSpecs::SubHashSettingInInitialize.new
h.to_a.should == [[:foo, :bar]]
h = HashSpecs::SubHashSettingInInitialize.new(:default)
h.to_a.should == [[:foo, :bar]]
h = HashSpecs::SubHashSettingInInitialize.new { :default_block }
h.to_a.should == [[:foo, :bar]]
end
it "returns self" do it "returns self" do
h = Hash.new h = Hash.new
h.send(:initialize).should equal(h) h.send(:initialize).should equal(h)

View file

@ -2,43 +2,41 @@ require_relative '../../spec_helper'
require_relative 'shared/comparison' require_relative 'shared/comparison'
require_relative 'shared/less_than' require_relative 'shared/less_than'
ruby_version_is "2.3" do describe "Hash#<" do
describe "Hash#<" do it_behaves_like :hash_comparison, :<
it_behaves_like :hash_comparison, :< it_behaves_like :hash_less_than, :<
it_behaves_like :hash_less_than, :<
it "returns false if both hashes are identical" do it "returns false if both hashes are identical" do
h = { a: 1, b: 2 } h = { a: 1, b: 2 }
(h < h).should be_false (h < h).should be_false
end end
end end
describe "Hash#<" do describe "Hash#<" do
before :each do before :each do
@hash = {a:1, b:2} @hash = {a:1, b:2}
@bigger = {a:1, b:2, c:3} @bigger = {a:1, b:2, c:3}
@unrelated = {c:3, d:4} @unrelated = {c:3, d:4}
@similar = {a:2, b:3} @similar = {a:2, b:3}
end end
it "returns false when receiver size is larger than argument" do it "returns false when receiver size is larger than argument" do
(@bigger < @hash).should == false (@bigger < @hash).should == false
(@bigger < @unrelated).should == false (@bigger < @unrelated).should == false
end end
it "returns false when receiver size is the same as argument" do it "returns false when receiver size is the same as argument" do
(@hash < @hash).should == false (@hash < @hash).should == false
(@hash < @unrelated).should == false (@hash < @unrelated).should == false
(@unrelated < @hash).should == false (@unrelated < @hash).should == false
end end
it "returns true when receiver is a subset of argument" do it "returns true when receiver is a subset of argument" do
(@hash < @bigger).should == true (@hash < @bigger).should == true
end end
it "returns false when keys match but values don't" do it "returns false when keys match but values don't" do
(@hash < @similar).should == false (@hash < @similar).should == false
(@similar < @hash).should == false (@similar < @hash).should == false
end
end end
end end

View file

@ -2,43 +2,41 @@ require_relative '../../spec_helper'
require_relative 'shared/comparison' require_relative 'shared/comparison'
require_relative 'shared/less_than' require_relative 'shared/less_than'
ruby_version_is "2.3" do describe "Hash#<=" do
describe "Hash#<=" do it_behaves_like :hash_comparison, :<=
it_behaves_like :hash_comparison, :<= it_behaves_like :hash_less_than, :<=
it_behaves_like :hash_less_than, :<=
it "returns true if both hashes are identical" do it "returns true if both hashes are identical" do
h = { a: 1, b: 2 } h = { a: 1, b: 2 }
(h <= h).should be_true (h <= h).should be_true
end end
end end
describe "Hash#<=" do describe "Hash#<=" do
before :each do before :each do
@hash = {a:1, b:2} @hash = {a:1, b:2}
@bigger = {a:1, b:2, c:3} @bigger = {a:1, b:2, c:3}
@unrelated = {c:3, d:4} @unrelated = {c:3, d:4}
@similar = {a:2, b:3} @similar = {a:2, b:3}
end end
it "returns false when receiver size is larger than argument" do it "returns false when receiver size is larger than argument" do
(@bigger <= @hash).should == false (@bigger <= @hash).should == false
(@bigger <= @unrelated).should == false (@bigger <= @unrelated).should == false
end end
it "returns false when receiver size is the same as argument" do it "returns false when receiver size is the same as argument" do
(@hash <= @unrelated).should == false (@hash <= @unrelated).should == false
(@unrelated <= @hash).should == false (@unrelated <= @hash).should == false
end end
it "returns true when receiver is a subset of argument or equals to argument" do it "returns true when receiver is a subset of argument or equals to argument" do
(@hash <= @bigger).should == true (@hash <= @bigger).should == true
(@hash <= @hash).should == true (@hash <= @hash).should == true
end end
it "returns false when keys match but values don't" do it "returns false when keys match but values don't" do
(@hash <= @similar).should == false (@hash <= @similar).should == false
(@similar <= @hash).should == false (@similar <= @hash).should == false
end
end end
end end

View file

@ -87,23 +87,10 @@ describe :hash_to_s, shared: true do
{ nil => nil }.untrust.send(@method).untrusted?.should be_true { nil => nil }.untrust.send(@method).untrusted?.should be_true
end end
ruby_version_is ''...'2.3' do it "does not raise if inspected result is not default external encoding" do
it "raises if inspected result is not default external encoding" do utf_16be = mock("utf_16be")
utf_16be = mock("utf_16be") utf_16be.should_receive(:inspect).and_return(%<"utf_16be \u3042">.encode!(Encoding::UTF_16BE))
utf_16be.should_receive(:inspect).and_return(%<"utf_16be \u3042">.encode!(Encoding::UTF_16BE))
lambda { {a: utf_16be}.send(@method).should == '{:a=>"utf_16be \u3042"}'
{a: utf_16be}.send(@method)
}.should raise_error(Encoding::CompatibilityError)
end
end
ruby_version_is '2.3' do
it "does not raise if inspected result is not default external encoding" do
utf_16be = mock("utf_16be")
utf_16be.should_receive(:inspect).and_return(%<"utf_16be \u3042">.encode!(Encoding::UTF_16BE))
{a: utf_16be}.send(@method).should == '{:a=>"utf_16be \u3042"}'
end
end end
end end

View file

@ -1,89 +1,87 @@
require_relative '../../spec_helper' require_relative '../../spec_helper'
require_relative 'fixtures/classes' require_relative 'fixtures/classes'
ruby_version_is "2.3" do describe "Hash#to_proc" do
describe "Hash#to_proc" do before :each do
@key = Object.new
@value = Object.new
@hash = { @key => @value }
@default = Object.new
@unstored = Object.new
end
it "returns an instance of Proc" do
@hash.to_proc.should be_an_instance_of Proc
end
describe "the returned proc" do
before :each do before :each do
@key = Object.new @proc = @hash.to_proc
@value = Object.new
@hash = { @key => @value }
@default = Object.new
@unstored = Object.new
end end
it "returns an instance of Proc" do it "is not a lambda" do
@hash.to_proc.should be_an_instance_of Proc @proc.lambda?.should == false
end end
describe "the returned proc" do it "raises ArgumentError if not passed exactly one argument" do
before :each do lambda {
@proc = @hash.to_proc @proc.call
}.should raise_error(ArgumentError)
lambda {
@proc.call 1, 2
}.should raise_error(ArgumentError)
end
context "with a stored key" do
it "returns the paired value" do
@proc.call(@key).should equal(@value)
end
end
context "passed as a block" do
it "retrieves the hash's values" do
[@key].map(&@proc)[0].should equal(@value)
end end
it "is not a lambda" do context "to instance_exec" do
@proc.lambda?.should == false it "always retrieves the original hash's values" do
hash = {foo: 1, bar: 2}
proc = hash.to_proc
hash.instance_exec(:foo, &proc).should == 1
hash2 = {quux: 1}
hash2.instance_exec(:foo, &proc).should == 1
end
end
end
context "with no stored key" do
it "returns nil" do
@proc.call(@unstored).should be_nil
end end
it "raises ArgumentError if not passed exactly one argument" do context "when the hash has a default value" do
lambda { before :each do
@proc.call @hash.default = @default
}.should raise_error(ArgumentError) end
lambda { it "returns the default value" do
@proc.call 1, 2 @proc.call(@unstored).should equal(@default)
}.should raise_error(ArgumentError)
end
context "with a stored key" do
it "returns the paired value" do
@proc.call(@key).should equal(@value)
end end
end end
context "passed as a block" do context "when the hash has a default proc" do
it "retrieves the hash's values" do it "returns an evaluated value from the default proc" do
[@key].map(&@proc)[0].should equal(@value) @hash.default_proc = -> hash, called_with { [hash.keys, called_with] }
end @proc.call(@unstored).should == [[@key], @unstored]
context "to instance_exec" do
it "always retrieves the original hash's values" do
hash = {foo: 1, bar: 2}
proc = hash.to_proc
hash.instance_exec(:foo, &proc).should == 1
hash2 = {quux: 1}
hash2.instance_exec(:foo, &proc).should == 1
end
end end
end end
end
context "with no stored key" do it "raises an ArgumentError when calling #call on the Proc with no arguments" do
it "returns nil" do lambda { @hash.to_proc.call }.should raise_error(ArgumentError)
@proc.call(@unstored).should be_nil
end
context "when the hash has a default value" do
before :each do
@hash.default = @default
end
it "returns the default value" do
@proc.call(@unstored).should equal(@default)
end
end
context "when the hash has a default proc" do
it "returns an evaluated value from the default proc" do
@hash.default_proc = -> hash, called_with { [hash.keys, called_with] }
@proc.call(@unstored).should == [[@key], @unstored]
end
end
end
it "raises an ArgumentError when calling #call on the Proc with no arguments" do
lambda { @hash.to_proc.call }.should raise_error(ArgumentError)
end
end end
end end
end end

View file

@ -41,9 +41,7 @@ describe "IO.binread" do
lambda { IO.binread @fname, -1 }.should raise_error(ArgumentError) lambda { IO.binread @fname, -1 }.should raise_error(ArgumentError)
end end
ruby_version_is "2.3" do # MRI leaks the fd on older versions it "raises an Errno::EINVAL when not passed a valid offset" do
it "raises an Errno::EINVAL when not passed a valid offset" do lambda { IO.binread @fname, 0, -1 }.should raise_error(Errno::EINVAL)
lambda { IO.binread @fname, 0, -1 }.should raise_error(Errno::EINVAL)
end
end end
end end

View file

@ -11,17 +11,7 @@ describe "IO#close_on_exec=" do
rm_r @name rm_r @name
end end
guard -> { platform_is :windows and ruby_version_is ""..."2.3" } do guard -> { platform_is_not :windows } do
it "returns false from #respond_to?" do
@io.respond_to?(:close_on_exec=).should be_false
end
it "raises a NotImplementedError when called" do
lambda { @io.close_on_exec = true }.should raise_error(NotImplementedError)
end
end
guard -> { platform_is_not :windows or ruby_version_is "2.3" } do
it "sets the close-on-exec flag if true" do it "sets the close-on-exec flag if true" do
@io.close_on_exec = true @io.close_on_exec = true
@io.close_on_exec?.should == true @io.close_on_exec?.should == true
@ -72,17 +62,7 @@ describe "IO#close_on_exec?" do
rm_r @name rm_r @name
end end
guard -> { platform_is :windows and ruby_version_is ""..."2.3" } do guard -> { platform_is_not :windows } do
it "returns false from #respond_to?" do
@io.respond_to?(:close_on_exec?).should be_false
end
it "raises a NotImplementedError when called" do
lambda { @io.close_on_exec? }.should raise_error(NotImplementedError)
end
end
guard -> { platform_is_not :windows or ruby_version_is "2.3" } do
it "returns true by default" do it "returns true by default" do
@io.close_on_exec?.should == true @io.close_on_exec?.should == true
end end

View file

@ -19,20 +19,10 @@ describe "IO#close_read" do
lambda { @io.read }.should raise_error(IOError) lambda { @io.read }.should raise_error(IOError)
end end
ruby_version_is ''...'2.3' do it "does nothing on subsequent invocations" do
it "raises an IOError on subsequent invocations" do @io.close_read
@io.close_read
lambda { @io.close_read }.should raise_error(IOError) @io.close_read.should be_nil
end
end
ruby_version_is '2.3' do
it "does nothing on subsequent invocations" do
@io.close_read
@io.close_read.should be_nil
end
end end
it "allows subsequent invocation of close" do it "allows subsequent invocation of close" do
@ -62,19 +52,9 @@ describe "IO#close_read" do
io.closed?.should == true io.closed?.should == true
end end
ruby_version_is ''...'2.3' do it "does nothing on closed stream" do
it "raises IOError on closed stream" do @io.close
@io.close
lambda { @io.close_read }.should raise_error(IOError) @io.close_read.should be_nil
end
end
ruby_version_is '2.3' do
it "does nothing on closed stream" do
@io.close
@io.close_read.should be_nil
end
end end
end end

View file

@ -38,19 +38,10 @@ describe "IO#close" do
lambda { @io.write "data" }.should_not raise_error(IOError) lambda { @io.write "data" }.should_not raise_error(IOError)
end end
ruby_version_is ''...'2.3' do it "does nothing if already closed" do
it "raises an IOError if closed" do @io.close
@io.close
lambda { @io.close }.should raise_error(IOError)
end
end
ruby_version_is "2.3" do @io.close.should be_nil
it "does nothing if already closed" do
@io.close
@io.close.should be_nil
end
end end
ruby_version_is '2.5' do ruby_version_is '2.5' do

View file

@ -18,20 +18,10 @@ describe "IO#close_write" do
lambda { @io.write "attempt to write" }.should raise_error(IOError) lambda { @io.write "attempt to write" }.should raise_error(IOError)
end end
ruby_version_is ''...'2.3' do it "does nothing on subsequent invocations" do
it "raises an IOError on subsequent invocations" do @io.close_write
@io.close_write
lambda { @io.close_write }.should raise_error(IOError) @io.close_write.should be_nil
end
end
ruby_version_is '2.3' do
it "does nothing on subsequent invocations" do
@io.close_write
@io.close_write.should be_nil
end
end end
it "allows subsequent invocation of close" do it "allows subsequent invocation of close" do
@ -66,19 +56,9 @@ describe "IO#close_write" do
@io.read.should == "12345\n" @io.read.should == "12345\n"
end end
ruby_version_is ''...'2.3' do it "does nothing on closed stream" do
it "raises IOError on closed stream" do @io.close
@io.close
lambda { @io.close_write }.should raise_error(IOError) @io.close_write.should be_nil
end
end
ruby_version_is '2.3' do
it "does nothing on closed stream" do
@io.close
@io.close_write.should be_nil
end
end end
end end

View file

@ -37,9 +37,7 @@ describe "IO#each_codepoint" do
@io.close if @io @io.close if @io
end end
ruby_version_is "2.3" do # earlier versions stay blocked it "raises an exception at incomplete character before EOF when conversion takes place" do
it "raises an exception at incomplete character before EOF when conversion takes place" do lambda { @io.each_codepoint {} }.should raise_error(ArgumentError)
lambda { @io.each_codepoint {} }.should raise_error(ArgumentError)
end
end end
end end

View file

@ -22,23 +22,21 @@ describe "IO#read_nonblock" do
} }
end end
ruby_version_is "2.3" do context "when exception option is set to false" do
context "when exception option is set to false" do context "when there is no data" do
context "when there is no data" do it "returns :wait_readable" do
it "returns :wait_readable" do @read.read_nonblock(5, exception: false).should == :wait_readable
@read.read_nonblock(5, exception: false).should == :wait_readable
end
end end
end
context "when the end is reached" do context "when the end is reached" do
it "returns nil" do it "returns nil" do
@write << "hello" @write << "hello"
@write.close @write.close
@read.read_nonblock(5) @read.read_nonblock(5)
@read.read_nonblock(5, exception: false).should be_nil @read.read_nonblock(5, exception: false).should be_nil
end
end end
end end
end end

View file

@ -66,12 +66,10 @@ describe 'IO#write_nonblock' do
} }
end end
ruby_version_is "2.3" do context "when exception option is set to false" do
context "when exception option is set to false" do it "returns :wait_writable when the operation would block" do
it "returns :wait_writable when the operation would block" do loop { break if @write.write_nonblock("a" * 10_000, exception: false) == :wait_writable }
loop { break if @write.write_nonblock("a" * 10_000, exception: false) == :wait_writable } 1.should == 1
1.should == 1
end
end end
end end

View file

@ -86,16 +86,14 @@ describe "Kernel#define_singleton_method" do
}.should raise_error(ArgumentError) }.should raise_error(ArgumentError)
end end
ruby_version_is "2.3" do it "does not use the caller block when no block is given" do
it "does not use the caller block when no block is given" do o = Object.new
o = Object.new def o.define(name)
def o.define(name) define_singleton_method(name)
define_singleton_method(name)
end
lambda {
o.define(:foo) { raise "not used" }
}.should raise_error(ArgumentError)
end end
lambda {
o.define(:foo) { raise "not used" }
}.should raise_error(ArgumentError)
end end
end end

View file

@ -58,15 +58,13 @@ describe "Kernel.loop" do
lambda{ loop do raise StandardError end }.should raise_error( StandardError ) lambda{ loop do raise StandardError end }.should raise_error( StandardError )
end end
ruby_version_is "2.3" do it "returns StopIteration#result, the result value of a finished iterator" do
it "returns StopIteration#result, the result value of a finished iterator" do e = Enumerator.new { |y|
e = Enumerator.new { |y| y << 1
y << 1 y << 2
y << 2 :stopped
:stopped }
} loop { e.next }.should == :stopped
loop { e.next }.should == :stopped
end
end end
describe "when no block is given" do describe "when no block is given" do

View file

@ -40,6 +40,48 @@ describe "Kernel#require_relative with a relative path" do
ScratchPad.recorded.should == [:loaded] ScratchPad.recorded.should == [:loaded]
end end
describe "in an #instance_eval with a" do
it "synthetic file base name loads a file base name relative to the working directory" do
Dir.chdir @abs_dir do
Object.new.instance_eval("require_relative(#{File.basename(@path).inspect})", "foo.rb").should be_true
end
ScratchPad.recorded.should == [:loaded]
end
it "synthetic file path loads a relative path relative to the working directory plus the directory of the synthetic path" do
Dir.chdir @abs_dir do
Object.new.instance_eval("require_relative(File.join('..', #{File.basename(@path).inspect}))", "bar/foo.rb").should be_true
end
ScratchPad.recorded.should == [:loaded]
end
platform_is_not :windows do
it "synthetic relative file path with a Windows path separator specified loads a relative path relative to the working directory" do
Dir.chdir @abs_dir do
Object.new.instance_eval("require_relative(#{File.basename(@path).inspect})", "bar\\foo.rb").should be_true
end
ScratchPad.recorded.should == [:loaded]
end
end
it "absolute file path loads a path relative to the absolute path" do
Object.new.instance_eval("require_relative(#{@path.inspect})", __FILE__).should be_true
ScratchPad.recorded.should == [:loaded]
end
it "absolute file path loads a path relative to the root directory" do
root = @abs_path
until File.dirname(root) == root
root = File.dirname(root)
end
root_relative = @abs_path[root.size..-1]
Object.new.instance_eval("require_relative(#{root_relative.inspect})", "/").should be_true
ScratchPad.recorded.should == [:loaded]
end
end
it "loads a file defining many methods" do it "loads a file defining many methods" do
require_relative("#{@dir}/methods_fixture.rb").should be_true require_relative("#{@dir}/methods_fixture.rb").should be_true
ScratchPad.recorded.should == [:loaded] ScratchPad.recorded.should == [:loaded]

View file

@ -454,21 +454,7 @@ describe :kernel_require, shared: true do
ScratchPad.recorded.should == [] ScratchPad.recorded.should == []
end end
ruby_version_is "2.2"..."2.3" do ruby_version_is ""..."2.5" do
it "complex, enumerator, rational and unicode_normalize are already required" do
provided = %w[complex enumerator rational unicode_normalize]
features = ruby_exe("puts $LOADED_FEATURES", options: '--disable-gems')
provided.each { |feature|
features.should =~ /\b#{feature}\.(rb|so)$/
}
code = provided.map { |f| "puts require #{f.inspect}\n" }.join
required = ruby_exe(code, options: '--disable-gems')
required.should == "false\n" * provided.size
end
end
ruby_version_is "2.3"..."2.5" do
it "complex, enumerator, rational, thread and unicode_normalize are already required" do it "complex, enumerator, rational, thread and unicode_normalize are already required" do
provided = %w[complex enumerator rational thread unicode_normalize] provided = %w[complex enumerator rational thread unicode_normalize]
features = ruby_exe("puts $LOADED_FEATURES", options: '--disable-gems') features = ruby_exe("puts $LOADED_FEATURES", options: '--disable-gems')

View file

@ -1,135 +1,132 @@
require_relative '../../spec_helper' require_relative '../../spec_helper'
require_relative 'fixtures/classes'
ruby_version_is "2.0.0" do describe "main.using" do
require_relative 'fixtures/classes' it "requires one Module argument" do
lambda do
eval('using', TOPLEVEL_BINDING)
end.should raise_error(ArgumentError)
describe "main.using" do lambda do
it "requires one Module argument" do eval('using "foo"', TOPLEVEL_BINDING)
lambda do end.should raise_error(TypeError)
eval('using', TOPLEVEL_BINDING) end
end.should raise_error(ArgumentError)
lambda do it "uses refinements from the given module only in the target file" do
eval('using "foo"', TOPLEVEL_BINDING) require_relative 'fixtures/string_refinement'
end.should raise_error(TypeError) load File.expand_path('../fixtures/string_refinement_user.rb', __FILE__)
end MainSpecs::DATA[:in_module].should == 'foo'
MainSpecs::DATA[:toplevel].should == 'foo'
lambda do
'hello'.foo
end.should raise_error(NoMethodError)
end
it "uses refinements from the given module only in the target file" do it "uses refinements from the given module for method calls in the target file" do
require_relative 'fixtures/string_refinement' require_relative 'fixtures/string_refinement'
load File.expand_path('../fixtures/string_refinement_user.rb', __FILE__) load File.expand_path('../fixtures/string_refinement_user.rb', __FILE__)
MainSpecs::DATA[:in_module].should == 'foo' lambda do
MainSpecs::DATA[:toplevel].should == 'foo' 'hello'.foo
lambda do end.should raise_error(NoMethodError)
'hello'.foo MainSpecs.call_foo('hello').should == 'foo'
end.should raise_error(NoMethodError) end
end
it "uses refinements from the given module for method calls in the target file" do it "uses refinements from the given module in the eval string" do
require_relative 'fixtures/string_refinement' cls = MainSpecs::DATA[:cls] = Class.new {def foo; 'foo'; end}
load File.expand_path('../fixtures/string_refinement_user.rb', __FILE__) MainSpecs::DATA[:mod] = Module.new do
lambda do refine(cls) do
'hello'.foo def foo; 'bar'; end
end.should raise_error(NoMethodError) end
MainSpecs.call_foo('hello').should == 'foo' end
end eval(<<-EOS, TOPLEVEL_BINDING).should == 'bar'
using MainSpecs::DATA[:mod]
it "uses refinements from the given module in the eval string" do MainSpecs::DATA[:cls].new.foo
cls = MainSpecs::DATA[:cls] = Class.new {def foo; 'foo'; end} EOS
MainSpecs::DATA[:mod] = Module.new do end
refine(cls) do
def foo; 'bar'; end it "does not affect methods defined before it is called" do
end cls = Class.new {def foo; 'foo'; end}
MainSpecs::DATA[:mod] = Module.new do
refine(cls) do
def foo; 'bar'; end
end
end
x = MainSpecs::DATA[:x] = Object.new
eval <<-EOS, TOPLEVEL_BINDING
x = MainSpecs::DATA[:x]
def x.before_using(obj)
obj.foo
end
using MainSpecs::DATA[:mod]
def x.after_using(obj)
obj.foo
end
EOS
obj = cls.new
x.before_using(obj).should == 'foo'
x.after_using(obj).should == 'bar'
end
it "propagates refinements added to existing modules after it is called" do
cls = Class.new {def foo; 'foo'; end}
mod = MainSpecs::DATA[:mod] = Module.new do
refine(cls) do
def foo; 'quux'; end
end
end
x = MainSpecs::DATA[:x] = Object.new
eval <<-EOS, TOPLEVEL_BINDING
using MainSpecs::DATA[:mod]
x = MainSpecs::DATA[:x]
def x.call_foo(obj)
obj.foo
end
def x.call_bar(obj)
obj.bar
end
EOS
obj = cls.new
x.call_foo(obj).should == 'quux'
mod.module_eval do
refine(cls) do
def bar; 'quux'; end
end end
eval(<<-EOS, TOPLEVEL_BINDING).should == 'bar'
using MainSpecs::DATA[:mod]
MainSpecs::DATA[:cls].new.foo
EOS
end end
it "does not affect methods defined before it is called" do x.call_bar(obj).should == 'quux'
cls = Class.new {def foo; 'foo'; end} end
MainSpecs::DATA[:mod] = Module.new do
refine(cls) do
def foo; 'bar'; end
end
end
x = MainSpecs::DATA[:x] = Object.new
eval <<-EOS, TOPLEVEL_BINDING
x = MainSpecs::DATA[:x]
def x.before_using(obj)
obj.foo
end
using MainSpecs::DATA[:mod]
def x.after_using(obj)
obj.foo
end
EOS
obj = cls.new it "does not propagate refinements of new modules added after it is called" do
x.before_using(obj).should == 'foo' cls = Class.new {def foo; 'foo'; end}
x.after_using(obj).should == 'bar' cls2 = Class.new {def bar; 'bar'; end}
mod = MainSpecs::DATA[:mod] = Module.new do
refine(cls) do
def foo; 'quux'; end
end
end
x = MainSpecs::DATA[:x] = Object.new
eval <<-EOS, TOPLEVEL_BINDING
using MainSpecs::DATA[:mod]
x = MainSpecs::DATA[:x]
def x.call_foo(obj)
obj.foo
end
def x.call_bar(obj)
obj.bar
end
EOS
x.call_foo(cls.new).should == 'quux'
mod.module_eval do
refine(cls2) do
def bar; 'quux'; end
end
end end
it "propagates refinements added to existing modules after it is called" do x.call_bar(cls2.new).should == 'bar'
cls = Class.new {def foo; 'foo'; end}
mod = MainSpecs::DATA[:mod] = Module.new do
refine(cls) do
def foo; 'quux'; end
end
end
x = MainSpecs::DATA[:x] = Object.new
eval <<-EOS, TOPLEVEL_BINDING
using MainSpecs::DATA[:mod]
x = MainSpecs::DATA[:x]
def x.call_foo(obj)
obj.foo
end
def x.call_bar(obj)
obj.bar
end
EOS
obj = cls.new
x.call_foo(obj).should == 'quux'
mod.module_eval do
refine(cls) do
def bar; 'quux'; end
end
end
x.call_bar(obj).should == 'quux'
end
it "does not propagate refinements of new modules added after it is called" do
cls = Class.new {def foo; 'foo'; end}
cls2 = Class.new {def bar; 'bar'; end}
mod = MainSpecs::DATA[:mod] = Module.new do
refine(cls) do
def foo; 'quux'; end
end
end
x = MainSpecs::DATA[:x] = Object.new
eval <<-EOS, TOPLEVEL_BINDING
using MainSpecs::DATA[:mod]
x = MainSpecs::DATA[:x]
def x.call_foo(obj)
obj.foo
end
def x.call_bar(obj)
obj.bar
end
EOS
x.call_foo(cls.new).should == 'quux'
mod.module_eval do
refine(cls2) do
def bar; 'quux'; end
end
end
x.call_bar(cls2.new).should == 'bar'
end
end end
end end

View file

@ -400,52 +400,51 @@ describe "Module#autoload" do
ModuleSpecs::Autoload.send(:remove_const, :Concur) ModuleSpecs::Autoload.send(:remove_const, :Concur)
end end
ruby_bug "#10892", ""..."2.3" do # https://bugs.ruby-lang.org/issues/10892
it "blocks others threads while doing an autoload" do it "blocks others threads while doing an autoload" do
file_path = fixture(__FILE__, "repeated_concurrent_autoload.rb") file_path = fixture(__FILE__, "repeated_concurrent_autoload.rb")
autoload_path = file_path.sub(/\.rb\Z/, '') autoload_path = file_path.sub(/\.rb\Z/, '')
mod_count = 30 mod_count = 30
thread_count = 16 thread_count = 16
mod_names = [] mod_names = []
mod_count.times do |i| mod_count.times do |i|
mod_name = :"Mod#{i}" mod_name = :"Mod#{i}"
Object.autoload mod_name, autoload_path Object.autoload mod_name, autoload_path
mod_names << mod_name mod_names << mod_name
end end
barrier = ModuleSpecs::CyclicBarrier.new thread_count barrier = ModuleSpecs::CyclicBarrier.new thread_count
ScratchPad.record ModuleSpecs::ThreadSafeCounter.new ScratchPad.record ModuleSpecs::ThreadSafeCounter.new
threads = (1..thread_count).map do threads = (1..thread_count).map do
Thread.new do Thread.new do
mod_names.each do |mod_name| mod_names.each do |mod_name|
break false unless barrier.enabled? break false unless barrier.enabled?
was_last_one_in = barrier.await # wait for all threads to finish the iteration was_last_one_in = barrier.await # wait for all threads to finish the iteration
# clean up so we can autoload the same file again # clean up so we can autoload the same file again
$LOADED_FEATURES.delete(file_path) if was_last_one_in && $LOADED_FEATURES.include?(file_path) $LOADED_FEATURES.delete(file_path) if was_last_one_in && $LOADED_FEATURES.include?(file_path)
barrier.await # get ready for race barrier.await # get ready for race
begin begin
Object.const_get(mod_name).foo Object.const_get(mod_name).foo
rescue NoMethodError rescue NoMethodError
barrier.disable! barrier.disable!
break false break false
end
end end
end end
end end
end
# check that no thread got a NoMethodError because of partially loaded module # check that no thread got a NoMethodError because of partially loaded module
threads.all? {|t| t.value}.should be_true threads.all? {|t| t.value}.should be_true
# check that the autoloaded file was evaled exactly once # check that the autoloaded file was evaled exactly once
ScratchPad.recorded.get.should == mod_count ScratchPad.recorded.get.should == mod_count
mod_names.each do |mod_name| mod_names.each do |mod_name|
Object.send(:remove_const, mod_name) Object.send(:remove_const, mod_name)
end
end end
end end

View file

@ -222,19 +222,17 @@ describe "Module#define_method" do
}.should raise_error(ArgumentError) }.should raise_error(ArgumentError)
end end
ruby_version_is "2.3" do it "does not use the caller block when no block is given" do
it "does not use the caller block when no block is given" do o = Object.new
o = Object.new def o.define(name)
def o.define(name) self.class.class_eval do
self.class.class_eval do define_method(name)
define_method(name)
end
end end
lambda {
o.define(:foo) { raise "not used" }
}.should raise_error(ArgumentError)
end end
lambda {
o.define(:foo) { raise "not used" }
}.should raise_error(ArgumentError)
end end
it "does not change the arity check style of the original proc" do it "does not change the arity check style of the original proc" do

View file

@ -1,52 +1,50 @@
require_relative '../../spec_helper' require_relative '../../spec_helper'
ruby_version_is "2.3" do describe "Module#deprecate_constant" do
describe "Module#deprecate_constant" do before :each do
before :each do @module = Module.new
@module = Module.new @value = :value
@value = :value @module::PUBLIC1 = @value
@module::PUBLIC1 = @value @module::PUBLIC2 = @value
@module::PUBLIC2 = @value @module::PRIVATE = @value
@module::PRIVATE = @value @module.private_constant :PRIVATE
@module.private_constant :PRIVATE @module.deprecate_constant :PRIVATE
@module.deprecate_constant :PRIVATE @pattern = /deprecated/
@pattern = /deprecated/ end
describe "when accessing the deprecated module" do
it "passes the accessing" do
@module.deprecate_constant :PUBLIC1
value = nil
lambda {
value = @module::PUBLIC1
}.should complain(@pattern)
value.should equal(@value)
lambda { @module::PRIVATE }.should raise_error(NameError)
end end
describe "when accessing the deprecated module" do it "warns with a message" do
it "passes the accessing" do @module.deprecate_constant :PUBLIC1
@module.deprecate_constant :PUBLIC1
value = nil
lambda {
value = @module::PUBLIC1
}.should complain(@pattern)
value.should equal(@value)
lambda { @module::PRIVATE }.should raise_error(NameError)
end
it "warns with a message" do
@module.deprecate_constant :PUBLIC1
lambda { @module::PUBLIC1 }.should complain(@pattern)
lambda { @module.const_get :PRIVATE }.should complain(@pattern)
end
end
it "accepts multiple symbols and strings as constant names" do
@module.deprecate_constant "PUBLIC1", :PUBLIC2
lambda { @module::PUBLIC1 }.should complain(@pattern) lambda { @module::PUBLIC1 }.should complain(@pattern)
lambda { @module::PUBLIC2 }.should complain(@pattern) lambda { @module.const_get :PRIVATE }.should complain(@pattern)
end
it "returns self" do
@module.deprecate_constant(:PUBLIC1).should equal(@module)
end
it "raises a NameError when given an undefined name" do
lambda { @module.deprecate_constant :UNDEFINED }.should raise_error(NameError)
end end
end end
it "accepts multiple symbols and strings as constant names" do
@module.deprecate_constant "PUBLIC1", :PUBLIC2
lambda { @module::PUBLIC1 }.should complain(@pattern)
lambda { @module::PUBLIC2 }.should complain(@pattern)
end
it "returns self" do
@module.deprecate_constant(:PUBLIC1).should equal(@module)
end
it "raises a NameError when given an undefined name" do
lambda { @module.deprecate_constant :UNDEFINED }.should raise_error(NameError)
end
end end

View file

@ -110,12 +110,10 @@ describe "Module#prepend" do
c.instance_method(:alias).owner.should == c c.instance_method(:alias).owner.should == c
end end
ruby_version_is "2.3" do it "reports the class for the owner of a method aliased from the prepended module" do
it "reports the class for the owner of a method aliased from the prepended module" do m = Module.new { def meth; :m end }
m = Module.new { def meth; :m end } c = Class.new { prepend(m); alias_method :alias, :meth }
c = Class.new { prepend(m); alias_method :alias, :meth } c.instance_method(:alias).owner.should == c
c.instance_method(:alias).owner.should == c
end
end end
it "sees an instance of a prepended class as kind of the prepended module" do it "sees an instance of a prepended class as kind of the prepended module" do

View file

@ -52,46 +52,44 @@ describe "Module#private" do
end.should raise_error(NameError) end.should raise_error(NameError)
end end
ruby_version_is "2.3" do ruby_bug "#14604", ""..."2.5.1" do
ruby_bug "#14604", "2.3"..."2.5.1" do it "only makes the method private in the class it is called on" do
it "only makes the method private in the class it is called on" do base = Class.new do
base = Class.new do def wrapped
def wrapped 1
1
end
end end
klass = Class.new(base) do
def wrapped
super + 1
end
private :wrapped
end
base.new.wrapped.should == 1
lambda do
klass.new.wrapped
end.should raise_error(NameError)
end end
it "continues to allow a prepended module method to call super" do klass = Class.new(base) do
wrapper = Module.new do def wrapped
def wrapped super + 1
super + 1
end
end end
private :wrapped
klass = Class.new do
prepend wrapper
def wrapped
1
end
private :wrapped
end
klass.new.wrapped.should == 2
end end
base.new.wrapped.should == 1
lambda do
klass.new.wrapped
end.should raise_error(NameError)
end
it "continues to allow a prepended module method to call super" do
wrapper = Module.new do
def wrapped
super + 1
end
end
klass = Class.new do
prepend wrapper
def wrapped
1
end
private :wrapped
end
klass.new.wrapped.should == 2
end end
end end
end end

View file

@ -1,43 +1,41 @@
require_relative '../../spec_helper' require_relative '../../spec_helper'
require_relative 'fixtures/classes' require_relative 'fixtures/classes'
ruby_version_is "2.3" do describe "Numeric#negative?" do
describe "Numeric#negative?" do describe "on positive numbers" do
describe "on positive numbers" do it "returns false" do
it "returns false" do 1.negative?.should be_false
1.negative?.should be_false 0.1.negative?.should be_false
0.1.negative?.should be_false
end
end
describe "on zero" do
it "returns false" do
0.negative?.should be_false
0.0.negative?.should be_false
end
end
describe "on negative numbers" do
it "returns true" do
-1.negative?.should be_true
-0.1.negative?.should be_true
end
end end
end end
describe "Numeric#negative?" do describe "on zero" do
before(:each) do it "returns false" do
@obj = NumericSpecs::Subclass.new 0.negative?.should be_false
0.0.negative?.should be_false
end end
end
it "returns true if self is less than 0" do describe "on negative numbers" do
@obj.should_receive(:<).with(0).and_return(true) it "returns true" do
@obj.negative?.should == true -1.negative?.should be_true
end -0.1.negative?.should be_true
it "returns false if self is greater than 0" do
@obj.should_receive(:<).with(0).and_return(false)
@obj.negative?.should == false
end end
end end
end end
describe "Numeric#negative?" do
before(:each) do
@obj = NumericSpecs::Subclass.new
end
it "returns true if self is less than 0" do
@obj.should_receive(:<).with(0).and_return(true)
@obj.negative?.should == true
end
it "returns false if self is greater than 0" do
@obj.should_receive(:<).with(0).and_return(false)
@obj.negative?.should == false
end
end

View file

@ -1,43 +1,41 @@
require_relative '../../spec_helper' require_relative '../../spec_helper'
require_relative 'fixtures/classes' require_relative 'fixtures/classes'
ruby_version_is "2.3" do describe "Numeric#positive?" do
describe "Numeric#positive?" do describe "on positive numbers" do
describe "on positive numbers" do it "returns true" do
it "returns true" do 1.positive?.should be_true
1.positive?.should be_true 0.1.positive?.should be_true
0.1.positive?.should be_true
end
end
describe "on zero" do
it "returns false" do
0.positive?.should be_false
0.0.positive?.should be_false
end
end
describe "on negative numbers" do
it "returns false" do
-1.positive?.should be_false
-0.1.positive?.should be_false
end
end end
end end
describe "Numeric#positive?" do describe "on zero" do
before(:each) do it "returns false" do
@obj = NumericSpecs::Subclass.new 0.positive?.should be_false
0.0.positive?.should be_false
end end
end
it "returns true if self is greater than 0" do describe "on negative numbers" do
@obj.should_receive(:>).with(0).and_return(true) it "returns false" do
@obj.positive?.should == true -1.positive?.should be_false
end -0.1.positive?.should be_false
it "returns false if self is less than 0" do
@obj.should_receive(:>).with(0).and_return(false)
@obj.positive?.should == false
end end
end end
end end
describe "Numeric#positive?" do
before(:each) do
@obj = NumericSpecs::Subclass.new
end
it "returns true if self is greater than 0" do
@obj.should_receive(:>).with(0).and_return(true)
@obj.positive?.should == true
end
it "returns false if self is less than 0" do
@obj.should_receive(:>).with(0).and_return(false)
@obj.positive?.should == false
end
end

View file

@ -184,18 +184,9 @@ describe "ObjectSpace.each_object" do
hidden.should == nil hidden.should == nil
end end
ruby_version_is ""..."2.3" do it "walks singleton classes" do
it "does not walk singleton classes" do @sclass.should be_kind_of(@meta)
@sclass.should be_kind_of(@meta) ObjectSpace.each_object(@meta).to_a.should include(@sclass)
ObjectSpace.each_object(@meta).to_a.should_not include(@sclass)
end
end
ruby_version_is "2.3" do
it "walks singleton classes" do
@sclass.should be_kind_of(@meta)
ObjectSpace.each_object(@meta).to_a.should include(@sclass)
end
end end
end end
@ -211,10 +202,8 @@ describe "ObjectSpace.each_object" do
expected = [ a, b, c, d ] expected = [ a, b, c, d ]
# singleton classes should be walked only on >= 2.3 # singleton classes should be walked only on >= 2.3
ruby_version_is "2.3" do expected << c_sclass
expected << c_sclass c_sclass.should be_kind_of(a.singleton_class)
c_sclass.should be_kind_of(a.singleton_class)
end
b.extend Enumerable # included modules should not be walked b.extend Enumerable # included modules should not be walked

View file

@ -1,7 +1,6 @@
require_relative '../../../spec_helper' require_relative '../../../spec_helper'
describe "Process::Status#exitstatus" do describe "Process::Status#exitstatus" do
before :each do before :each do
ruby_exe("exit(42)") ruby_exe("exit(42)")
end end
@ -10,4 +9,17 @@ describe "Process::Status#exitstatus" do
$?.exitstatus.should == 42 $?.exitstatus.should == 42
end end
describe "for a child that raised SignalException" do
before :each do
ruby_exe("raise SignalException, 'SIGTERM'")
end
platform_is_not :windows do
# The exitstatus is not set in these cases. See the termsig_spec
# for info on where the signal number (SIGTERM) is available.
it "returns nil" do
$?.exitstatus.should == nil
end
end
end
end end

View file

@ -13,6 +13,18 @@ describe "Process::Status#termsig" do
end end
end end
describe "for a child that raised SignalException" do
before :each do
ruby_exe("raise SignalException, 'SIGTERM'")
end
platform_is_not :windows do
it "returns the signal" do
$?.termsig.should == Signal.list["TERM"]
end
end
end
describe "for a child that was sent a signal" do describe "for a child that was sent a signal" do
before :each do before :each do

View file

@ -2,7 +2,7 @@
require_relative '../../spec_helper' require_relative '../../spec_helper'
require_relative 'shared/urandom' require_relative 'shared/urandom'
ruby_version_is "2.3"..."2.5" do ruby_version_is ""..."2.5" do
describe "Random.raw_seed" do describe "Random.raw_seed" do
it_behaves_like :random_urandom, :raw_seed it_behaves_like :random_urandom, :raw_seed
end end

View file

@ -5,16 +5,8 @@ describe "Signal.signame" do
Signal.signame(0).should == "EXIT" Signal.signame(0).should == "EXIT"
end end
ruby_version_is "2.0"..."2.3" do it "returns nil if the argument is an invalid signal number" do
it "raises an ArgumentError if the argument is an invalid signal number" do Signal.signame(-1).should == nil
lambda { Signal.signame(-1) }.should raise_error(ArgumentError)
end
end
ruby_version_is "2.3" do
it "returns nil if the argument is an invalid signal number" do
Signal.signame(-1).should == nil
end
end end
it "raises a TypeError when the passed argument can't be coerced to Integer" do it "raises a TypeError when the passed argument can't be coerced to Integer" do

View file

@ -36,10 +36,8 @@ describe "String#crypt" do
lambda { "hello".crypt("a\x00") }.should raise_error(ArgumentError) lambda { "hello".crypt("a\x00") }.should raise_error(ArgumentError)
end end
ruby_version_is "2.3" do it "raises an ArgumentError when the string contains NUL character" do
it "raises an ArgumentError when the string contains NUL character" do lambda { "poison\0null".crypt("aa") }.should raise_error(ArgumentError)
lambda { "poison\0null".crypt("aa") }.should raise_error(ArgumentError)
end
end end
it "calls #to_str to converts the salt arg to a String" do it "calls #to_str to converts the salt arg to a String" do

View file

@ -7,12 +7,10 @@ describe "String.new" do
str.should be_an_instance_of(String) str.should be_an_instance_of(String)
end end
ruby_version_is "2.3" do it "accepts an encoding argument" do
it "accepts an encoding argument" do xA4xA2 = [0xA4, 0xA2].pack('CC').force_encoding 'utf-8'
xA4xA2 = [0xA4, 0xA2].pack('CC').force_encoding 'utf-8' str = String.new(xA4xA2, encoding: 'euc-jp')
str = String.new(xA4xA2, encoding: 'euc-jp') str.encoding.should == Encoding::EUC_JP
str.encoding.should == Encoding::EUC_JP
end
end end
ruby_version_is "2.4" do ruby_version_is "2.4" do

View file

@ -51,9 +51,8 @@ describe :string_each_line, shared: true do
end end
end end
quarantine! do # Currently fails on Travis
ruby_version_is '2.5' do ruby_version_is '2.5' do
it "yields paragraphs (broken by 2 or more successive newlines) when passed ''" do it "yields paragraphs (broken by 2 or more successive newlines) when passed '' and replaces multiple newlines with only two ones" do
a = [] a = []
"hello\nworld\n\n\nand\nuniverse\n\n\n\n\n".send(@method, '') { |s| a << s } "hello\nworld\n\n\nand\nuniverse\n\n\n\n\n".send(@method, '') { |s| a << s }
a.should == ["hello\nworld\n\n", "and\nuniverse\n\n"] a.should == ["hello\nworld\n\n", "and\nuniverse\n\n"]
@ -63,7 +62,6 @@ quarantine! do # Currently fails on Travis
a.should == ["hello\nworld\n\n", "and\nuniverse\n\n", "dog"] a.should == ["hello\nworld\n\n", "and\nuniverse\n\n", "dog"]
end end
end end
end
describe "uses $/" do describe "uses $/" do
before :each do before :each do
@ -136,7 +134,7 @@ end
ruby_version_is '2.4' do ruby_version_is '2.4' do
context "when `chomp` keyword argument is passed" do context "when `chomp` keyword argument is passed" do
it "removes new line characters" do it "removes new line characters when separator is not specified" do
a = [] a = []
"hello \nworld\n".send(@method, chomp: true) { |s| a << s } "hello \nworld\n".send(@method, chomp: true) { |s| a << s }
a.should == ["hello ", "world"] a.should == ["hello ", "world"]
@ -145,6 +143,23 @@ end
"hello \r\nworld\r\n".send(@method, chomp: true) { |s| a << s } "hello \r\nworld\r\n".send(@method, chomp: true) { |s| a << s }
a.should == ["hello ", "world"] a.should == ["hello ", "world"]
end end
it "removes only specified separator" do
a = []
"hello world".send(@method, ' ', chomp: true) { |s| a << s }
a.should == ["hello", "world"]
end
# https://bugs.ruby-lang.org/issues/14257
it "ignores new line characters when separator is specified" do
a = []
"hello\n world\n".send(@method, ' ', chomp: true) { |s| a << s }
a.should == ["hello\n", "world\n"]
a = []
"hello\r\n world\r\n".send(@method, ' ', chomp: true) { |s| a << s }
a.should == ["hello\r\n", "world\r\n"]
end
end end
end end
end end

View file

@ -1,46 +1,44 @@
require_relative '../../spec_helper' require_relative '../../spec_helper'
ruby_version_is "2.3" do describe 'String#-@' do
describe 'String#-@' do it 'returns self if the String is frozen' do
it 'returns self if the String is frozen' do input = 'foo'.freeze
input = 'foo'.freeze output = -input
output = -input
output.equal?(input).should == true output.equal?(input).should == true
output.frozen?.should == true output.frozen?.should == true
end
it 'returns a frozen copy if the String is not frozen' do
input = 'foo'
output = -input
output.frozen?.should == true
output.should == 'foo'
end
ruby_version_is "2.5" do
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 end
it 'returns a frozen copy if the String is not frozen' do it "returns the same object when it's called on the same String literal" do
input = 'foo' (-"unfrozen string").should equal(-"unfrozen string")
output = -input (-"unfrozen string").should_not equal(-"another unfrozen string")
output.frozen?.should == true
output.should == 'foo'
end end
ruby_version_is "2.5" do it "is an identity function if the string is frozen" do
it "returns the same object for equal unfrozen strings" do dynamic = %w(this string is frozen).join(' ').freeze
origin = "this is a string"
dynamic = %w(this is a string).join(' ')
origin.should_not equal(dynamic) (-dynamic).should equal(dynamic)
(-origin).should equal(-dynamic)
end
it "returns the same object when it's called on the same String literal" do dynamic.should_not equal("this string is frozen".freeze)
(-"unfrozen string").should equal(-"unfrozen string") (-dynamic).should_not equal("this string is frozen".freeze)
(-"unfrozen string").should_not equal(-"another unfrozen string") (-dynamic).should_not equal(-"this string is frozen".freeze)
end
it "is an identity function if the string is frozen" do
dynamic = %w(this string is frozen).join(' ').freeze
(-dynamic).should equal(dynamic)
dynamic.should_not equal("this string is frozen".freeze)
(-dynamic).should_not equal("this string is frozen".freeze)
(-dynamic).should_not equal(-"this string is frozen".freeze)
end
end end
end end
end end

View file

@ -3,272 +3,270 @@ require_relative '../fixtures/classes'
require_relative 'shared/basic' require_relative 'shared/basic'
require_relative 'shared/integer' require_relative 'shared/integer'
ruby_version_is '2.3' do platform_is pointer_size: 64 do
platform_is pointer_size: 64 do little_endian do
little_endian do
describe "String#unpack with format 'J'" do
describe "with modifier '_'" do
it_behaves_like :string_unpack_64bit_le, 'J_'
it_behaves_like :string_unpack_64bit_le_unsigned, 'J_'
end
describe "with modifier '!'" do
it_behaves_like :string_unpack_64bit_le, 'J!'
it_behaves_like :string_unpack_64bit_le_unsigned, 'J!'
end
end
describe "String#unpack with format 'j'" do
describe "with modifier '_'" do
it_behaves_like :string_unpack_64bit_le, 'j_'
it_behaves_like :string_unpack_64bit_le_signed, 'j_'
end
describe "with modifier '!'" do
it_behaves_like :string_unpack_64bit_le, 'j!'
it_behaves_like :string_unpack_64bit_le_signed, 'j!'
end
end
end
big_endian do
describe "String#unpack with format 'J'" do
describe "with modifier '_'" do
it_behaves_like :string_unpack_64bit_be, 'J_'
it_behaves_like :string_unpack_64bit_be_unsigned, 'J_'
end
describe "with modifier '!'" do
it_behaves_like :string_unpack_64bit_be, 'J!'
it_behaves_like :string_unpack_64bit_be_unsigned, 'J!'
end
end
describe "String#unpack with format 'j'" do
describe "with modifier '_'" do
it_behaves_like :string_unpack_64bit_be, 'j_'
it_behaves_like :string_unpack_64bit_be_signed, 'j_'
end
describe "with modifier '!'" do
it_behaves_like :string_unpack_64bit_be, 'j!'
it_behaves_like :string_unpack_64bit_be_signed, 'j!'
end
end
end
describe "String#unpack with format 'J'" do describe "String#unpack with format 'J'" do
describe "with modifier '<'" do describe "with modifier '_'" do
it_behaves_like :string_unpack_64bit_le, 'J<' it_behaves_like :string_unpack_64bit_le, 'J_'
it_behaves_like :string_unpack_64bit_le_unsigned, 'J<' it_behaves_like :string_unpack_64bit_le_unsigned, 'J_'
end end
describe "with modifier '>'" do describe "with modifier '!'" do
it_behaves_like :string_unpack_64bit_be, 'J>' it_behaves_like :string_unpack_64bit_le, 'J!'
it_behaves_like :string_unpack_64bit_be_unsigned, 'J>' it_behaves_like :string_unpack_64bit_le_unsigned, 'J!'
end
describe "with modifier '<' and '_'" do
it_behaves_like :string_unpack_64bit_le, 'J<_'
it_behaves_like :string_unpack_64bit_le, 'J_<'
it_behaves_like :string_unpack_64bit_le_unsigned, 'J<_'
it_behaves_like :string_unpack_64bit_le_unsigned, 'J_<'
end
describe "with modifier '<' and '!'" do
it_behaves_like :string_unpack_64bit_le, 'J<!'
it_behaves_like :string_unpack_64bit_le, 'J!<'
it_behaves_like :string_unpack_64bit_le_unsigned, 'J<!'
it_behaves_like :string_unpack_64bit_le_unsigned, 'J!<'
end
describe "with modifier '>' and '_'" do
it_behaves_like :string_unpack_64bit_be, 'J>_'
it_behaves_like :string_unpack_64bit_be, 'J_>'
it_behaves_like :string_unpack_64bit_be_unsigned, 'J>_'
it_behaves_like :string_unpack_64bit_be_unsigned, 'J_>'
end
describe "with modifier '>' and '!'" do
it_behaves_like :string_unpack_64bit_be, 'J>!'
it_behaves_like :string_unpack_64bit_be, 'J!>'
it_behaves_like :string_unpack_64bit_be_unsigned, 'J>!'
it_behaves_like :string_unpack_64bit_be_unsigned, 'J!>'
end end
end end
describe "String#unpack with format 'j'" do describe "String#unpack with format 'j'" do
describe "with modifier '<'" do describe "with modifier '_'" do
it_behaves_like :string_unpack_64bit_le, 'j<' it_behaves_like :string_unpack_64bit_le, 'j_'
it_behaves_like :string_unpack_64bit_le_signed, 'j<' it_behaves_like :string_unpack_64bit_le_signed, 'j_'
end end
describe "with modifier '>'" do describe "with modifier '!'" do
it_behaves_like :string_unpack_64bit_be, 'j>' it_behaves_like :string_unpack_64bit_le, 'j!'
it_behaves_like :string_unpack_64bit_be_signed, 'j>' it_behaves_like :string_unpack_64bit_le_signed, 'j!'
end
describe "with modifier '<' and '_'" do
it_behaves_like :string_unpack_64bit_le, 'j<_'
it_behaves_like :string_unpack_64bit_le, 'j_<'
it_behaves_like :string_unpack_64bit_le_signed, 'j<_'
it_behaves_like :string_unpack_64bit_le_signed, 'j_<'
end
describe "with modifier '<' and '!'" do
it_behaves_like :string_unpack_64bit_le, 'j<!'
it_behaves_like :string_unpack_64bit_le, 'j!<'
it_behaves_like :string_unpack_64bit_le_signed, 'j<!'
it_behaves_like :string_unpack_64bit_le_signed, 'j!<'
end
describe "with modifier '>' and '_'" do
it_behaves_like :string_unpack_64bit_be, 'j>_'
it_behaves_like :string_unpack_64bit_be, 'j_>'
it_behaves_like :string_unpack_64bit_be_signed, 'j>_'
it_behaves_like :string_unpack_64bit_be_signed, 'j_>'
end
describe "with modifier '>' and '!'" do
it_behaves_like :string_unpack_64bit_be, 'j>!'
it_behaves_like :string_unpack_64bit_be, 'j!>'
it_behaves_like :string_unpack_64bit_be_signed, 'j>!'
it_behaves_like :string_unpack_64bit_be_signed, 'j!>'
end end
end end
end end
platform_is pointer_size: 32 do big_endian do
little_endian do
describe "String#unpack with format 'J'" do
describe "with modifier '_'" do
it_behaves_like :string_unpack_32bit_le, 'J_'
it_behaves_like :string_unpack_32bit_le_unsigned, 'J_'
end
describe "with modifier '!'" do
it_behaves_like :string_unpack_32bit_le, 'J!'
it_behaves_like :string_unpack_32bit_le_unsigned, 'J!'
end
end
describe "String#unpack with format 'j'" do
describe "with modifier '_'" do
it_behaves_like :string_unpack_32bit_le, 'j_'
it_behaves_like :string_unpack_32bit_le_signed, 'j_'
end
describe "with modifier '!'" do
it_behaves_like :string_unpack_32bit_le, 'j!'
it_behaves_like :string_unpack_32bit_le_signed, 'j!'
end
end
end
big_endian do
describe "String#unpack with format 'J'" do
describe "with modifier '_'" do
it_behaves_like :string_unpack_32bit_be, 'J_'
it_behaves_like :string_unpack_32bit_be_unsigned, 'J_'
end
describe "with modifier '!'" do
it_behaves_like :string_unpack_32bit_be, 'J!'
it_behaves_like :string_unpack_32bit_be_unsigned, 'J!'
end
end
describe "String#unpack with format 'j'" do
describe "with modifier '_'" do
it_behaves_like :string_unpack_32bit_be, 'j_'
it_behaves_like :string_unpack_32bit_be_signed, 'j_'
end
describe "with modifier '!'" do
it_behaves_like :string_unpack_32bit_be, 'j!'
it_behaves_like :string_unpack_32bit_be_signed, 'j!'
end
end
end
describe "String#unpack with format 'J'" do describe "String#unpack with format 'J'" do
describe "with modifier '<'" do describe "with modifier '_'" do
it_behaves_like :string_unpack_32bit_le, 'J<' it_behaves_like :string_unpack_64bit_be, 'J_'
it_behaves_like :string_unpack_32bit_le_unsigned, 'J<' it_behaves_like :string_unpack_64bit_be_unsigned, 'J_'
end end
describe "with modifier '>'" do describe "with modifier '!'" do
it_behaves_like :string_unpack_32bit_be, 'J>' it_behaves_like :string_unpack_64bit_be, 'J!'
it_behaves_like :string_unpack_32bit_be_unsigned, 'J>' it_behaves_like :string_unpack_64bit_be_unsigned, 'J!'
end
describe "with modifier '<' and '_'" do
it_behaves_like :string_unpack_32bit_le, 'J<_'
it_behaves_like :string_unpack_32bit_le, 'J_<'
it_behaves_like :string_unpack_32bit_le_unsigned, 'J<_'
it_behaves_like :string_unpack_32bit_le_unsigned, 'J_<'
end
describe "with modifier '<' and '!'" do
it_behaves_like :string_unpack_32bit_le, 'J<!'
it_behaves_like :string_unpack_32bit_le, 'J!<'
it_behaves_like :string_unpack_32bit_le_unsigned, 'J<!'
it_behaves_like :string_unpack_32bit_le_unsigned, 'J!<'
end
describe "with modifier '>' and '_'" do
it_behaves_like :string_unpack_32bit_be, 'J>_'
it_behaves_like :string_unpack_32bit_be, 'J_>'
it_behaves_like :string_unpack_32bit_be_unsigned, 'J>_'
it_behaves_like :string_unpack_32bit_be_unsigned, 'J_>'
end
describe "with modifier '>' and '!'" do
it_behaves_like :string_unpack_32bit_be, 'J>!'
it_behaves_like :string_unpack_32bit_be, 'J!>'
it_behaves_like :string_unpack_32bit_be_unsigned, 'J>!'
it_behaves_like :string_unpack_32bit_be_unsigned, 'J!>'
end end
end end
describe "String#unpack with format 'j'" do describe "String#unpack with format 'j'" do
describe "with modifier '<'" do describe "with modifier '_'" do
it_behaves_like :string_unpack_32bit_le, 'j<' it_behaves_like :string_unpack_64bit_be, 'j_'
it_behaves_like :string_unpack_32bit_le_signed, 'j<' it_behaves_like :string_unpack_64bit_be_signed, 'j_'
end end
describe "with modifier '>'" do describe "with modifier '!'" do
it_behaves_like :string_unpack_32bit_be, 'j>' it_behaves_like :string_unpack_64bit_be, 'j!'
it_behaves_like :string_unpack_32bit_be_signed, 'j>' it_behaves_like :string_unpack_64bit_be_signed, 'j!'
end end
end
end
describe "with modifier '<' and '_'" do describe "String#unpack with format 'J'" do
it_behaves_like :string_unpack_32bit_le, 'j<_' describe "with modifier '<'" do
it_behaves_like :string_unpack_32bit_le, 'j_<' it_behaves_like :string_unpack_64bit_le, 'J<'
it_behaves_like :string_unpack_32bit_le_signed, 'j<_' it_behaves_like :string_unpack_64bit_le_unsigned, 'J<'
it_behaves_like :string_unpack_32bit_le_signed, 'j_<' end
end
describe "with modifier '<' and '!'" do describe "with modifier '>'" do
it_behaves_like :string_unpack_32bit_le, 'j<!' it_behaves_like :string_unpack_64bit_be, 'J>'
it_behaves_like :string_unpack_32bit_le, 'j!<' it_behaves_like :string_unpack_64bit_be_unsigned, 'J>'
it_behaves_like :string_unpack_32bit_le_signed, 'j<!' end
it_behaves_like :string_unpack_32bit_le_signed, 'j!<'
end
describe "with modifier '>' and '_'" do describe "with modifier '<' and '_'" do
it_behaves_like :string_unpack_32bit_be, 'j>_' it_behaves_like :string_unpack_64bit_le, 'J<_'
it_behaves_like :string_unpack_32bit_be, 'j_>' it_behaves_like :string_unpack_64bit_le, 'J_<'
it_behaves_like :string_unpack_32bit_be_signed, 'j>_' it_behaves_like :string_unpack_64bit_le_unsigned, 'J<_'
it_behaves_like :string_unpack_32bit_be_signed, 'j_>' it_behaves_like :string_unpack_64bit_le_unsigned, 'J_<'
end end
describe "with modifier '>' and '!'" do describe "with modifier '<' and '!'" do
it_behaves_like :string_unpack_32bit_be, 'j>!' it_behaves_like :string_unpack_64bit_le, 'J<!'
it_behaves_like :string_unpack_32bit_be, 'j!>' it_behaves_like :string_unpack_64bit_le, 'J!<'
it_behaves_like :string_unpack_32bit_be_signed, 'j>!' it_behaves_like :string_unpack_64bit_le_unsigned, 'J<!'
it_behaves_like :string_unpack_32bit_be_signed, 'j!>' it_behaves_like :string_unpack_64bit_le_unsigned, 'J!<'
end end
describe "with modifier '>' and '_'" do
it_behaves_like :string_unpack_64bit_be, 'J>_'
it_behaves_like :string_unpack_64bit_be, 'J_>'
it_behaves_like :string_unpack_64bit_be_unsigned, 'J>_'
it_behaves_like :string_unpack_64bit_be_unsigned, 'J_>'
end
describe "with modifier '>' and '!'" do
it_behaves_like :string_unpack_64bit_be, 'J>!'
it_behaves_like :string_unpack_64bit_be, 'J!>'
it_behaves_like :string_unpack_64bit_be_unsigned, 'J>!'
it_behaves_like :string_unpack_64bit_be_unsigned, 'J!>'
end
end
describe "String#unpack with format 'j'" do
describe "with modifier '<'" do
it_behaves_like :string_unpack_64bit_le, 'j<'
it_behaves_like :string_unpack_64bit_le_signed, 'j<'
end
describe "with modifier '>'" do
it_behaves_like :string_unpack_64bit_be, 'j>'
it_behaves_like :string_unpack_64bit_be_signed, 'j>'
end
describe "with modifier '<' and '_'" do
it_behaves_like :string_unpack_64bit_le, 'j<_'
it_behaves_like :string_unpack_64bit_le, 'j_<'
it_behaves_like :string_unpack_64bit_le_signed, 'j<_'
it_behaves_like :string_unpack_64bit_le_signed, 'j_<'
end
describe "with modifier '<' and '!'" do
it_behaves_like :string_unpack_64bit_le, 'j<!'
it_behaves_like :string_unpack_64bit_le, 'j!<'
it_behaves_like :string_unpack_64bit_le_signed, 'j<!'
it_behaves_like :string_unpack_64bit_le_signed, 'j!<'
end
describe "with modifier '>' and '_'" do
it_behaves_like :string_unpack_64bit_be, 'j>_'
it_behaves_like :string_unpack_64bit_be, 'j_>'
it_behaves_like :string_unpack_64bit_be_signed, 'j>_'
it_behaves_like :string_unpack_64bit_be_signed, 'j_>'
end
describe "with modifier '>' and '!'" do
it_behaves_like :string_unpack_64bit_be, 'j>!'
it_behaves_like :string_unpack_64bit_be, 'j!>'
it_behaves_like :string_unpack_64bit_be_signed, 'j>!'
it_behaves_like :string_unpack_64bit_be_signed, 'j!>'
end
end
end
platform_is pointer_size: 32 do
little_endian do
describe "String#unpack with format 'J'" do
describe "with modifier '_'" do
it_behaves_like :string_unpack_32bit_le, 'J_'
it_behaves_like :string_unpack_32bit_le_unsigned, 'J_'
end
describe "with modifier '!'" do
it_behaves_like :string_unpack_32bit_le, 'J!'
it_behaves_like :string_unpack_32bit_le_unsigned, 'J!'
end
end
describe "String#unpack with format 'j'" do
describe "with modifier '_'" do
it_behaves_like :string_unpack_32bit_le, 'j_'
it_behaves_like :string_unpack_32bit_le_signed, 'j_'
end
describe "with modifier '!'" do
it_behaves_like :string_unpack_32bit_le, 'j!'
it_behaves_like :string_unpack_32bit_le_signed, 'j!'
end
end
end
big_endian do
describe "String#unpack with format 'J'" do
describe "with modifier '_'" do
it_behaves_like :string_unpack_32bit_be, 'J_'
it_behaves_like :string_unpack_32bit_be_unsigned, 'J_'
end
describe "with modifier '!'" do
it_behaves_like :string_unpack_32bit_be, 'J!'
it_behaves_like :string_unpack_32bit_be_unsigned, 'J!'
end
end
describe "String#unpack with format 'j'" do
describe "with modifier '_'" do
it_behaves_like :string_unpack_32bit_be, 'j_'
it_behaves_like :string_unpack_32bit_be_signed, 'j_'
end
describe "with modifier '!'" do
it_behaves_like :string_unpack_32bit_be, 'j!'
it_behaves_like :string_unpack_32bit_be_signed, 'j!'
end
end
end
describe "String#unpack with format 'J'" do
describe "with modifier '<'" do
it_behaves_like :string_unpack_32bit_le, 'J<'
it_behaves_like :string_unpack_32bit_le_unsigned, 'J<'
end
describe "with modifier '>'" do
it_behaves_like :string_unpack_32bit_be, 'J>'
it_behaves_like :string_unpack_32bit_be_unsigned, 'J>'
end
describe "with modifier '<' and '_'" do
it_behaves_like :string_unpack_32bit_le, 'J<_'
it_behaves_like :string_unpack_32bit_le, 'J_<'
it_behaves_like :string_unpack_32bit_le_unsigned, 'J<_'
it_behaves_like :string_unpack_32bit_le_unsigned, 'J_<'
end
describe "with modifier '<' and '!'" do
it_behaves_like :string_unpack_32bit_le, 'J<!'
it_behaves_like :string_unpack_32bit_le, 'J!<'
it_behaves_like :string_unpack_32bit_le_unsigned, 'J<!'
it_behaves_like :string_unpack_32bit_le_unsigned, 'J!<'
end
describe "with modifier '>' and '_'" do
it_behaves_like :string_unpack_32bit_be, 'J>_'
it_behaves_like :string_unpack_32bit_be, 'J_>'
it_behaves_like :string_unpack_32bit_be_unsigned, 'J>_'
it_behaves_like :string_unpack_32bit_be_unsigned, 'J_>'
end
describe "with modifier '>' and '!'" do
it_behaves_like :string_unpack_32bit_be, 'J>!'
it_behaves_like :string_unpack_32bit_be, 'J!>'
it_behaves_like :string_unpack_32bit_be_unsigned, 'J>!'
it_behaves_like :string_unpack_32bit_be_unsigned, 'J!>'
end
end
describe "String#unpack with format 'j'" do
describe "with modifier '<'" do
it_behaves_like :string_unpack_32bit_le, 'j<'
it_behaves_like :string_unpack_32bit_le_signed, 'j<'
end
describe "with modifier '>'" do
it_behaves_like :string_unpack_32bit_be, 'j>'
it_behaves_like :string_unpack_32bit_be_signed, 'j>'
end
describe "with modifier '<' and '_'" do
it_behaves_like :string_unpack_32bit_le, 'j<_'
it_behaves_like :string_unpack_32bit_le, 'j_<'
it_behaves_like :string_unpack_32bit_le_signed, 'j<_'
it_behaves_like :string_unpack_32bit_le_signed, 'j_<'
end
describe "with modifier '<' and '!'" do
it_behaves_like :string_unpack_32bit_le, 'j<!'
it_behaves_like :string_unpack_32bit_le, 'j!<'
it_behaves_like :string_unpack_32bit_le_signed, 'j<!'
it_behaves_like :string_unpack_32bit_le_signed, 'j!<'
end
describe "with modifier '>' and '_'" do
it_behaves_like :string_unpack_32bit_be, 'j>_'
it_behaves_like :string_unpack_32bit_be, 'j_>'
it_behaves_like :string_unpack_32bit_be_signed, 'j>_'
it_behaves_like :string_unpack_32bit_be_signed, 'j_>'
end
describe "with modifier '>' and '!'" do
it_behaves_like :string_unpack_32bit_be, 'j>!'
it_behaves_like :string_unpack_32bit_be, 'j!>'
it_behaves_like :string_unpack_32bit_be_signed, 'j>!'
it_behaves_like :string_unpack_32bit_be_signed, 'j!>'
end end
end end
end end

View file

@ -1,24 +1,22 @@
require_relative '../../spec_helper' require_relative '../../spec_helper'
ruby_version_is "2.3" do describe 'String#+@' do
describe 'String#+@' do it 'returns an unfrozen copy of a frozen String' do
it 'returns an unfrozen copy of a frozen String' do input = 'foo'.freeze
input = 'foo'.freeze output = +input
output = +input
output.frozen?.should == false output.frozen?.should == false
output.should == 'foo' output.should == 'foo'
end end
it 'returns self if the String is not frozen' do it 'returns self if the String is not frozen' do
input = 'foo' input = 'foo'
output = +input output = +input
output.equal?(input).should == true output.equal?(input).should == true
end end
it 'returns mutable copy despite freeze-magic-comment in file' do it 'returns mutable copy despite freeze-magic-comment in file' do
ruby_exe(fixture(__FILE__, "freeze_magic_comment.rb")).should == 'mutable' ruby_exe(fixture(__FILE__, "freeze_magic_comment.rb")).should == 'mutable'
end
end end
end end

View file

@ -1,44 +1,42 @@
require_relative '../../spec_helper' require_relative '../../spec_helper'
ruby_version_is "2.3" do describe "Struct#dig" do
describe "Struct#dig" do before(:each) do
before(:each) do @klass = Struct.new(:a)
@klass = Struct.new(:a) @instance = @klass.new(@klass.new({ b: [1, 2, 3] }))
@instance = @klass.new(@klass.new({ b: [1, 2, 3] })) end
it "returns the nested value specified by the sequence of keys" do
@instance.dig(:a, :a).should == { b: [1, 2, 3] }
end
it "returns the nested value specified if the sequence includes an index" do
@instance.dig(:a, :a, :b, 0).should == 1
end
it "returns nil if any intermediate step is nil" do
@instance.dig(:b, 0).should == nil
end
it "raises a TypeError if any intermediate step does not respond to #dig" do
instance = @klass.new(1)
lambda {
instance.dig(:a, 3)
}.should raise_error(TypeError)
end
it "raises an ArgumentError if no arguments provided" do
lambda { @instance.dig }.should raise_error(ArgumentError)
end
it "calls #dig on any intermediate step with the rest of the sequence as arguments" do
obj = Object.new
instance = @klass.new(obj)
def obj.dig(*args)
{dug: args}
end end
it "returns the nested value specified by the sequence of keys" do instance.dig(:a, :bar, :baz).should == { dug: [:bar, :baz] }
@instance.dig(:a, :a).should == { b: [1, 2, 3] }
end
it "returns the nested value specified if the sequence includes an index" do
@instance.dig(:a, :a, :b, 0).should == 1
end
it "returns nil if any intermediate step is nil" do
@instance.dig(:b, 0).should == nil
end
it "raises a TypeError if any intermediate step does not respond to #dig" do
instance = @klass.new(1)
lambda {
instance.dig(:a, 3)
}.should raise_error(TypeError)
end
it "raises an ArgumentError if no arguments provided" do
lambda { @instance.dig }.should raise_error(ArgumentError)
end
it "calls #dig on any intermediate step with the rest of the sequence as arguments" do
obj = Object.new
instance = @klass.new(obj)
def obj.dig(*args)
{dug: args}
end
instance.dig(:a, :bar, :baz).should == { dug: [:bar, :baz] }
end
end end
end end

View file

@ -1,56 +1,54 @@
require_relative '../../spec_helper' require_relative '../../spec_helper'
ruby_version_is '2.3' do describe "Thread#name" do
describe "Thread#name" do before :each do
before :each do @thread = Thread.new {}
@thread = Thread.new {}
end
after :each do
@thread.join
end
it "is nil initially" do
@thread.name.should == nil
end
it "returns the thread name" do
@thread.name = "thread_name"
@thread.name.should == "thread_name"
end
end end
describe "Thread#name=" do after :each do
before :each do @thread.join
@thread = Thread.new {} end
end
after :each do it "is nil initially" do
@thread.join @thread.name.should == nil
end end
it "can be set to a String" do it "returns the thread name" do
@thread.name = "new thread name" @thread.name = "thread_name"
@thread.name.should == "new thread name" @thread.name.should == "thread_name"
end end
end
it "raises an ArgumentError if the name includes a null byte" do
lambda { describe "Thread#name=" do
@thread.name = "new thread\0name" before :each do
}.should raise_error(ArgumentError) @thread = Thread.new {}
end end
it "can be reset to nil" do after :each do
@thread.name = nil @thread.join
@thread.name.should == nil end
end
it "can be set to a String" do
it "calls #to_str to convert name to String" do @thread.name = "new thread name"
name = mock("Thread#name") @thread.name.should == "new thread name"
name.should_receive(:to_str).and_return("a thread name") end
@thread.name = name it "raises an ArgumentError if the name includes a null byte" do
@thread.name.should == "a thread name" lambda {
end @thread.name = "new thread\0name"
}.should raise_error(ArgumentError)
end
it "can be reset to nil" do
@thread.name = nil
@thread.name.should == nil
end
it "calls #to_str to convert name to String" do
name = mock("Thread#name")
name.should_receive(:to_str).and_return("a thread name")
@thread.name = name
@thread.name.should == "a thread name"
end end
end end

View file

@ -34,7 +34,7 @@ describe "Time.at" do
describe "passed BigDecimal" do describe "passed BigDecimal" do
it "doesn't round input value" do it "doesn't round input value" do
require 'bigdecimal' require 'bigdecimal'
Time.at(BigDecimal.new('1.1')).to_f.should == 1.1 Time.at(BigDecimal('1.1')).to_f.should == 1.1
end end
end end
end end

View file

@ -55,7 +55,7 @@ describe 'TracePoint#disable' do
end end
end end
ruby_bug "#14057", "2.0"..."2.5" do ruby_bug "#14057", ""..."2.5" do
it 'can accept param within a block but it should not yield arguments' do it 'can accept param within a block but it should not yield arguments' do
event_name = nil event_name = nil
trace = TracePoint.new(:line) {} trace = TracePoint.new(:line) {}

View file

@ -62,7 +62,7 @@ describe 'TracePoint#enable' do
end.enable { event_name.should equal(:line) } end.enable { event_name.should equal(:line) }
end end
ruby_bug "#14057", "2.0"..."2.5" do ruby_bug "#14057", ""..."2.5" do
it 'can accept arguments within a block but it should not yield arguments' do it 'can accept arguments within a block but it should not yield arguments' do
event_name = nil event_name = nil
trace = TracePoint.new(:line) { |tp| event_name = tp.event } trace = TracePoint.new(:line) { |tp| event_name = tp.event }

View file

@ -56,7 +56,7 @@ describe 'TracePoint.new' do
-> { TracePoint.new(o) {}}.should raise_error(TypeError) -> { TracePoint.new(o) {}}.should raise_error(TypeError)
end end
ruby_bug "#140740", "2.0"..."2.5" do ruby_bug "#140740", ""..."2.5" do
it 'expects to be called with a block' do it 'expects to be called with a block' do
-> { TracePoint.new(:line) }.should raise_error(ArgumentError) -> { TracePoint.new(:line) }.should raise_error(ArgumentError)
end end

View file

@ -62,14 +62,12 @@ describe "A block yielded a single" do
result.should == [{"a" => 1}, b: 2] result.should == [{"a" => 1}, b: 2]
end end
ruby_version_is "2.2.1" do # SEGV on MRI 2.2.0 it "calls #to_hash on the argument but does not use the result when no keywords are present" do
it "calls #to_hash on the argument but does not use the result when no keywords are present" do obj = mock("coerce block keyword arguments")
obj = mock("coerce block keyword arguments") obj.should_receive(:to_hash).and_return({"a" => 1, "b" => 2})
obj.should_receive(:to_hash).and_return({"a" => 1, "b" => 2})
result = m([obj]) { |a=nil, **b| [a, b] } result = m([obj]) { |a=nil, **b| [a, b] }
result.should == [{"a" => 1, "b" => 2}, {}] result.should == [{"a" => 1, "b" => 2}, {}]
end
end end
it "assigns non-symbol keys to non-keyword arguments" do it "assigns non-symbol keys to non-keyword arguments" do

View file

@ -13,11 +13,9 @@ describe "The class keyword" do
ClassSpecsKeywordWithSemicolon.should be_an_instance_of(Class) ClassSpecsKeywordWithSemicolon.should be_an_instance_of(Class)
end end
ruby_version_is "2.3" do it "does not raise a SyntaxError when opening a class without a semicolon" do
it "does not raise a SyntaxError when opening a class without a semicolon" do eval "class ClassSpecsKeywordWithoutSemicolon end"
eval "class ClassSpecsKeywordWithoutSemicolon end" ClassSpecsKeywordWithoutSemicolon.should be_an_instance_of(Class)
ClassSpecsKeywordWithoutSemicolon.should be_an_instance_of(Class)
end
end end
end end

View file

@ -404,24 +404,22 @@ describe "Constant resolution within a singleton class (class << obj)" do
ConstantSpecs::CS_SINGLETON1.foo.should == 1 ConstantSpecs::CS_SINGLETON1.foo.should == 1
end end
ruby_version_is "2.3" do it "uses its own namespace for each object" do
it "uses its own namespace for each object" do a = ConstantSpecs::CS_SINGLETON2[0].foo
a = ConstantSpecs::CS_SINGLETON2[0].foo b = ConstantSpecs::CS_SINGLETON2[1].foo
b = ConstantSpecs::CS_SINGLETON2[1].foo [a, b].should == [1, 2]
[a, b].should == [1, 2] end
end
it "uses its own namespace for nested modules" do it "uses its own namespace for nested modules" do
a = ConstantSpecs::CS_SINGLETON3[0].x a = ConstantSpecs::CS_SINGLETON3[0].x
b = ConstantSpecs::CS_SINGLETON3[1].x b = ConstantSpecs::CS_SINGLETON3[1].x
a.should_not equal(b) a.should_not equal(b)
end end
it "allows nested modules to have proper resolution" do it "allows nested modules to have proper resolution" do
a = ConstantSpecs::CS_SINGLETON4_CLASSES[0].new a = ConstantSpecs::CS_SINGLETON4_CLASSES[0].new
b = ConstantSpecs::CS_SINGLETON4_CLASSES[1].new b = ConstantSpecs::CS_SINGLETON4_CLASSES[1].new
[a.foo, b.foo].should == [1, 2] [a.foo, b.foo].should == [1, 2]
end
end end
end end

View file

@ -66,6 +66,18 @@ describe "An ensure block inside a begin block" do
:ensure :ensure
end.should == :begin end.should == :begin
end end
it "sets exception cause if raises exception in block and in ensure" do
-> {
begin
raise "from block"
ensure
raise "from ensure"
end
}.should raise_error(RuntimeError, "from ensure") do |e|
e.cause.message.should == "from block"
end
end
end end
describe "The value of an ensure expression," do describe "The value of an ensure expression," do
@ -117,6 +129,34 @@ describe "An ensure block inside a method" do
it "has an impact on the method's explicit return value" do it "has an impact on the method's explicit return value" do
@obj.explicit_return_in_method_with_ensure.should == :ensure @obj.explicit_return_in_method_with_ensure.should == :ensure
end end
it "has an impact on the method's explicit return value from rescue if returns explicitly" do
@obj.explicit_return_in_rescue_and_explicit_return_in_ensure.should == "returned in ensure"
end
it "has no impact on the method's explicit return value from rescue if returns implicitly" do
@obj.explicit_return_in_rescue_and_implicit_return_in_ensure.should == "returned in rescue"
end
it "suppresses exception raised in method if returns value explicitly" do
@obj.raise_and_explicit_return_in_ensure.should == "returned in ensure"
end
it "suppresses exception raised in rescue if returns value explicitly" do
@obj.raise_in_rescue_and_explicit_return_in_ensure.should == "returned in ensure"
end
it "overrides exception raised in rescue if raises exception itself" do
-> {
@obj.raise_in_rescue_and_raise_in_ensure
}.should raise_error(RuntimeError, "raised in ensure")
end
it "suppresses exception raised in method if raises exception itself" do
-> {
@obj.raise_in_method_and_raise_in_ensure
}.should raise_error(RuntimeError, "raised in ensure")
end
end end
describe "An ensure block inside a class" do describe "An ensure block inside a class" do

View file

@ -40,6 +40,50 @@ module EnsureSpec
ensure ensure
return :ensure return :ensure
end end
def explicit_return_in_rescue_and_explicit_return_in_ensure
raise
rescue
return 2
ensure
return "returned in ensure"
end
def explicit_return_in_rescue_and_implicit_return_in_ensure
raise
rescue
return "returned in rescue"
ensure
3
end
def raise_and_explicit_return_in_ensure
raise
ensure
return "returned in ensure"
end
def raise_in_rescue_and_explicit_return_in_ensure
raise
rescue
raise
ensure
return "returned in ensure"
end
def raise_in_rescue_and_raise_in_ensure
raise
rescue
raise "raised in rescue"
ensure
raise "raised in ensure"
end
def raise_in_method_and_raise_in_ensure
raise
ensure
raise "raised in ensure"
end
end end
end end

View file

@ -455,6 +455,38 @@ module Super
end end
end end
module ZSuperWithRestReassigned
class A
def a(*args)
args
end
end
class B < A
def a(*args)
args = ["foo"]
super
end
end
end
module ZSuperWithRestReassignedWithScalar
class A
def a(*args)
args
end
end
class B < A
def a(*args)
args = "foo"
super
end
end
end
module ZSuperWithUnderscores module ZSuperWithUnderscores
class A class A
def m(*args) def m(*args)

View file

@ -53,35 +53,33 @@ HERE
s.should == ' foo bar#{@ip}' + "\n" s.should == ' foo bar#{@ip}' + "\n"
end end
ruby_version_is "2.3" do it "allows HEREDOC with <<~'identifier', allowing to indent identifier and content" do
it "allows HEREDOC with <<~'identifier', allowing to indent identifier and content" do require_relative 'fixtures/squiggly_heredoc'
require_relative 'fixtures/squiggly_heredoc' SquigglyHeredocSpecs.message.should == "character density, n.:\n The number of very weird people in the office.\n"
SquigglyHeredocSpecs.message.should == "character density, n.:\n The number of very weird people in the office.\n" end
end
it "trims trailing newline character for blank HEREDOC with <<~'identifier'" do it "trims trailing newline character for blank HEREDOC with <<~'identifier'" do
require_relative 'fixtures/squiggly_heredoc' require_relative 'fixtures/squiggly_heredoc'
SquigglyHeredocSpecs.blank.should == "" SquigglyHeredocSpecs.blank.should == ""
end end
it 'allows HEREDOC with <<~identifier, interpolated' do it 'allows HEREDOC with <<~identifier, interpolated' do
require_relative 'fixtures/squiggly_heredoc' require_relative 'fixtures/squiggly_heredoc'
SquigglyHeredocSpecs.unquoted.should == "unquoted interpolated\n" SquigglyHeredocSpecs.unquoted.should == "unquoted interpolated\n"
end end
it 'allows HEREDOC with <<~"identifier", interpolated' do it 'allows HEREDOC with <<~"identifier", interpolated' do
require_relative 'fixtures/squiggly_heredoc' require_relative 'fixtures/squiggly_heredoc'
SquigglyHeredocSpecs.doublequoted.should == "doublequoted interpolated\n" SquigglyHeredocSpecs.doublequoted.should == "doublequoted interpolated\n"
end end
it "allows HEREDOC with <<~'identifier', no interpolation" do it "allows HEREDOC with <<~'identifier', no interpolation" do
require_relative 'fixtures/squiggly_heredoc' require_relative 'fixtures/squiggly_heredoc'
SquigglyHeredocSpecs.singlequoted.should == "singlequoted \#{\"interpolated\"}\n" SquigglyHeredocSpecs.singlequoted.should == "singlequoted \#{\"interpolated\"}\n"
end end
it "selects the least-indented line and removes its indentation from all the lines" do it "selects the least-indented line and removes its indentation from all the lines" do
require_relative 'fixtures/squiggly_heredoc' require_relative 'fixtures/squiggly_heredoc'
SquigglyHeredocSpecs.least_indented_on_the_last_line.should == " a\n b\nc\n" SquigglyHeredocSpecs.least_indented_on_the_last_line.should == " a\n b\nc\n"
end
end end
end end

View file

@ -181,6 +181,52 @@ describe 'Optional variable assignments' do
@a.b.should == 20 @a.b.should == 20
end end
end end
describe 'using a #[]' do
before do
@a = {}
end
it 'leaves new variable unassigned' do
@a[:k] &&= 10
@a.key?(:k).should == false
end
it 'leaves false' do
@a[:k] = false
@a[:k] &&= 10
@a[:k].should == false
end
it 'leaves nil' do
@a[:k] = nil
@a[:k] &&= 10
@a[:k].should == nil
end
it 'does not evaluate the right side when not needed' do
@a[:k] = nil
@a[:k] &&= raise('should not be executed')
@a[:k].should == nil
end
it 'does re-assign a variable with a truthy value' do
@a[:k] = 10
@a[:k] &&= 20
@a[:k].should == 20
end
it 'does re-assign a variable with a truthy value when using an inline rescue' do
@a[:k] = 10
@a[:k] &&= 20 rescue 30
@a[:k].should == 20
end
end
end end
describe 'using compunded constants' do describe 'using compunded constants' do

View file

@ -0,0 +1,4 @@
p TOPLEVEL_BINDING.local_variables.sort
TOPLEVEL_BINDING.local_variable_set(:dynamic_set_main, 2)
p TOPLEVEL_BINDING.local_variables.sort
main_script = 3

View file

@ -0,0 +1,2 @@
TOPLEVEL_BINDING.local_variable_set(:dynamic_set_required, 1)
p TOPLEVEL_BINDING.local_variables

View file

@ -0,0 +1,4 @@
a = TOPLEVEL_BINDING.object_id
require_relative 'toplevel_binding_id_required'
c = eval('TOPLEVEL_BINDING.object_id')
p [a, $b, c].uniq.size

View file

@ -0,0 +1 @@
$b = TOPLEVEL_BINDING.object_id

View file

@ -0,0 +1,2 @@
required = true
p [:required_before, TOPLEVEL_BINDING.local_variables]

View file

@ -0,0 +1,9 @@
p TOPLEVEL_BINDING.local_variable_get(:a)
p TOPLEVEL_BINDING.local_variable_get(:b)
a = 1
p TOPLEVEL_BINDING.local_variable_get(:a)
p TOPLEVEL_BINDING.local_variable_get(:b)
b = 2
a = 3
p TOPLEVEL_BINDING.local_variable_get(:a)
p TOPLEVEL_BINDING.local_variable_get(:b)

View file

@ -0,0 +1,4 @@
main_script = 1
require_relative 'toplevel_binding_variables_required'
eval('eval_var = 3')
p TOPLEVEL_BINDING.local_variables

View file

@ -0,0 +1,2 @@
required = 2
p [:required_after, TOPLEVEL_BINDING.local_variables]

View file

@ -0,0 +1,34 @@
require_relative '../../spec_helper'
describe "The TOPLEVEL_BINDING constant" do
it "only includes local variables defined in the main script, not in required files or eval" do
binding_toplevel_variables = ruby_exe(fixture(__FILE__, "toplevel_binding_variables.rb"))
binding_toplevel_variables.should == "[:required_after, [:main_script]]\n[:main_script]\n"
end
it "has no local variables in files required before the main script" do
required = fixture(__FILE__, 'toplevel_binding_required_before.rb')
out = ruby_exe("a=1; p TOPLEVEL_BINDING.local_variables.sort; b=2", options: "-r#{required}")
out.should == "[:required_before, []]\n[:a, :b]\n"
end
it "merges local variables of the main script with dynamically-defined Binding variables" do
required = fixture(__FILE__, 'toplevel_binding_dynamic_required.rb')
out = ruby_exe(fixture(__FILE__, 'toplevel_binding_dynamic.rb'), options: "-r#{required}")
out.should == <<EOS
[:dynamic_set_required]
[:dynamic_set_required, :main_script]
[:dynamic_set_main, :dynamic_set_required, :main_script]
EOS
end
it "gets updated variables values as they are defined and set" do
out = ruby_exe(fixture(__FILE__, "toplevel_binding_values.rb"))
out.should == "nil\nnil\n1\nnil\n3\n2\n"
end
it "is always the same object for all top levels" do
binding_toplevel_id = ruby_exe(fixture(__FILE__, "toplevel_binding_id.rb"))
binding_toplevel_id.should == "1\n"
end
end

View file

@ -371,11 +371,23 @@ describe "The rescue keyword" do
end end
it "evaluates rescue expressions only when needed" do it "evaluates rescue expressions only when needed" do
invalid_rescuer = Object.new
begin begin
:foo ScratchPad << :foo
rescue invalid_rescuer rescue -> { ScratchPad << :bar; StandardError }.call
end.should == :foo end
ScratchPad.recorded.should == [:foo]
end
it "suppresses exception from block when raises one from rescue expression" do
-> {
begin
raise "from block"
rescue (raise "from rescue expression")
end
}.should raise_error(RuntimeError, "from rescue expression") do |e|
e.cause.message.should == "from block"
end
end end
it "should splat the handling Error classes" do it "should splat the handling Error classes" do

View file

@ -1,101 +1,99 @@
require_relative '../spec_helper' require_relative '../spec_helper'
ruby_version_is "2.3" do describe "Safe navigator" do
describe "Safe navigator" do it "requires a method name to be provided" do
it "requires a method name to be provided" do lambda { eval("obj&. {}") }.should raise_error(SyntaxError)
lambda { eval("obj&. {}") }.should raise_error(SyntaxError) end
context "when context is nil" do
it "always returns nil" do
eval("nil&.unknown").should == nil
eval("[][10]&.unknown").should == nil
end end
context "when context is nil" do it "can be chained" do
it "always returns nil" do eval("nil&.one&.two&.three").should == nil
eval("nil&.unknown").should == nil
eval("[][10]&.unknown").should == nil
end
it "can be chained" do
eval("nil&.one&.two&.three").should == nil
end
it "doesn't evaluate arguments" do
obj = Object.new
obj.should_not_receive(:m)
eval("nil&.unknown(obj.m) { obj.m }")
end
end end
context "when context is false" do it "doesn't evaluate arguments" do
it "calls the method" do obj = Object.new
eval("false&.to_s").should == "false" obj.should_not_receive(:m)
eval("nil&.unknown(obj.m) { obj.m }")
lambda { eval("false&.unknown") }.should raise_error(NoMethodError)
end
end
context "when context is truthy" do
it "calls the method" do
eval("1&.to_s").should == "1"
lambda { eval("1&.unknown") }.should raise_error(NoMethodError)
end
end
it "takes a list of arguments" do
eval("[1,2,3]&.first(2)").should == [1,2]
end
it "takes a block" do
eval("[1,2]&.map { |i| i * 2 }").should == [2, 4]
end
it "allows assignment methods" do
klass = Class.new do
attr_reader :foo
def foo=(val)
@foo = val
42
end
end
obj = klass.new
eval("obj&.foo = 3").should == 3
obj.foo.should == 3
obj = nil
eval("obj&.foo = 3").should == nil
end
it "allows assignment operators" do
klass = Class.new do
attr_accessor :m
def initialize
@m = 0
end
end
obj = klass.new
eval("obj&.m += 3")
obj.m.should == 3
obj = nil
eval("obj&.m += 3").should == nil
end
it "does not call the operator method lazily with an assignment operator" do
klass = Class.new do
attr_writer :foo
def foo
nil
end
end
obj = klass.new
lambda {
eval("obj&.foo += 3")
}.should raise_error(NoMethodError) { |e|
e.name.should == :+
}
end end
end end
context "when context is false" do
it "calls the method" do
eval("false&.to_s").should == "false"
lambda { eval("false&.unknown") }.should raise_error(NoMethodError)
end
end
context "when context is truthy" do
it "calls the method" do
eval("1&.to_s").should == "1"
lambda { eval("1&.unknown") }.should raise_error(NoMethodError)
end
end
it "takes a list of arguments" do
eval("[1,2,3]&.first(2)").should == [1,2]
end
it "takes a block" do
eval("[1,2]&.map { |i| i * 2 }").should == [2, 4]
end
it "allows assignment methods" do
klass = Class.new do
attr_reader :foo
def foo=(val)
@foo = val
42
end
end
obj = klass.new
eval("obj&.foo = 3").should == 3
obj.foo.should == 3
obj = nil
eval("obj&.foo = 3").should == nil
end
it "allows assignment operators" do
klass = Class.new do
attr_accessor :m
def initialize
@m = 0
end
end
obj = klass.new
eval("obj&.m += 3")
obj.m.should == 3
obj = nil
eval("obj&.m += 3").should == nil
end
it "does not call the operator method lazily with an assignment operator" do
klass = Class.new do
attr_writer :foo
def foo
nil
end
end
obj = klass.new
lambda {
eval("obj&.foo += 3")
}.should raise_error(NoMethodError) { |e|
e.name.should == :+
}
end
end end

View file

@ -233,27 +233,25 @@ describe "Ruby String literals" do
long_string_literals.should == "Beautiful is better than ugly.Explicit is better than implicit." long_string_literals.should == "Beautiful is better than ugly.Explicit is better than implicit."
end end
ruby_version_is "2.3" do describe "with a magic frozen comment" do
describe "with a magic frozen comment" do it "produce the same object each time" do
it "produce the same object each time" do ruby_exe(fixture(__FILE__, "freeze_magic_comment_one_literal.rb")).chomp.should == "true"
ruby_exe(fixture(__FILE__, "freeze_magic_comment_one_literal.rb")).chomp.should == "true" end
end
it "produce the same object for literals with the same content" do it "produce the same object for literals with the same content" do
ruby_exe(fixture(__FILE__, "freeze_magic_comment_two_literals.rb")).chomp.should == "true" ruby_exe(fixture(__FILE__, "freeze_magic_comment_two_literals.rb")).chomp.should == "true"
end end
it "produce the same object for literals with the same content in different files" do it "produce the same object for literals with the same content in different files" do
ruby_exe(fixture(__FILE__, "freeze_magic_comment_across_files.rb")).chomp.should == "true" ruby_exe(fixture(__FILE__, "freeze_magic_comment_across_files.rb")).chomp.should == "true"
end end
it "produce different objects for literals with the same content in different files if the other file doesn't have the comment" do it "produce different objects for literals with the same content in different files if the other file doesn't have the comment" do
ruby_exe(fixture(__FILE__, "freeze_magic_comment_across_files_no_comment.rb")).chomp.should == "true" ruby_exe(fixture(__FILE__, "freeze_magic_comment_across_files_no_comment.rb")).chomp.should == "true"
end end
it "produce different objects for literals with the same content in different files if they have different encodings" do it "produce different objects for literals with the same content in different files if they have different encodings" do
ruby_exe(fixture(__FILE__, "freeze_magic_comment_across_files_diff_enc.rb")).chomp.should == "true" ruby_exe(fixture(__FILE__, "freeze_magic_comment_across_files_diff_enc.rb")).chomp.should == "true"
end
end end
end end

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