summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--spec/ruby/.rubocop.yml21
-rw-r--r--spec/ruby/.rubocop_todo.yml13
-rw-r--r--spec/ruby/.travis.yml14
-rw-r--r--spec/ruby/CONTRIBUTING.md107
-rw-r--r--spec/ruby/core/array/at_spec.rb4
-rw-r--r--spec/ruby/core/array/intersection_spec.rb4
-rw-r--r--spec/ruby/core/array/max_spec.rb6
-rw-r--r--spec/ruby/core/array/min_spec.rb6
-rw-r--r--spec/ruby/core/array/pack/buffer_spec.rb52
-rw-r--r--spec/ruby/core/array/permutation_spec.rb2
-rw-r--r--spec/ruby/core/array/pop_spec.rb2
-rw-r--r--spec/ruby/core/array/shift_spec.rb2
-rw-r--r--spec/ruby/core/array/sum_spec.rb44
-rw-r--r--spec/ruby/core/bignum/bignum_spec.rb12
-rw-r--r--spec/ruby/core/complex/finite_spec.rb36
-rw-r--r--spec/ruby/core/complex/infinite_spec.rb34
-rw-r--r--spec/ruby/core/dir/empty_spec.rb33
-rw-r--r--spec/ruby/core/dir/glob_spec.rb2
-rw-r--r--spec/ruby/core/encoding/converter/primitive_convert_spec.rb2
-rw-r--r--spec/ruby/core/encoding/converter/primitive_errinfo_spec.rb6
-rw-r--r--spec/ruby/core/encoding/converter/putback_spec.rb3
-rw-r--r--spec/ruby/core/encoding/invalid_byte_sequence_error/source_encoding_name_spec.rb2
-rw-r--r--spec/ruby/core/encoding/invalid_byte_sequence_error/source_encoding_spec.rb2
-rw-r--r--spec/ruby/core/encoding/undefined_conversion_error/source_encoding_name_spec.rb2
-rw-r--r--spec/ruby/core/encoding/undefined_conversion_error/source_encoding_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/any_spec.rb8
-rw-r--r--spec/ruby/core/enumerable/cycle_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/drop_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/uniq_spec.rb65
-rw-r--r--spec/ruby/core/enumerator/lazy/force_spec.rb2
-rw-r--r--spec/ruby/core/false/dup_spec.rb9
-rw-r--r--spec/ruby/core/file/empty_spec.rb15
-rw-r--r--spec/ruby/core/file/readlink_spec.rb23
-rw-r--r--spec/ruby/core/file/shared/fnmatch.rb10
-rw-r--r--spec/ruby/core/fixnum/fixnum_spec.rb12
-rw-r--r--spec/ruby/core/float/ceil_spec.rb10
-rw-r--r--spec/ruby/core/float/dup_spec.rb10
-rw-r--r--spec/ruby/core/float/floor_spec.rb10
-rw-r--r--spec/ruby/core/float/round_spec.rb14
-rw-r--r--spec/ruby/core/float/truncate_spec.rb10
-rw-r--r--spec/ruby/core/hash/delete_spec.rb4
-rw-r--r--spec/ruby/core/hash/transform_values_spec.rb21
-rw-r--r--spec/ruby/core/integer/ceil_spec.rb15
-rw-r--r--spec/ruby/core/integer/digits_spec.rb34
-rw-r--r--spec/ruby/core/integer/dup_spec.rb10
-rw-r--r--spec/ruby/core/integer/floor_spec.rb15
-rw-r--r--spec/ruby/core/integer/integer_spec.rb7
-rw-r--r--spec/ruby/core/integer/round_spec.rb48
-rw-r--r--spec/ruby/core/integer/shared/integer_rounding.rb31
-rw-r--r--spec/ruby/core/integer/sqrt_spec.rb33
-rw-r--r--spec/ruby/core/integer/truncate_spec.rb15
-rw-r--r--spec/ruby/core/io/advise_spec.rb2
-rw-r--r--spec/ruby/core/io/fixtures/classes.rb12
-rw-r--r--spec/ruby/core/io/gets_spec.rb10
-rw-r--r--spec/ruby/core/io/readline_spec.rb8
-rw-r--r--spec/ruby/core/io/shared/each.rb9
-rw-r--r--spec/ruby/core/io/shared/readlines.rb7
-rw-r--r--spec/ruby/core/kernel/equal_value_spec.rb6
-rw-r--r--spec/ruby/core/main/fixtures/classes.rb3
-rw-r--r--spec/ruby/core/main/fixtures/string_refinement.rb7
-rw-r--r--spec/ruby/core/main/fixtures/string_refinement_user.rb11
-rw-r--r--spec/ruby/core/main/using_spec.rb134
-rw-r--r--spec/ruby/core/module/fixtures/refine.rb13
-rw-r--r--spec/ruby/core/module/fixtures/using.rb10
-rw-r--r--spec/ruby/core/module/refine_spec.rb616
-rw-r--r--spec/ruby/core/module/using_spec.rb276
-rw-r--r--spec/ruby/core/mutex/lock_spec.rb11
-rw-r--r--spec/ruby/core/nil/dup_spec.rb9
-rw-r--r--spec/ruby/core/numeric/coerce_spec.rb2
-rw-r--r--spec/ruby/core/numeric/finite_spec.rb10
-rw-r--r--spec/ruby/core/numeric/infinite_spec.rb10
-rw-r--r--spec/ruby/core/process/wait2_spec.rb5
-rw-r--r--spec/ruby/core/random/bytes_spec.rb4
-rw-r--r--spec/ruby/core/string/capitalize_spec.rb8
-rw-r--r--spec/ruby/core/string/casecmp_spec.rb74
-rw-r--r--spec/ruby/core/string/downcase_spec.rb8
-rw-r--r--spec/ruby/core/string/lines_spec.rb9
-rw-r--r--spec/ruby/core/string/new_spec.rb7
-rw-r--r--spec/ruby/core/string/shared/chars.rb6
-rw-r--r--spec/ruby/core/string/shared/codepoints.rb2
-rw-r--r--spec/ruby/core/string/shared/each_line.rb14
-rw-r--r--spec/ruby/core/string/shared/to_sym.rb67
-rw-r--r--spec/ruby/core/string/swapcase_spec.rb8
-rw-r--r--spec/ruby/core/string/unpack1_spec.rb12
-rw-r--r--spec/ruby/core/string/upcase_spec.rb9
-rw-r--r--spec/ruby/core/struct/initialize_spec.rb2
-rw-r--r--spec/ruby/core/symbol/capitalize_spec.rb7
-rw-r--r--spec/ruby/core/symbol/casecmp_spec.rb106
-rw-r--r--spec/ruby/core/symbol/downcase_spec.rb7
-rw-r--r--spec/ruby/core/symbol/dup_spec.rb9
-rw-r--r--spec/ruby/core/symbol/swapcase_spec.rb7
-rw-r--r--spec/ruby/core/symbol/upcase_spec.rb7
-rw-r--r--spec/ruby/core/thread/element_set_spec.rb8
-rw-r--r--spec/ruby/core/thread/fixtures/classes.rb7
-rw-r--r--spec/ruby/core/thread/join_spec.rb5
-rw-r--r--spec/ruby/core/thread/key_spec.rb2
-rw-r--r--spec/ruby/core/thread/raise_spec.rb6
-rw-r--r--spec/ruby/core/thread/report_on_exception_spec.rb102
-rw-r--r--spec/ruby/core/thread/shared/exit.rb2
-rw-r--r--spec/ruby/core/thread/value_spec.rb5
-rw-r--r--spec/ruby/core/time/shared/now.rb12
-rw-r--r--spec/ruby/core/time/shared/time_params.rb6
-rw-r--r--spec/ruby/core/tracepoint/callee_id_spec.rb20
-rw-r--r--spec/ruby/core/tracepoint/fixtures/classes.rb8
-rw-r--r--spec/ruby/core/true/dup_spec.rb9
-rw-r--r--spec/ruby/core/warning/warn_spec.rb60
-rw-r--r--spec/ruby/language/README2
-rw-r--r--spec/ruby/language/block_spec.rb2
-rw-r--r--spec/ruby/language/break_spec.rb13
-rw-r--r--spec/ruby/language/case_spec.rb7
-rw-r--r--spec/ruby/language/class_spec.rb22
-rw-r--r--spec/ruby/language/constants_spec.rb17
-rw-r--r--spec/ruby/language/defined_spec.rb2
-rw-r--r--spec/ruby/language/ensure_spec.rb4
-rw-r--r--spec/ruby/language/fixtures/binary_symbol.rb4
-rw-r--r--spec/ruby/language/fixtures/super.rb133
-rw-r--r--spec/ruby/language/if_spec.rb19
-rw-r--r--spec/ruby/language/method_spec.rb10
-rw-r--r--spec/ruby/language/optional_assignments_spec.rb4
-rw-r--r--spec/ruby/language/predefined_spec.rb19
-rw-r--r--spec/ruby/language/regexp/character_classes_spec.rb23
-rw-r--r--spec/ruby/language/regexp/modifiers_spec.rb7
-rw-r--r--spec/ruby/language/rescue_spec.rb7
-rw-r--r--spec/ruby/language/return_spec.rb223
-rw-r--r--spec/ruby/language/super_spec.rb119
-rw-r--r--spec/ruby/language/symbol_spec.rb13
-rw-r--r--spec/ruby/language/throw_spec.rb15
-rw-r--r--spec/ruby/library/bigdecimal/sign_spec.rb2
-rw-r--r--spec/ruby/library/cgi/cookie/parse_spec.rb21
-rw-r--r--spec/ruby/library/cgi/shared/http_header.rb6
-rw-r--r--spec/ruby/library/conditionvariable/marshal_dump_spec.rb9
-rw-r--r--spec/ruby/library/csv/liberal_parsing_spec.rb21
-rw-r--r--spec/ruby/library/csv/parse_spec.rb14
-rw-r--r--spec/ruby/library/csv/readlines_spec.rb14
-rw-r--r--spec/ruby/library/date/friday_spec.rb12
-rw-r--r--spec/ruby/library/date/minus_month_spec.rb2
-rw-r--r--spec/ruby/library/date/minus_spec.rb4
-rw-r--r--spec/ruby/library/date/monday_spec.rb8
-rw-r--r--spec/ruby/library/date/next_day_spec.rb10
-rw-r--r--spec/ruby/library/date/next_month_spec.rb15
-rw-r--r--spec/ruby/library/date/prev_day_spec.rb6
-rw-r--r--spec/ruby/library/date/prev_month_spec.rb15
-rw-r--r--spec/ruby/library/date/saturday_spec.rb8
-rw-r--r--spec/ruby/library/date/sunday_spec.rb8
-rw-r--r--spec/ruby/library/date/thursday_spec.rb8
-rw-r--r--spec/ruby/library/date/today_spec.rb10
-rw-r--r--spec/ruby/library/date/tuesday_spec.rb8
-rw-r--r--spec/ruby/library/date/wday_spec.rb5
-rw-r--r--spec/ruby/library/date/wednesday_spec.rb8
-rw-r--r--spec/ruby/library/datetime/new_spec.rb2
-rw-r--r--spec/ruby/library/datetime/now_spec.rb17
-rw-r--r--spec/ruby/library/datetime/to_date_spec.rb33
-rw-r--r--spec/ruby/library/datetime/to_datetime_spec.rb5
-rw-r--r--spec/ruby/library/datetime/to_s_spec.rb13
-rw-r--r--spec/ruby/library/datetime/to_time_spec.rb22
-rw-r--r--spec/ruby/library/etc/getlogin_spec.rb12
-rw-r--r--spec/ruby/library/fiber/resume_spec.rb2
-rw-r--r--spec/ruby/library/fiber/transfer_spec.rb2
-rw-r--r--spec/ruby/library/getoptlong/terminate_spec.rb2
-rw-r--r--spec/ruby/library/ipaddr/operator_spec.rb9
-rw-r--r--spec/ruby/library/logger/logger/new_spec.rb57
-rw-r--r--spec/ruby/library/matrix/diagonal_spec.rb4
-rw-r--r--spec/ruby/library/matrix/hermitian_spec.rb6
-rw-r--r--spec/ruby/library/matrix/normal_spec.rb4
-rw-r--r--spec/ruby/library/matrix/orthogonal_spec.rb4
-rw-r--r--spec/ruby/library/matrix/permutation_spec.rb4
-rw-r--r--spec/ruby/library/matrix/symmetric_spec.rb6
-rw-r--r--spec/ruby/library/matrix/unitary_spec.rb4
-rw-r--r--spec/ruby/library/net/ftp/fixtures/server.rb10
-rw-r--r--spec/ruby/library/net/ftp/status_spec.rb6
-rw-r--r--spec/ruby/library/net/http/http/fixtures/http_server.rb12
-rw-r--r--spec/ruby/library/net/http/http/post_spec.rb39
-rw-r--r--spec/ruby/library/net/http/http/request_types_spec.rb28
-rw-r--r--spec/ruby/library/net/http/httpheader/content_length_spec.rb2
-rw-r--r--spec/ruby/library/optionparser/order_spec.rb32
-rw-r--r--spec/ruby/library/optionparser/parse_spec.rb32
-rw-r--r--spec/ruby/library/pathname/empty_spec.rb34
-rw-r--r--spec/ruby/library/pathname/relative_path_from_spec.rb2
-rw-r--r--spec/ruby/library/rexml/element/add_attributes_spec.rb2
-rw-r--r--spec/ruby/library/rexml/element/add_text_spec.rb2
-rw-r--r--spec/ruby/library/rexml/element/element_reference_spec.rb22
-rw-r--r--spec/ruby/library/securerandom/base64_spec.rb2
-rw-r--r--spec/ruby/library/securerandom/hex_spec.rb2
-rw-r--r--spec/ruby/library/set/compare_by_identity_spec.rb147
-rw-r--r--spec/ruby/library/set/shared/difference.rb2
-rw-r--r--spec/ruby/library/set/sortedset/shared/difference.rb2
-rw-r--r--spec/ruby/library/shellwords/shellwords_spec.rb7
-rw-r--r--spec/ruby/library/socket/tcpserver/accept_spec.rb13
-rw-r--r--spec/ruby/library/socket/tcpserver/new_spec.rb2
-rw-r--r--spec/ruby/library/socket/unixserver/accept_spec.rb12
-rw-r--r--spec/ruby/library/stringio/each_line_spec.rb6
-rw-r--r--spec/ruby/library/stringio/each_spec.rb6
-rw-r--r--spec/ruby/library/stringio/getc_spec.rb2
-rw-r--r--spec/ruby/library/stringio/getch_spec.rb2
-rw-r--r--spec/ruby/library/stringio/gets_spec.rb13
-rw-r--r--spec/ruby/library/stringio/lines_spec.rb6
-rw-r--r--spec/ruby/library/stringio/readline_spec.rb13
-rw-r--r--spec/ruby/library/stringio/readlines_spec.rb9
-rw-r--r--spec/ruby/library/stringio/shared/each.rb9
-rw-r--r--spec/ruby/library/time/to_time_spec.rb17
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/new_spec.rb2
-rw-r--r--spec/ruby/library/yaml/shared/each_document.rb2
-rw-r--r--spec/ruby/library/yaml/to_yaml_spec.rb2
-rw-r--r--spec/ruby/optional/capi/encoding_spec.rb2
-rw-r--r--spec/ruby/optional/capi/ext/kernel_spec.c14
-rw-r--r--spec/ruby/optional/capi/ext/rubyspec.h1
-rw-r--r--spec/ruby/optional/capi/ext/string_spec.c16
-rw-r--r--spec/ruby/optional/capi/kernel_spec.rb10
-rw-r--r--spec/ruby/optional/capi/object_spec.rb7
-rw-r--r--spec/ruby/optional/capi/proc_spec.rb2
-rw-r--r--spec/ruby/optional/capi/spec_helper.rb7
-rw-r--r--spec/ruby/optional/capi/string_spec.rb35
-rw-r--r--spec/ruby/optional/capi/thread_spec.rb9
-rw-r--r--spec/ruby/shared/fiber/resume.rb12
-rw-r--r--spec/ruby/shared/rational/minus.rb6
-rw-r--r--spec/ruby/shared/rational/plus.rb6
-rw-r--r--spec/ruby/shared/rational/round.rb25
-rw-r--r--spec/ruby/spec_helper.rb11
218 files changed, 4068 insertions, 327 deletions
diff --git a/spec/ruby/.rubocop.yml b/spec/ruby/.rubocop.yml
index a776517b73..d8b9aa7f8a 100644
--- a/spec/ruby/.rubocop.yml
+++ b/spec/ruby/.rubocop.yml
@@ -7,13 +7,28 @@ AllCops:
- command_line/fixtures/bad_syntax.rb
DisabledByDefault: true
+Layout/TrailingWhitespace:
+ Enabled: true
+
Lint:
Enabled: true
Lint/AssignmentInCondition:
Enabled: false
-Lint/LiteralInCondition:
+Lint/BooleanSymbol:
+ Enabled: false
+
+Lint/InterpolationCheck:
+ Enabled: false
+
+Lint/LiteralAsCondition:
+ Enabled: false
+
+Lint/UnneededRequireStatement:
+ Enabled: false
+
+Lint/RescueWithoutErrorClass:
Enabled: false
Lint/UnifiedInteger:
@@ -38,3 +53,7 @@ Lint/Void:
Lint/EmptyExpression:
Exclude:
- 'language/**/*.rb'
+
+Lint/UriRegexp:
+ Exclude:
+ - 'library/uri/regexp_spec.rb'
diff --git a/spec/ruby/.rubocop_todo.yml b/spec/ruby/.rubocop_todo.yml
index cb91f43ead..1d68068121 100644
--- a/spec/ruby/.rubocop_todo.yml
+++ b/spec/ruby/.rubocop_todo.yml
@@ -1,6 +1,6 @@
# This configuration was generated by
# `rubocop --auto-gen-config`
-# on 2017-06-18 19:12:38 +0200 using RuboCop version 0.49.1.
+# on 2017-10-09 20:22:01 +0200 using RuboCop version 0.50.0.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
@@ -52,7 +52,7 @@ Lint/FloatOutOfRange:
Exclude:
- 'core/string/modulo_spec.rb'
-# Offense count: 46
+# Offense count: 43
Lint/FormatParameterMismatch:
Exclude:
- 'core/kernel/sprintf_spec.rb'
@@ -137,6 +137,7 @@ Lint/RescueException:
- 'library/erb/filename_spec.rb'
# Offense count: 1
+# Cop supports --auto-correct.
Lint/ScriptPermission:
Exclude:
- 'command_line/fixtures/bin/launcher.rb'
@@ -181,7 +182,7 @@ Lint/UnneededSplatExpansion:
- 'language/send_spec.rb'
- 'language/variables_spec.rb'
-# Offense count: 53
+# Offense count: 55
Lint/UnreachableCode:
Exclude:
- 'core/enumerator/lazy/fixtures/classes.rb'
@@ -198,7 +199,7 @@ Lint/UnreachableCode:
- 'optional/capi/kernel_spec.rb'
- 'shared/kernel/raise.rb'
-# Offense count: 9
+# Offense count: 7
# Configuration parameters: ContextCreatingMethods, MethodCreatingMethods.
Lint/UselessAccessModifier:
Exclude:
@@ -206,6 +207,4 @@ Lint/UselessAccessModifier:
- 'core/module/fixtures/classes.rb'
- 'core/module/module_function_spec.rb'
- 'core/module/private_class_method_spec.rb'
- - 'core/module/private_spec.rb'
- - 'core/module/protected_spec.rb'
- - 'core/module/public_spec.rb'
+ - 'language/fixtures/send.rb'
diff --git a/spec/ruby/.travis.yml b/spec/ruby/.travis.yml
index 1a2e64ff84..e8a9106ac1 100644
--- a/spec/ruby/.travis.yml
+++ b/spec/ruby/.travis.yml
@@ -3,21 +3,23 @@ language: ruby
install:
- git clone https://github.com/ruby/mspec.git ../mspec
script:
- - if [ -n "$RUBOCOP" ]; then gem install rubocop -v 0.49.1 && rubocop; fi
+ - if [ -n "$RUBOCOP" ]; then gem install rubocop -v 0.51.0 && rubocop; fi
- ../mspec/bin/mspec $MSPEC_OPTS
matrix:
include:
- os: osx
- rvm: 2.4.0
+ osx_image: xcode9
+ rvm: 2.4.2
+ env: CHECK_LEAKS=true
- os: linux
- rvm: 2.4.1
+ rvm: 2.4.2
env: MSPEC_OPTS="-R2 -ff"
- os: linux
- rvm: 2.2.7
+ rvm: 2.2.8
- os: linux
- rvm: 2.3.4
+ rvm: 2.3.5
- os: linux
- rvm: 2.4.1
+ rvm: 2.4.2
env: CHECK_LEAKS=true RUBOCOP=true
- os: linux
rvm: ruby-head
diff --git a/spec/ruby/CONTRIBUTING.md b/spec/ruby/CONTRIBUTING.md
index e675a61afa..fc88475970 100644
--- a/spec/ruby/CONTRIBUTING.md
+++ b/spec/ruby/CONTRIBUTING.md
@@ -48,9 +48,116 @@ You might also want to search for:
which indicates the file was generated but the method unspecified.
+### Matchers and expectations
+
+Here is a list of frequently-used matchers, which should be enough for most specs.
+There are a few extra specific matchers used in the couple specs that need it.
+
+```ruby
+(1 + 2).should == 3 # Calls #==
+(1 + 2).should_not == 5
+
+File.should equal(File) # Calls #equal? (tests identity)
+(1 + 2).should eql(3) # Calls #eql? (Hash equality)
+
+1.should < 2
+2.should <= 2
+3.should >= 3
+4.should > 3
+
+"Hello".should =~ /l{2}/ # Calls #=~ (Regexp match)
+
+[].should be_empty # Calls #empty?
+[1,2,3].should include(2) # Calls #include?
+
+(0.1 + 0.2).should be_close(0.3, TOLERANCE) # (0.2-0.1).abs < TOLERANCE
+(0.0/0.0).should be_nan # Calls Float#nan?
+(1.0/0.0).should be_positive_infinity
+(-1.0/0.0).should be_negative_infinity
+
+3.14.should be_an_instance_of(Float) # Calls #instance_of?
+3.14.should be_kind_of(Numeric) # Calls #is_a?
+Numeric.should be_ancestor_of(Float) # Float.ancestors.include?(Numeric)
+
+3.14.should respond_to(:to_i) # Calls #respond_to?
+Fixnum.should have_instance_method(:+)
+Array.should have_method(:new)
+# Also have_constant, have_private_instance_method, have_singleton_method, etc
+
+-> {
+ raise "oops"
+}.should raise_error(RuntimeError, /oops/)
+
+# To avoid! Instead, use an expectation testing what the code in the lambda does.
+# If an exception is raised, it will fail the example anyway.
+-> { ... }.should_not raise_error
+
+-> {
+ Fixnum
+}.should complain(/constant ::Fixnum is deprecated/) # Expect a warning
+```
+
### Guards
Different guards are available as defined by mspec.
+Here is a list of the most commonly-used guards:
+
+```ruby
+ruby_version_is ""..."2.4" do
+ # Specs for RUBY_VERSION < 2.4
+end
+
+ruby_version_is "2.4" do
+ # Specs for RUBY_VERSION >= 2.4
+end
+
+platform_is :windows do
+ # Specs only valid on Windows
+end
+
+platform_is_not :windows do
+ # Specs valid on platforms other than Windows
+end
+
+platform_is :linux, :darwin do # OR
+end
+
+platform_is_not :linux, :darwin do # Not Linux and not Darwin
+end
+
+platform_is wordsize: 64 do
+ # 64-bit platform
+end
+
+big_endian do
+ # Big-endian platform
+end
+
+# In case there is a bug in MRI but the expected behavior is obvious
+# First file a bug at https://bugs.ruby-lang.org/
+# It is better to use a ruby_version_is guard if there was a release with the fix
+ruby_bug '#13669', ''...'2.5' do
+ it "works like this" do
+ # Specify the expected behavior here, not the bug
+ end
+end
+
+
+# Combining guards
+guard -> { platform_is :windows and ruby_version_is ""..."2.3" } do
+ # Windows and RUBY_VERSION < 2.3
+end
+
+guard_not -> { platform_is :windows and ruby_version_is ""..."2.3" } do
+ # The opposite
+end
+
+# Custom guard
+max_uint = (1 << 32) - 1
+guard -> { max_uint <= fixnum_max } do
+end
+```
+
In general, the usage of guards should be minimized as possible.
There are no guards to define implementation-specific behavior because
diff --git a/spec/ruby/core/array/at_spec.rb b/spec/ruby/core/array/at_spec.rb
index e40c26f2cc..f2af0e13a1 100644
--- a/spec/ruby/core/array/at_spec.rb
+++ b/spec/ruby/core/array/at_spec.rb
@@ -15,7 +15,7 @@ describe "Array#at" do
a.at(7).should == nil
end
- it "returns the (-n)'th elemet from the last, for the given negative index n" do
+ it "returns the (-n)'th element from the last, for the given negative index n" do
a = [1, 2, 3, 4, 5, 6]
a.at(-1).should == 6
a.at(-2).should == 5
@@ -50,7 +50,7 @@ describe "Array#at" do
lambda { [].at("cat") }.should raise_error(TypeError)
end
- it "raises an ArgumentError when 2 or more arguments is passed" do
+ it "raises an ArgumentError when 2 or more arguments are passed" do
lambda { [:a, :b].at(0,1) }.should raise_error(ArgumentError)
end
end
diff --git a/spec/ruby/core/array/intersection_spec.rb b/spec/ruby/core/array/intersection_spec.rb
index 4d6c2a12d3..e399509ea7 100644
--- a/spec/ruby/core/array/intersection_spec.rb
+++ b/spec/ruby/core/array/intersection_spec.rb
@@ -19,7 +19,7 @@ describe "Array#&" do
it "does not modify the original Array" do
a = [1, 1, 3, 5]
- a & [1, 2, 3]
+ (a & [1, 2, 3]).should == [1, 3]
a.should == [1, 1, 3, 5]
end
@@ -52,7 +52,7 @@ describe "Array#&" do
obj1.stub!(:hash).and_return(0)
obj2.stub!(:hash).and_return(0)
obj1.should_receive(:eql?).at_least(1).and_return(true)
- obj2.should_receive(:eql?).at_least(1).and_return(true)
+ obj2.stub!(:eql?).and_return(true)
([obj1] & [obj2]).should == [obj1]
([obj1, obj1, obj2, obj2] & [obj2]).should == [obj1]
diff --git a/spec/ruby/core/array/max_spec.rb b/spec/ruby/core/array/max_spec.rb
index cf6a48c2e3..db1d755645 100644
--- a/spec/ruby/core/array/max_spec.rb
+++ b/spec/ruby/core/array/max_spec.rb
@@ -1,6 +1,12 @@
require File.expand_path('../../../spec_helper', __FILE__)
describe "Array#max" do
+ ruby_version_is "2.4" do
+ it "is defined on Array" do
+ [1].method(:max).owner.should equal Array
+ end
+ end
+
it "returns nil with no values" do
[].max.should == nil
end
diff --git a/spec/ruby/core/array/min_spec.rb b/spec/ruby/core/array/min_spec.rb
index 53fe4e0692..59f3814da2 100644
--- a/spec/ruby/core/array/min_spec.rb
+++ b/spec/ruby/core/array/min_spec.rb
@@ -1,6 +1,12 @@
require File.expand_path('../../../spec_helper', __FILE__)
describe "Array#min" do
+ ruby_version_is "2.4" do
+ it "is defined on Array" do
+ [1].method(:max).owner.should equal Array
+ end
+ end
+
it "returns nil with no values" do
[].min.should == nil
end
diff --git a/spec/ruby/core/array/pack/buffer_spec.rb b/spec/ruby/core/array/pack/buffer_spec.rb
new file mode 100644
index 0000000000..928f7db731
--- /dev/null
+++ b/spec/ruby/core/array/pack/buffer_spec.rb
@@ -0,0 +1,52 @@
+# encoding: ascii-8bit
+
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+ruby_version_is '2.4' do
+ describe "Aray#pack with `buffer` option" do
+ it "returns specified buffer" do
+ n = [ 65, 66, 67 ]
+ buffer = " "*3
+ result = n.pack("ccc", buffer: buffer) #=> "ABC"
+ result.should equal(buffer)
+ end
+
+ it "adds result at the end of buffer content" do
+ n = [ 65, 66, 67 ] # result without buffer is "ABC"
+
+ buffer = ""
+ n.pack("ccc", buffer: buffer).should == "ABC"
+
+ buffer = "123"
+ n.pack("ccc", buffer: buffer).should == "123ABC"
+
+ buffer = "12345"
+ n.pack("ccc", buffer: buffer).should == "12345ABC"
+ end
+
+ it "raises TypeError exception if buffer is not String" do
+ lambda { [65].pack("ccc", buffer: []) }.should raise_error(
+ TypeError, "buffer must be String, not Array")
+ end
+
+ context "offset (@) is specified" do
+ it 'keeps buffer content if it is longer than offset' do
+ n = [ 65, 66, 67 ]
+ buffer = "123456"
+ n.pack("@3ccc", buffer: buffer).should == "123ABC"
+ end
+
+ it "fills the gap with \0 if buffer content is shorter than offset" do
+ n = [ 65, 66, 67 ]
+ buffer = "123"
+ n.pack("@6ccc", buffer: buffer).should == "123\0\0\0ABC"
+ end
+
+ it 'does not keep buffer content if it is longer than offset + result' do
+ n = [ 65, 66, 67 ]
+ buffer = "1234567890"
+ n.pack("@3ccc", buffer: buffer).should == "123ABC"
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/array/permutation_spec.rb b/spec/ruby/core/array/permutation_spec.rb
index 8a80b93c3b..c0eba57a3e 100644
--- a/spec/ruby/core/array/permutation_spec.rb
+++ b/spec/ruby/core/array/permutation_spec.rb
@@ -52,7 +52,7 @@ describe "Array#permutation" do
end
it "returns no permutations when the given length has no permutations" do
- @numbers.permutation(9).entries.size == 0
+ @numbers.permutation(9).entries.size.should == 0
@numbers.permutation(9) { |n| @yielded << n }
@yielded.should == []
end
diff --git a/spec/ruby/core/array/pop_spec.rb b/spec/ruby/core/array/pop_spec.rb
index 313dc4189e..ea649c6585 100644
--- a/spec/ruby/core/array/pop_spec.rb
+++ b/spec/ruby/core/array/pop_spec.rb
@@ -119,7 +119,7 @@ describe "Array#pop" do
a.should == []
end
- it "raises a TypeError when the passed n can be coerced to Integer" do
+ it "raises a TypeError when the passed n cannot be coerced to Integer" do
lambda{ [1, 2].pop("cat") }.should raise_error(TypeError)
lambda{ [1, 2].pop(nil) }.should raise_error(TypeError)
end
diff --git a/spec/ruby/core/array/shift_spec.rb b/spec/ruby/core/array/shift_spec.rb
index e5d25e2050..a7b6f58392 100644
--- a/spec/ruby/core/array/shift_spec.rb
+++ b/spec/ruby/core/array/shift_spec.rb
@@ -104,7 +104,7 @@ describe "Array#shift" do
a.should == []
end
- it "raises a TypeError when the passed n can be coerced to Integer" do
+ it "raises a TypeError when the passed n cannot be coerced to Integer" do
lambda{ [1, 2].shift("cat") }.should raise_error(TypeError)
lambda{ [1, 2].shift(nil) }.should raise_error(TypeError)
end
diff --git a/spec/ruby/core/array/sum_spec.rb b/spec/ruby/core/array/sum_spec.rb
new file mode 100644
index 0000000000..6548655c35
--- /dev/null
+++ b/spec/ruby/core/array/sum_spec.rb
@@ -0,0 +1,44 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+ruby_version_is '2.4' do
+ describe "Array#sum" do
+ it "returns the sum of elements" do
+ [1, 2, 3].sum.should == 6
+ end
+
+ it "applies a block to each element before adding if it's given" do
+ [1, 2, 3].sum { |i| i * 10 }.should == 60
+ end
+
+ it "returns init value if array is empty" do
+ [].sum(-1).should == -1
+ end
+
+ it "returns 0 if array is empty and init is omitted" do
+ [].sum.should == 0
+ end
+
+ it "adds init value to the sum of elemens" do
+ [1, 2, 3].sum(10).should == 16
+ end
+
+ it "can be used for non-numeric objects by providing init value" do
+ ["a", "b", "c"].sum("").should == "abc"
+ end
+
+ it 'raises TypeError if any element are not numeric' do
+ lambda { ["a"].sum }.should raise_error(TypeError)
+ end
+
+ it 'raises TypeError if any element cannot be added to init value' do
+ lambda { [1].sum([]) }.should raise_error(TypeError)
+ end
+
+ it "calls + to sum the elements" do
+ a = mock("a")
+ b = mock("b")
+ a.should_receive(:+).with(b).and_return(42)
+ [b].sum(a).should == 42
+ end
+ end
+end
diff --git a/spec/ruby/core/bignum/bignum_spec.rb b/spec/ruby/core/bignum/bignum_spec.rb
index cf99bb4937..3df43aec2d 100644
--- a/spec/ruby/core/bignum/bignum_spec.rb
+++ b/spec/ruby/core/bignum/bignum_spec.rb
@@ -16,4 +16,16 @@ describe "Bignum" do
Bignum.new
end.should raise_error(NoMethodError)
end
+
+ ruby_version_is '2.4' do
+ it "unified into Integer" do
+ Bignum.should equal(Integer)
+ end
+
+ it "is deprecated" do
+ -> {
+ Bignum
+ }.should complain(/constant ::Bignum is deprecated/)
+ end
+ end
end
diff --git a/spec/ruby/core/complex/finite_spec.rb b/spec/ruby/core/complex/finite_spec.rb
new file mode 100644
index 0000000000..e9ee19bef3
--- /dev/null
+++ b/spec/ruby/core/complex/finite_spec.rb
@@ -0,0 +1,36 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+ruby_version_is "2.4" do
+ describe "Complex#finite?" do
+ it "returns true if magnitude is finite" do
+ (1+1i).finite?.should == true
+ end
+
+ it "returns false for positive infinity" do
+ value = Complex(Float::INFINITY, 42)
+ value.finite?.should == false
+ end
+
+ it "returns false for positive complex with infinite imaginary" do
+ value = Complex(1, Float::INFINITY)
+ value.finite?.should == false
+ end
+
+ it "returns false for negative infinity" do
+ value = -Complex(Float::INFINITY, 42)
+ value.finite?.should == false
+ end
+
+ it "returns false for negative complex with infinite imaginary" do
+ value = -Complex(1, Float::INFINITY)
+ value.finite?.should == false
+ end
+
+ ruby_bug "#14014", "2.4"..."2.5" do
+ it "returns false for NaN" do
+ value = Complex(Float::NAN, Float::NAN)
+ value.finite?.should == false
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/complex/infinite_spec.rb b/spec/ruby/core/complex/infinite_spec.rb
new file mode 100644
index 0000000000..79792c3169
--- /dev/null
+++ b/spec/ruby/core/complex/infinite_spec.rb
@@ -0,0 +1,34 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+ruby_version_is "2.4" do
+ describe "Complex#infinite?" do
+ it "returns nil if magnitude is finite" do
+ (1+1i).infinite?.should == nil
+ end
+
+ it "returns 1 for positive infinity" do
+ value = Complex(Float::INFINITY, 42).infinite?
+ value.should == 1
+ end
+
+ it "returns 1 for positive complex with infinite imaginary" do
+ value = Complex(1, Float::INFINITY).infinite?
+ value.should == 1
+ end
+
+ it "returns -1 for negative infinity" do
+ value = -Complex(Float::INFINITY, 42).infinite?
+ value.should == -1
+ end
+
+ it "returns -1 for negative complex with infinite imaginary" do
+ value = -Complex(1, Float::INFINITY).infinite?
+ value.should == -1
+ end
+
+ it "returns nil for NaN" do
+ value = Complex(0, Float::NAN).infinite?
+ value.should == nil
+ end
+ end
+end
diff --git a/spec/ruby/core/dir/empty_spec.rb b/spec/ruby/core/dir/empty_spec.rb
new file mode 100644
index 0000000000..861a538f84
--- /dev/null
+++ b/spec/ruby/core/dir/empty_spec.rb
@@ -0,0 +1,33 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+ruby_version_is "2.4" do
+ describe "Dir.empty?" do
+ before :all do
+ @empty_dir = tmp("empty_dir")
+ mkdir_p @empty_dir
+ end
+
+ after :all do
+ rm_r @empty_dir
+ end
+
+ it "returns true for empty directories" do
+ result = Dir.empty? @empty_dir
+ result.should be_true
+ end
+
+ it "returns false for non-empty directories" do
+ result = Dir.empty? __dir__
+ result.should be_false
+ end
+
+ it "returns false for a non-directory" do
+ result = Dir.empty? __FILE__
+ result.should be_false
+ end
+
+ it "raises ENOENT for nonexistent directories" do
+ lambda { Dir.empty? tmp("nonexistent") }.should raise_error(Errno::ENOENT)
+ end
+ end
+end
diff --git a/spec/ruby/core/dir/glob_spec.rb b/spec/ruby/core/dir/glob_spec.rb
index b65b738b61..4a9230f8b3 100644
--- a/spec/ruby/core/dir/glob_spec.rb
+++ b/spec/ruby/core/dir/glob_spec.rb
@@ -68,7 +68,7 @@ describe "Dir.glob" do
Dir.glob('**/', File::FNM_DOTMATCH).sort.should == expected
end
- # This is a seperate case to check **/ coming after a constant
+ # This is a separate case to check **/ coming after a constant
# directory as well.
it "recursively matches any subdirectories except './' or '../' with '**/' and option File::FNM_DOTMATCH" do
expected = %w[
diff --git a/spec/ruby/core/encoding/converter/primitive_convert_spec.rb b/spec/ruby/core/encoding/converter/primitive_convert_spec.rb
index b9d6288bb2..ed479c6b13 100644
--- a/spec/ruby/core/encoding/converter/primitive_convert_spec.rb
+++ b/spec/ruby/core/encoding/converter/primitive_convert_spec.rb
@@ -89,7 +89,7 @@ with_feature :encoding do
@ec.primitive_convert("","",nil,nil, {after_output: true}).should == :finished
end
- it "sets the destination buffer's encoding to the destination encoding if the conversion suceeded" do
+ it "sets the destination buffer's encoding to the destination encoding if the conversion succeeded" do
dest = "".force_encoding('utf-8')
dest.encoding.should == Encoding::UTF_8
@ec.primitive_convert("\u{98}",dest).should == :finished
diff --git a/spec/ruby/core/encoding/converter/primitive_errinfo_spec.rb b/spec/ruby/core/encoding/converter/primitive_errinfo_spec.rb
index f92c95c6d5..cba654b9fe 100644
--- a/spec/ruby/core/encoding/converter/primitive_errinfo_spec.rb
+++ b/spec/ruby/core/encoding/converter/primitive_errinfo_spec.rb
@@ -16,15 +16,13 @@ with_feature :encoding do
it "returns [:source_buffer_empty,nil,nil,nil, nil] when #convert last succeeded" do
ec = Encoding::Converter.new('ascii','utf-8')
- ec.convert("a".force_encoding('ascii')).should == "a".\
- force_encoding('utf-8')
+ ec.convert("a".force_encoding('ascii')).should == "a".force_encoding('utf-8')
ec.primitive_errinfo.should == [:source_buffer_empty, nil, nil, nil, nil]
end
it "returns [:destination_buffer_full,nil,nil,nil,nil] when #primitive_convert last returned :destination_buffer_full" do
ec = Encoding::Converter.new("utf-8", "iso-2022-jp")
- ec.primitive_convert("\u{9999}", "", 0, 0, partial_input: false) \
- .should == :destination_buffer_full
+ ec.primitive_convert("\u{9999}", "", 0, 0, partial_input: false).should == :destination_buffer_full
ec.primitive_errinfo.should == [:destination_buffer_full, nil, nil, nil, nil]
end
diff --git a/spec/ruby/core/encoding/converter/putback_spec.rb b/spec/ruby/core/encoding/converter/putback_spec.rb
index 69ce59e89b..3ed1ad9956 100644
--- a/spec/ruby/core/encoding/converter/putback_spec.rb
+++ b/spec/ruby/core/encoding/converter/putback_spec.rb
@@ -40,8 +40,7 @@ with_feature :encoding do
src = "\x00\xd8\x61\x00"
dst = ""
ec.primitive_convert(src, dst).should == :invalid_byte_sequence
- ec.primitive_errinfo.should ==
- [:invalid_byte_sequence, "UTF-16LE", "UTF-8", "\x00\xD8", "a\x00"]
+ ec.primitive_errinfo.should == [:invalid_byte_sequence, "UTF-16LE", "UTF-8", "\x00\xD8", "a\x00"]
ec.putback(1).should == "\x00".force_encoding("utf-16le")
ec.putback.should == "a".force_encoding("utf-16le")
ec.putback.should == ""
diff --git a/spec/ruby/core/encoding/invalid_byte_sequence_error/source_encoding_name_spec.rb b/spec/ruby/core/encoding/invalid_byte_sequence_error/source_encoding_name_spec.rb
index 41320c5207..428b292c68 100644
--- a/spec/ruby/core/encoding/invalid_byte_sequence_error/source_encoding_name_spec.rb
+++ b/spec/ruby/core/encoding/invalid_byte_sequence_error/source_encoding_name_spec.rb
@@ -23,7 +23,7 @@ with_feature :encoding do
# conversion from ISO-8859-1 -> UTF-8 succeeded, but the conversion from
# UTF-8 to EUC-JP failed. IOW, it failed when the source encoding was
# UTF-8, so UTF-8 is regarded as the source encoding.
- it "is equal to the source encoding at the stage of the conversion path where the error occured" do
+ it "is equal to the source encoding at the stage of the conversion path where the error occurred" do
@exception2.source_encoding_name.should == 'UTF-8'
end
end
diff --git a/spec/ruby/core/encoding/invalid_byte_sequence_error/source_encoding_spec.rb b/spec/ruby/core/encoding/invalid_byte_sequence_error/source_encoding_spec.rb
index 75514e5229..09379acc5d 100644
--- a/spec/ruby/core/encoding/invalid_byte_sequence_error/source_encoding_spec.rb
+++ b/spec/ruby/core/encoding/invalid_byte_sequence_error/source_encoding_spec.rb
@@ -28,7 +28,7 @@ with_feature :encoding do
# FIXME: Derive example where the failure occurs at the UTF-8 ->
# ISO-8859-1 case so as to better illustrate the issue
- it "is equal to the source encoding at the stage of the conversion path where the error occured" do
+ it "is equal to the source encoding at the stage of the conversion path where the error occurred" do
@exception2.source_encoding.should == Encoding::EUC_JP
end
end
diff --git a/spec/ruby/core/encoding/undefined_conversion_error/source_encoding_name_spec.rb b/spec/ruby/core/encoding/undefined_conversion_error/source_encoding_name_spec.rb
index 4a7aba2044..742184250f 100644
--- a/spec/ruby/core/encoding/undefined_conversion_error/source_encoding_name_spec.rb
+++ b/spec/ruby/core/encoding/undefined_conversion_error/source_encoding_name_spec.rb
@@ -23,7 +23,7 @@ with_feature :encoding do
# conversion from ISO-8859-1 -> UTF-8 succeeded, but the conversion from
# UTF-8 to EUC-JP failed. IOW, it failed when the source encoding was
# UTF-8, so UTF-8 is regarded as the source encoding.
- it "is equal to the source encoding at the stage of the conversion path where the error occured" do
+ it "is equal to the source encoding at the stage of the conversion path where the error occurred" do
@exception2.source_encoding_name.should == 'UTF-8'
end
end
diff --git a/spec/ruby/core/encoding/undefined_conversion_error/source_encoding_spec.rb b/spec/ruby/core/encoding/undefined_conversion_error/source_encoding_spec.rb
index 984862646c..0489ad82bf 100644
--- a/spec/ruby/core/encoding/undefined_conversion_error/source_encoding_spec.rb
+++ b/spec/ruby/core/encoding/undefined_conversion_error/source_encoding_spec.rb
@@ -24,7 +24,7 @@ with_feature :encoding do
# conversion from ISO-8859-1 -> UTF-8 succeeded, but the conversion from
# UTF-8 to EUC-JP failed. IOW, it failed when the source encoding was
# UTF-8, so UTF-8 is regarded as the source encoding.
- it "is equal to the source encoding at the stage of the conversion path where the error occured" do
+ it "is equal to the source encoding at the stage of the conversion path where the error occurred" do
@exception2.source_encoding.should == Encoding::UTF_8
end
end
diff --git a/spec/ruby/core/enumerable/any_spec.rb b/spec/ruby/core/enumerable/any_spec.rb
index 4f7af68b07..4a7511f649 100644
--- a/spec/ruby/core/enumerable/any_spec.rb
+++ b/spec/ruby/core/enumerable/any_spec.rb
@@ -68,11 +68,11 @@ describe "Enumerable#any?" do
describe "with block" do
it "returns true if the block ever returns other than false or nil" do
- @enum.any? { true } == true
- @enum.any? { 0 } == true
- @enum.any? { 1 } == true
+ @enum.any? { true }.should == true
+ @enum.any? { 0 }.should == true
+ @enum.any? { 1 }.should == true
- @enum1.any? { Object.new } == true
+ @enum1.any? { Object.new }.should == true
@enum1.any?{ |o| o < 1 }.should == true
@enum1.any?{ |o| 5 }.should == true
diff --git a/spec/ruby/core/enumerable/cycle_spec.rb b/spec/ruby/core/enumerable/cycle_spec.rb
index 2f5760992d..9089a94963 100644
--- a/spec/ruby/core/enumerable/cycle_spec.rb
+++ b/spec/ruby/core/enumerable/cycle_spec.rb
@@ -69,7 +69,7 @@ describe "Enumerable#cycle" do
enum.cycle(obj).to_a.should == [3, 2, 1, 3, 2, 1]
end
- it "raises a TypeError when the passed n can be coerced to Integer" do
+ it "raises a TypeError when the passed n cannot be coerced to Integer" do
enum = EnumerableSpecs::Numerous.new
lambda{ enum.cycle("cat"){} }.should raise_error(TypeError)
end
diff --git a/spec/ruby/core/enumerable/drop_spec.rb b/spec/ruby/core/enumerable/drop_spec.rb
index 1bcdc0ee9a..4013a639ce 100644
--- a/spec/ruby/core/enumerable/drop_spec.rb
+++ b/spec/ruby/core/enumerable/drop_spec.rb
@@ -34,7 +34,7 @@ describe "Enumerable#drop" do
EnumerableSpecs::Numerous.new(3, 2, 1, :go).drop(4).should == []
end
- it "raises a TypeError when the passed n can be coerced to Integer" do
+ it "raises a TypeError when the passed n cannot be coerced to Integer" do
lambda{ @enum.drop("hat") }.should raise_error(TypeError)
lambda{ @enum.drop(nil) }.should raise_error(TypeError)
end
diff --git a/spec/ruby/core/enumerable/uniq_spec.rb b/spec/ruby/core/enumerable/uniq_spec.rb
index 0ede0170ce..5ca7556aed 100644
--- a/spec/ruby/core/enumerable/uniq_spec.rb
+++ b/spec/ruby/core/enumerable/uniq_spec.rb
@@ -7,6 +7,71 @@ ruby_version_is '2.4' do
[0, 1, 2, 3].to_enum.uniq { |n| n.even? }.should == [0, 1]
end
+ it "uses eql? semantics" do
+ [1.0, 1].to_enum.uniq.should == [1.0, 1]
+ end
+
+ it "compares elements first with hash" do
+ x = mock('0')
+ x.should_receive(:hash).at_least(1).and_return(0)
+ y = mock('0')
+ y.should_receive(:hash).at_least(1).and_return(0)
+
+ [x, y].to_enum.uniq.should == [x, y]
+ end
+
+ it "does not compare elements with different hash codes via eql?" do
+ x = mock('0')
+ x.should_not_receive(:eql?)
+ y = mock('1')
+ y.should_not_receive(:eql?)
+
+ x.should_receive(:hash).at_least(1).and_return(0)
+ y.should_receive(:hash).at_least(1).and_return(1)
+
+ [x, y].to_enum.uniq.should == [x, y]
+ end
+
+ it "compares elements with matching hash codes with #eql?" do
+ a = Array.new(2) do
+ obj = mock('0')
+ obj.should_receive(:hash).at_least(1).and_return(0)
+
+ def obj.eql?(o)
+ # It's undefined whether the impl does a[0].eql?(a[1]) or
+ # a[1].eql?(a[0]) so we taint both.
+ taint
+ o.taint
+ false
+ end
+
+ obj
+ end
+
+ a.uniq.should == a
+ a[0].tainted?.should == true
+ a[1].tainted?.should == true
+
+ a = Array.new(2) do
+ obj = mock('0')
+ obj.should_receive(:hash).at_least(1).and_return(0)
+
+ def obj.eql?(o)
+ # It's undefined whether the impl does a[0].eql?(a[1]) or
+ # a[1].eql?(a[0]) so we taint both.
+ taint
+ o.taint
+ true
+ end
+
+ obj
+ end
+
+ a.to_enum.uniq.size.should == 1
+ a[0].tainted?.should == true
+ a[1].tainted?.should == true
+ end
+
context 'when yielded with multiple arguments' do
before :each do
@enum = Object.new.to_enum
diff --git a/spec/ruby/core/enumerator/lazy/force_spec.rb b/spec/ruby/core/enumerator/lazy/force_spec.rb
index 03ff9a0fb6..1a218c1b0f 100644
--- a/spec/ruby/core/enumerator/lazy/force_spec.rb
+++ b/spec/ruby/core/enumerator/lazy/force_spec.rb
@@ -24,7 +24,7 @@ describe "Enumerator::Lazy#force" do
(0..Float::INFINITY).lazy.map(&:succ).take(2).force.should == [1, 2]
@eventsmixed.take(1).map(&:succ).force.should == [1]
- ScratchPad.recorded == [:after_yields]
+ ScratchPad.recorded.should == [:before_yield]
end
end
end
diff --git a/spec/ruby/core/false/dup_spec.rb b/spec/ruby/core/false/dup_spec.rb
new file mode 100644
index 0000000000..b04e641a41
--- /dev/null
+++ b/spec/ruby/core/false/dup_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+ruby_version_is '2.4' do
+ describe "FalseClass#dup" do
+ it "returns self" do
+ false.dup.should equal(false)
+ end
+ end
+end
diff --git a/spec/ruby/core/file/empty_spec.rb b/spec/ruby/core/file/empty_spec.rb
new file mode 100644
index 0000000000..766aa95e46
--- /dev/null
+++ b/spec/ruby/core/file/empty_spec.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../../../shared/file/zero', __FILE__)
+
+describe "File.empty?" do
+ ruby_version_is "2.4" do
+ it_behaves_like :file_zero, :empty?, File
+ it_behaves_like :file_zero_missing, :empty?, File
+
+ platform_is :solaris do
+ it "returns false for /dev/null" do
+ File.empty?('/dev/null').should == true
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/file/readlink_spec.rb b/spec/ruby/core/file/readlink_spec.rb
index 6db2c09780..b529cd1355 100644
--- a/spec/ruby/core/file/readlink_spec.rb
+++ b/spec/ruby/core/file/readlink_spec.rb
@@ -3,7 +3,7 @@ require File.expand_path('../../../spec_helper', __FILE__)
describe "File.readlink" do
# symlink/readlink are not supported on Windows
platform_is_not :windows do
- describe "File.readlink with absolute paths" do
+ describe "with absolute paths" do
before :each do
@file = tmp('file_readlink.txt')
@link = tmp('file_readlink.lnk')
@@ -35,7 +35,26 @@ describe "File.readlink" do
end
end
- describe "File.readlink when changing the working directory" do
+ describe "with paths containing unicode characters" do
+ before :each do
+ @file = tmp('tàrget.txt')
+ @link = tmp('lïnk.lnk')
+ File.symlink(@file, @link)
+ end
+
+ after :each do
+ rm_r @file, @link
+ end
+
+ it "returns the name of the file referenced by the given link" do
+ touch @file
+ result = File.readlink(@link)
+ result.encoding.should equal Encoding.find('filesystem')
+ result.should == @file.dup.force_encoding(Encoding.find('filesystem'))
+ end
+ end
+
+ describe "when changing the working directory" do
before :each do
@cwd = Dir.pwd
@tmpdir = tmp("/readlink")
diff --git a/spec/ruby/core/file/shared/fnmatch.rb b/spec/ruby/core/file/shared/fnmatch.rb
index 80e37b3fff..9b423ae47e 100644
--- a/spec/ruby/core/file/shared/fnmatch.rb
+++ b/spec/ruby/core/file/shared/fnmatch.rb
@@ -75,11 +75,11 @@ describe :file_fnmatch, shared: true do
File.send(@method, 'c*t', 'c/a/b/t').should == true
end
- it "matches ranges of characters using bracket expresions (e.g. [a-z])" do
+ it "matches ranges of characters using bracket expression (e.g. [a-z])" do
File.send(@method, 'ca[a-z]', 'cat').should == true
end
- it "matches ranges of characters using bracket expresions, taking case into account" do
+ it "matches ranges of characters using bracket expression, taking case into account" do
File.send(@method, '[a-z]', 'D').should == false
File.send(@method, '[^a-z]', 'D').should == true
File.send(@method, '[A-Z]', 'd').should == false
@@ -92,7 +92,7 @@ describe :file_fnmatch, shared: true do
File.send(@method, '/ca[s][s-t]/rul[a-b]/[z]he/[x-Z]orld', '/cats/rule/the/World').should == false
end
- it "matches ranges of characters using exclusive bracket expresions (e.g. [^t] or [!t])" do
+ it "matches ranges of characters using exclusive bracket expression (e.g. [^t] or [!t])" do
File.send(@method, 'ca[^t]', 'cat').should == false
File.send(@method, 'ca[!t]', 'cat').should == false
end
@@ -106,13 +106,13 @@ describe :file_fnmatch, shared: true do
end
platform_is_not :windows do
- it "doesn't match case sensitive characters on platfroms with case sensitive paths, when flags include FNM_SYSCASE" do
+ it "doesn't match case sensitive characters on platforms with case sensitive paths, when flags include FNM_SYSCASE" do
File.send(@method, 'cat', 'CAT', File::FNM_SYSCASE).should == false
end
end
platform_is :windows do
- it "matches case sensitive characters on platfroms with case insensitive paths, when flags include FNM_SYSCASE" do
+ it "matches case sensitive characters on platforms with case insensitive paths, when flags include FNM_SYSCASE" do
File.send(@method, 'cat', 'CAT', File::FNM_SYSCASE).should == true
end
end
diff --git a/spec/ruby/core/fixnum/fixnum_spec.rb b/spec/ruby/core/fixnum/fixnum_spec.rb
index 8a050fd25e..7f72f95e94 100644
--- a/spec/ruby/core/fixnum/fixnum_spec.rb
+++ b/spec/ruby/core/fixnum/fixnum_spec.rb
@@ -16,4 +16,16 @@ describe "Fixnum" do
Fixnum.new
end.should raise_error(NoMethodError)
end
+
+ ruby_version_is '2.4' do
+ it "is unified into Integer" do
+ Fixnum.should equal(Integer)
+ end
+
+ it "is deprecated" do
+ -> {
+ Fixnum
+ }.should complain(/constant ::Fixnum is deprecated/)
+ end
+ end
end
diff --git a/spec/ruby/core/float/ceil_spec.rb b/spec/ruby/core/float/ceil_spec.rb
index 8037164c68..f1d9dcd823 100644
--- a/spec/ruby/core/float/ceil_spec.rb
+++ b/spec/ruby/core/float/ceil_spec.rb
@@ -10,4 +10,14 @@ describe "Float#ceil" do
-9223372036854775808.1.ceil.should eql(-9223372036854775808)
+9223372036854775808.1.ceil.should eql(+9223372036854775808)
end
+
+ ruby_version_is "2.4" do
+ it "returns the smallest number greater than or equal to self with an optionally given precision" do
+ 2.1679.ceil(0).should eql(3)
+ 214.94.ceil(-1).should eql(220)
+ 7.0.ceil(1).should eql(7.0)
+ -1.234.ceil(2).should eql(-1.23)
+ 5.123812.ceil(4).should eql(5.1239)
+ end
+ end
end
diff --git a/spec/ruby/core/float/dup_spec.rb b/spec/ruby/core/float/dup_spec.rb
new file mode 100644
index 0000000000..775dc2913c
--- /dev/null
+++ b/spec/ruby/core/float/dup_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+ruby_version_is '2.4' do
+ describe "Float#dup" do
+ it "returns self" do
+ float = 2.4
+ float.dup.should equal(float)
+ end
+ end
+end
diff --git a/spec/ruby/core/float/floor_spec.rb b/spec/ruby/core/float/floor_spec.rb
index 63a5138366..6da5d5c5ee 100644
--- a/spec/ruby/core/float/floor_spec.rb
+++ b/spec/ruby/core/float/floor_spec.rb
@@ -10,4 +10,14 @@ describe "Float#floor" do
-9223372036854775808.1.floor.should eql(-9223372036854775808)
+9223372036854775808.1.floor.should eql(+9223372036854775808)
end
+
+ ruby_version_is "2.4" do
+ it "returns the largest number less than or equal to self with an optionally given precision" do
+ 2.1679.floor(0).should eql(2)
+ 214.94.floor(-1).should eql(210)
+ 7.0.floor(1).should eql(7.0)
+ -1.234.floor(2).should eql(-1.24)
+ 5.123812.floor(4).should eql(5.1238)
+ end
+ end
end
diff --git a/spec/ruby/core/float/round_spec.rb b/spec/ruby/core/float/round_spec.rb
index 46d23b36d0..56668d5856 100644
--- a/spec/ruby/core/float/round_spec.rb
+++ b/spec/ruby/core/float/round_spec.rb
@@ -84,4 +84,18 @@ describe "Float#round" do
-2.5e200.round(-200).should eql( -3 * 10 ** 200 )
-2.4e200.round(-200).should eql( -2 * 10 ** 200 )
end
+
+ ruby_version_is "2.4" do
+ it "returns different rounded values depending on the half option" do
+ 2.5.round(half: :up).should eql(3)
+ 2.5.round(half: :down).should eql(2)
+ 2.5.round(half: :even).should eql(2)
+ 3.5.round(half: :up).should eql(4)
+ 3.5.round(half: :down).should eql(3)
+ 3.5.round(half: :even).should eql(4)
+ (-2.5).round(half: :up).should eql(-3)
+ (-2.5).round(half: :down).should eql(-2)
+ (-2.5).round(half: :even).should eql(-2)
+ end
+ end
end
diff --git a/spec/ruby/core/float/truncate_spec.rb b/spec/ruby/core/float/truncate_spec.rb
index 85ee8ef580..7feeb81735 100644
--- a/spec/ruby/core/float/truncate_spec.rb
+++ b/spec/ruby/core/float/truncate_spec.rb
@@ -3,4 +3,14 @@ require File.expand_path('../shared/to_i', __FILE__)
describe "Float#truncate" do
it_behaves_like(:float_to_i, :truncate)
+
+ ruby_version_is "2.4" do
+ it "returns self truncated to an optionally given precision" do
+ 2.1679.truncate(0).should eql(2)
+ 7.1.truncate(1).should eql(7.1)
+ 214.94.truncate(-1).should eql(210)
+ -1.234.truncate(2).should eql(-1.23)
+ 5.123812.truncate(4).should eql(5.1238)
+ end
+ end
end
diff --git a/spec/ruby/core/hash/delete_spec.rb b/spec/ruby/core/hash/delete_spec.rb
index a45b8cd171..a41fad3586 100644
--- a/spec/ruby/core/hash/delete_spec.rb
+++ b/spec/ruby/core/hash/delete_spec.rb
@@ -11,13 +11,13 @@ describe "Hash#delete" do
it "calls supplied block if the key is not found" do
{ a: 1, b: 10, c: 100 }.delete(:d) { 5 }.should == 5
Hash.new(:default).delete(:d) { 5 }.should == 5
- Hash.new { :defualt }.delete(:d) { 5 }.should == 5
+ Hash.new { :default }.delete(:d) { 5 }.should == 5
end
it "returns nil if the key is not found when no block is given" do
{ a: 1, b: 10, c: 100 }.delete(:d).should == nil
Hash.new(:default).delete(:d).should == nil
- Hash.new { :defualt }.delete(:d).should == nil
+ Hash.new { :default }.delete(:d).should == nil
end
# MRI explicitly implements this behavior
diff --git a/spec/ruby/core/hash/transform_values_spec.rb b/spec/ruby/core/hash/transform_values_spec.rb
index 7e4ff45bea..0c9e43d621 100644
--- a/spec/ruby/core/hash/transform_values_spec.rb
+++ b/spec/ruby/core/hash/transform_values_spec.rb
@@ -24,6 +24,15 @@ ruby_version_is "2.4" do
enumerator.each(&:succ).should == { a: 2, b: 3, c: 4 }
end
end
+
+ it "returns a Hash instance, even on subclasses" do
+ klass = Class.new(Hash)
+ h = klass.new
+ h[:foo] = 42
+ r = h.transform_values{|v| 2 * v}
+ r[:foo].should == 84
+ r.class.should == Hash
+ end
end
describe "Hash#transform_values!" do
@@ -41,6 +50,14 @@ ruby_version_is "2.4" do
@hash.should == { a: 2, b: 3, c: 4 }
end
+ it "partially modifies the contents if we broke from the block" do
+ @hash.transform_values! do |v|
+ break if v == 3
+ 100 + v
+ end
+ @hash.should == { a: 101, b: 102, c: 3}
+ end
+
context "when no block is given" do
it "returns a sized Enumerator" do
enumerator = @hash.transform_values!
@@ -56,6 +73,10 @@ ruby_version_is "2.4" do
@hash.freeze
end
+ it "raises a RuntimeError on an empty hash" do
+ ->{ {}.freeze.transform_values!(&:succ) }.should raise_error(RuntimeError)
+ end
+
it "keeps pairs and raises a RuntimeError" do
->{ @hash.transform_values!(&:succ) }.should raise_error(RuntimeError)
@hash.should == @initial_pairs
diff --git a/spec/ruby/core/integer/ceil_spec.rb b/spec/ruby/core/integer/ceil_spec.rb
index 7a49ede0df..31c56f378d 100644
--- a/spec/ruby/core/integer/ceil_spec.rb
+++ b/spec/ruby/core/integer/ceil_spec.rb
@@ -1,6 +1,21 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../shared/to_i', __FILE__)
+require File.expand_path('../shared/integer_rounding', __FILE__)
describe "Integer#ceil" do
it_behaves_like(:integer_to_i, :ceil)
+ it_behaves_like(:integer_rounding_positive_precision, :ceil)
+
+ ruby_version_is "2.4" do
+ context "precision argument specified as part of the ceil method is negative" do
+ it "returns the smallest integer greater than self with at least precision.abs trailing zeros" do
+ 18.ceil(-1).should eql(20)
+ 18.ceil(-2).should eql(100)
+ 18.ceil(-3).should eql(1000)
+ -1832.ceil(-1).should eql(-1830)
+ -1832.ceil(-2).should eql(-1800)
+ -1832.ceil(-3).should eql(-1000)
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/integer/digits_spec.rb b/spec/ruby/core/integer/digits_spec.rb
new file mode 100644
index 0000000000..3546a654eb
--- /dev/null
+++ b/spec/ruby/core/integer/digits_spec.rb
@@ -0,0 +1,34 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+ruby_version_is "2.4" do
+ describe "Integer#digits" do
+ it "returns an array of place values in base-10 by default" do
+ 12345.digits.should == [5,4,3,2,1]
+ end
+
+ it "returns digits by place value of a given radix" do
+ 12345.digits(7).should == [4,6,6,0,5]
+ end
+
+ it "converts the radix with #to_int" do
+ 12345.digits(mock_int(2)).should == [1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1]
+ end
+
+ it "returns [0] when called on 0, regardless of base" do
+ 0.digits.should == [0]
+ 0.digits(7).should == [0]
+ end
+
+ it "raises ArgumentError when calling with a radix less than 2" do
+ lambda { 12345.digits(1) }.should raise_error(ArgumentError)
+ end
+
+ it "raises ArgumentError when calling with a negative radix" do
+ lambda { 12345.digits(-2) }.should raise_error(ArgumentError)
+ end
+
+ it "raises Math::DomainError when calling digits on a negative number" do
+ lambda { -12345.digits(7) }.should raise_error(Math::DomainError)
+ end
+ end
+end
diff --git a/spec/ruby/core/integer/dup_spec.rb b/spec/ruby/core/integer/dup_spec.rb
new file mode 100644
index 0000000000..f46bdf89bd
--- /dev/null
+++ b/spec/ruby/core/integer/dup_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+ruby_version_is '2.4' do
+ describe "Integer#dup" do
+ it "returns self" do
+ int = 2
+ int.dup.should equal(int)
+ end
+ end
+end
diff --git a/spec/ruby/core/integer/floor_spec.rb b/spec/ruby/core/integer/floor_spec.rb
index b533a84ad4..9babcd9a3e 100644
--- a/spec/ruby/core/integer/floor_spec.rb
+++ b/spec/ruby/core/integer/floor_spec.rb
@@ -1,6 +1,21 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../shared/to_i', __FILE__)
+require File.expand_path('../shared/integer_rounding', __FILE__)
describe "Integer#floor" do
it_behaves_like(:integer_to_i, :floor)
+ it_behaves_like(:integer_rounding_positive_precision, :floor)
+
+ ruby_version_is "2.4" do
+ context "precision argument specified as part of the floor method is negative" do
+ it "returns the largest integer less than self with at least precision.abs trailing zeros" do
+ 1832.floor(-1).should eql(1830)
+ 1832.floor(-2).should eql(1800)
+ 1832.floor(-3).should eql(1000)
+ -1832.floor(-1).should eql(-1840)
+ -1832.floor(-2).should eql(-1900)
+ -1832.floor(-3).should eql(-2000)
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/integer/integer_spec.rb b/spec/ruby/core/integer/integer_spec.rb
index a6f406cba0..393f072563 100644
--- a/spec/ruby/core/integer/integer_spec.rb
+++ b/spec/ruby/core/integer/integer_spec.rb
@@ -4,6 +4,13 @@ describe "Integer" do
it "includes Comparable" do
Integer.include?(Comparable).should == true
end
+
+ ruby_version_is "2.4" do
+ it "is the class of both small and large integers" do
+ 42.class.should equal(Integer)
+ bignum_value.class.should equal(Integer)
+ end
+ end
end
describe "Integer#integer?" do
diff --git a/spec/ruby/core/integer/round_spec.rb b/spec/ruby/core/integer/round_spec.rb
index 5cc9aa3881..5a46e6cba6 100644
--- a/spec/ruby/core/integer/round_spec.rb
+++ b/spec/ruby/core/integer/round_spec.rb
@@ -1,10 +1,12 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../shared/to_i', __FILE__)
+require File.expand_path('../shared/integer_rounding', __FILE__)
describe "Integer#round" do
it_behaves_like(:integer_to_i, :round)
+ it_behaves_like(:integer_rounding_positive_precision, :round)
- ruby_version_is ""..."2.5" do
+ ruby_version_is ""..."2.5" do # Not just since 2.4
it "rounds itself as a float if passed a positive precision" do
[2, -4, 10**70, -10**100].each do |v|
v.round(42).should eql(v.to_f)
@@ -12,20 +14,6 @@ describe "Integer#round" do
end
end
- ruby_version_is "2.5" do
- it "returns itself if passed a positive precision" do
- [2, -4, 10**70, -10**100].each do |v|
- v.round(42).should eql(v)
- end
- end
- end
-
- it "returns itself if passed zero" do
- [2, -4, 10**70, -10**100].each do |v|
- v.round(0).should eql(v)
- end
- end
-
# redmine:5228
it "returns itself rounded if passed a negative value" do
+249.round(-2).should eql(+200)
@@ -74,4 +62,34 @@ describe "Integer#round" do
obj.stub!(:to_int).and_return([])
lambda { 42.round(obj) }.should raise_error(TypeError)
end
+
+ ruby_version_is "2.4" do
+ it "returns different rounded values depending on the half option" do
+ 25.round(-1, half: :up).should eql(30)
+ 25.round(-1, half: :down).should eql(20)
+ 25.round(-1, half: :even).should eql(20)
+ 35.round(-1, half: :up).should eql(40)
+ 35.round(-1, half: :down).should eql(30)
+ 35.round(-1, half: :even).should eql(40)
+ (-25).round(-1, half: :up).should eql(-30)
+ (-25).round(-1, half: :down).should eql(-20)
+ (-25).round(-1, half: :even).should eql(-20)
+ end
+ end
+
+ ruby_version_is "2.4"..."2.5" do
+ it "returns itself as a float if passed a positive precision and the half option" do
+ 35.round(1, half: :up).should eql(35.0)
+ 35.round(1, half: :down).should eql(35.0)
+ 35.round(1, half: :even).should eql(35.0)
+ end
+ end
+
+ ruby_version_is "2.5" do
+ it "returns itself if passed a positive precision and the half option" do
+ 35.round(1, half: :up).should eql(35)
+ 35.round(1, half: :down).should eql(35)
+ 35.round(1, half: :even).should eql(35)
+ end
+ end
end
diff --git a/spec/ruby/core/integer/shared/integer_rounding.rb b/spec/ruby/core/integer/shared/integer_rounding.rb
new file mode 100644
index 0000000000..ecbda1bb4a
--- /dev/null
+++ b/spec/ruby/core/integer/shared/integer_rounding.rb
@@ -0,0 +1,31 @@
+describe :integer_rounding_positive_precision, shared: true do
+ it "returns self if not passed a precision" do
+ [2, -4, 10**70, -10**100].each do |v|
+ v.send(@method).should eql(v)
+ end
+ end
+
+ ruby_version_is "2.4" do
+ it "returns self if passed a precision of zero" do
+ [2, -4, 10**70, -10**100].each do |v|
+ v.send(@method, 0).should eql(v)
+ end
+ end
+ end
+
+ ruby_version_is "2.4"..."2.5" do
+ it "returns itself as a float if passed a positive precision" do
+ [2, -4, 10**70, -10**100].each do |v|
+ v.send(@method, 42).should eql(v.to_f)
+ end
+ end
+ end
+
+ ruby_version_is "2.5" do
+ it "returns itself if passed a positive precision" do
+ [2, -4, 10**70, -10**100].each do |v|
+ v.send(@method, 42).should eql(v)
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/integer/sqrt_spec.rb b/spec/ruby/core/integer/sqrt_spec.rb
new file mode 100644
index 0000000000..b7d9ef441b
--- /dev/null
+++ b/spec/ruby/core/integer/sqrt_spec.rb
@@ -0,0 +1,33 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+ruby_version_is "2.5" do
+ describe "Integer.sqrt" do
+ it "returns an integer" do
+ Integer.sqrt(10).should be_kind_of(Integer)
+ end
+
+ it "returns the integer square root of the argument" do
+ Integer.sqrt(0).should == 0
+ Integer.sqrt(1).should == 1
+ Integer.sqrt(24).should == 4
+ Integer.sqrt(25).should == 5
+ Integer.sqrt(10**400).should == 10**200
+ end
+
+ it "raises a Math::DomainError if the argument is negative" do
+ lambda { Integer.sqrt(-4) }.should raise_error(Math::DomainError)
+ end
+
+ it "accepts any argument that can be coerced to Integer" do
+ Integer.sqrt(10.0).should == 3
+ end
+
+ it "converts the argument with #to_int" do
+ Integer.sqrt(mock_int(10)).should == 3
+ end
+
+ it "raises a TypeError if the argument cannot be coerced to Integer" do
+ lambda { Integer.sqrt("test") }.should raise_error(TypeError)
+ end
+ end
+end
diff --git a/spec/ruby/core/integer/truncate_spec.rb b/spec/ruby/core/integer/truncate_spec.rb
index b503b1e4e8..429ab1a312 100644
--- a/spec/ruby/core/integer/truncate_spec.rb
+++ b/spec/ruby/core/integer/truncate_spec.rb
@@ -1,6 +1,21 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../shared/to_i', __FILE__)
+require File.expand_path('../shared/integer_rounding', __FILE__)
describe "Integer#truncate" do
it_behaves_like(:integer_to_i, :truncate)
+ it_behaves_like(:integer_rounding_positive_precision, :truncate)
+
+ ruby_version_is "2.4" do
+ context "precision argument specified as part of the truncate method is negative" do
+ it "returns an integer with at least precision.abs trailing zeros" do
+ 1832.truncate(-1).should eql(1830)
+ 1832.truncate(-2).should eql(1800)
+ 1832.truncate(-3).should eql(1000)
+ -1832.truncate(-1).should eql(-1830)
+ -1832.truncate(-2).should eql(-1800)
+ -1832.truncate(-3).should eql(-1000)
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/io/advise_spec.rb b/spec/ruby/core/io/advise_spec.rb
index 460b50a59d..44cd32df94 100644
--- a/spec/ruby/core/io/advise_spec.rb
+++ b/spec/ruby/core/io/advise_spec.rb
@@ -17,7 +17,7 @@ describe "IO#advise" do
}.should raise_error(TypeError)
end
- it "raises a TypeError if offsert cannot be coerced to an Integer" do
+ it "raises a TypeError if offset cannot be coerced to an Integer" do
lambda {
@io.advise(:normal, "wat")
}.should raise_error(TypeError)
diff --git a/spec/ruby/core/io/fixtures/classes.rb b/spec/ruby/core/io/fixtures/classes.rb
index fb431d5023..a771e3d929 100644
--- a/spec/ruby/core/io/fixtures/classes.rb
+++ b/spec/ruby/core/io/fixtures/classes.rb
@@ -20,6 +20,18 @@ module IOSpecs
"Here is line six.\n" ]
end
+ def self.lines_without_newline_characters
+ [ "Voici la ligne une.",
+ "Qui \303\250 la linea due.",
+ "",
+ "",
+ "Aqu\303\255 est\303\241 la l\303\255nea tres.",
+ "Hier ist Zeile vier.",
+ "",
+ "Est\303\241 aqui a linha cinco.",
+ "Here is line six." ]
+ end
+
def self.lines_limit
[ "Voici la l",
"igne une.\n",
diff --git a/spec/ruby/core/io/gets_spec.rb b/spec/ruby/core/io/gets_spec.rb
index d984e795c2..6e0518b512 100644
--- a/spec/ruby/core/io/gets_spec.rb
+++ b/spec/ruby/core/io/gets_spec.rb
@@ -138,6 +138,14 @@ describe "IO#gets" do
end
end
end
+
+ ruby_version_is "2.4" do
+ describe "when passed chomp" do
+ it "returns the first line without a trailing newline character" do
+ @io.gets(chomp: true).should == IOSpecs.lines_without_newline_characters[0]
+ end
+ end
+ end
end
describe "IO#gets" do
@@ -191,7 +199,7 @@ describe "IO#gets" do
@io.gets(obj, 5).should == "one\n"
end
- it "reads to the default seperator when passed a single argument greater than the number of bytes to the separator" do
+ it "reads to the default separator when passed a single argument greater than the number of bytes to the separator" do
@io.gets(6).should == "one\n"
end
diff --git a/spec/ruby/core/io/readline_spec.rb b/spec/ruby/core/io/readline_spec.rb
index 39706948eb..a1cddafe5c 100644
--- a/spec/ruby/core/io/readline_spec.rb
+++ b/spec/ruby/core/io/readline_spec.rb
@@ -42,4 +42,12 @@ describe "IO#readline" do
$_.should == line
end
end
+
+ ruby_version_is "2.4" do
+ describe "when passed chomp" do
+ it "returns the first line without a trailing newline character" do
+ @io.readline(chomp: true).should == IOSpecs.lines_without_newline_characters[0]
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/io/shared/each.rb b/spec/ruby/core/io/shared/each.rb
index dc07434ecd..d87303b54a 100644
--- a/spec/ruby/core/io/shared/each.rb
+++ b/spec/ruby/core/io/shared/each.rb
@@ -114,6 +114,15 @@ describe :io_each, shared: true do
ScratchPad.recorded.should == IOSpecs.paragraphs
end
end
+
+ ruby_version_is "2.4" do
+ describe "when passed chomp" do
+ it "yields each line without trailing newline characters to the passed block" do
+ @io.send(@method, chomp: true) { |s| ScratchPad << s }
+ ScratchPad.recorded.should == IOSpecs.lines_without_newline_characters
+ end
+ end
+ end
end
describe :io_each_default_separator, shared: true do
diff --git a/spec/ruby/core/io/shared/readlines.rb b/spec/ruby/core/io/shared/readlines.rb
index 4cb821274a..f545d8876a 100644
--- a/spec/ruby/core/io/shared/readlines.rb
+++ b/spec/ruby/core/io/shared/readlines.rb
@@ -17,6 +17,13 @@ describe :io_readlines, shared: true do
result = IO.send(@method, @name, "", &@object)
(result ? result : ScratchPad.recorded).should == IOSpecs.lines_empty_separator
end
+
+ ruby_version_is "2.4" do
+ it "yields a sequence of lines without trailing newline characters when chomp is passed" do
+ result = IO.send(@method, @name, chomp: true, &@object)
+ (result ? result : ScratchPad.recorded).should == IOSpecs.lines_without_newline_characters
+ end
+ end
end
describe :io_readlines_options_19, shared: true do
diff --git a/spec/ruby/core/kernel/equal_value_spec.rb b/spec/ruby/core/kernel/equal_value_spec.rb
index 670987ead2..a66493f283 100644
--- a/spec/ruby/core/kernel/equal_value_spec.rb
+++ b/spec/ruby/core/kernel/equal_value_spec.rb
@@ -7,9 +7,9 @@ describe "Kernel#==" do
o2 = mock('o2')
(o1 == o1).should == true
(o2 == o2).should == true
- (o1 == o2).should== false
+ (o1 == o2).should == false
(nil == nil).should == true
- (o1 == nil).should== false
- (nil == o2).should== false
+ (o1 == nil).should == false
+ (nil == o2).should == false
end
end
diff --git a/spec/ruby/core/main/fixtures/classes.rb b/spec/ruby/core/main/fixtures/classes.rb
index 0b74080492..6aba948ce0 100644
--- a/spec/ruby/core/main/fixtures/classes.rb
+++ b/spec/ruby/core/main/fixtures/classes.rb
@@ -4,8 +4,11 @@ module MainSpecs
module WrapIncludeModule
end
+
+ DATA = {}
end
+
def main_public_method
end
public :main_public_method
diff --git a/spec/ruby/core/main/fixtures/string_refinement.rb b/spec/ruby/core/main/fixtures/string_refinement.rb
new file mode 100644
index 0000000000..2dc6de52ca
--- /dev/null
+++ b/spec/ruby/core/main/fixtures/string_refinement.rb
@@ -0,0 +1,7 @@
+module StringRefinement
+ refine(String) do
+ def foo
+ 'foo'
+ end
+ end
+end
diff --git a/spec/ruby/core/main/fixtures/string_refinement_user.rb b/spec/ruby/core/main/fixtures/string_refinement_user.rb
new file mode 100644
index 0000000000..48620c325f
--- /dev/null
+++ b/spec/ruby/core/main/fixtures/string_refinement_user.rb
@@ -0,0 +1,11 @@
+using StringRefinement
+
+module MainSpecs
+ DATA[:in_module] = 'hello'.foo
+
+ def self.call_foo(x)
+ x.foo
+ end
+end
+
+MainSpecs::DATA[:toplevel] = 'hello'.foo
diff --git a/spec/ruby/core/main/using_spec.rb b/spec/ruby/core/main/using_spec.rb
new file mode 100644
index 0000000000..ed18cdca39
--- /dev/null
+++ b/spec/ruby/core/main/using_spec.rb
@@ -0,0 +1,134 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+ruby_version_is "2.0.0" do
+ require File.expand_path('../fixtures/classes', __FILE__)
+ require File.expand_path('../fixtures/string_refinement', __FILE__)
+
+ describe "main.using" do
+ it "requires one Module argument" do
+ lambda do
+ eval('using', TOPLEVEL_BINDING)
+ end.should raise_error(ArgumentError)
+
+ lambda do
+ eval('using "foo"', TOPLEVEL_BINDING)
+ end.should raise_error(TypeError)
+ end
+
+ it "uses refinements from the given module only in the target file" do
+ load File.expand_path('../fixtures/string_refinement_user.rb', __FILE__)
+ 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 for method calls in the target file" do
+ load File.expand_path('../fixtures/string_refinement_user.rb', __FILE__)
+ lambda do
+ 'hello'.foo
+ end.should raise_error(NoMethodError)
+ MainSpecs.call_foo('hello').should == 'foo'
+ end
+
+ it "uses refinements from the given module in the eval string" do
+ cls = MainSpecs::DATA[:cls] = Class.new {def foo; 'foo'; end}
+ MainSpecs::DATA[:mod] = Module.new do
+ refine(cls) do
+ def foo; 'bar'; end
+ end
+ end
+ eval(<<-EOS, TOPLEVEL_BINDING).should == 'bar'
+ using MainSpecs::DATA[:mod]
+ MainSpecs::DATA[:cls].new.foo
+ EOS
+ end
+
+ it "does not affect methods defined before it is called" do
+ 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
+
+ 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
diff --git a/spec/ruby/core/module/fixtures/refine.rb b/spec/ruby/core/module/fixtures/refine.rb
new file mode 100644
index 0000000000..46975361dd
--- /dev/null
+++ b/spec/ruby/core/module/fixtures/refine.rb
@@ -0,0 +1,13 @@
+module ModuleSpecs
+ class ClassWithFoo
+ def foo; "foo" end
+ end
+
+ module PrependedModule
+ def foo; "foo from prepended module"; end
+ end
+
+ module IncludedModule
+ def foo; "foo from included module"; end
+ end
+end
diff --git a/spec/ruby/core/module/fixtures/using.rb b/spec/ruby/core/module/fixtures/using.rb
new file mode 100644
index 0000000000..0ed9355af1
--- /dev/null
+++ b/spec/ruby/core/module/fixtures/using.rb
@@ -0,0 +1,10 @@
+module ModuleSpecs
+ module EmptyRefinement
+ end
+
+ module RefinementForStringToS
+ refine String do
+ def to_s; "hello from refinement"; end
+ end
+ end
+end
diff --git a/spec/ruby/core/module/refine_spec.rb b/spec/ruby/core/module/refine_spec.rb
new file mode 100644
index 0000000000..03e70915e2
--- /dev/null
+++ b/spec/ruby/core/module/refine_spec.rb
@@ -0,0 +1,616 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/refine', __FILE__)
+
+describe "Module#refine" do
+ it "runs its block in an anonymous module" do
+ inner_self = nil
+ mod = Module.new do
+ refine String do
+ inner_self = self
+ end
+ end
+
+ mod.should_not == inner_self
+ inner_self.should be_kind_of(Module)
+ inner_self.name.should == nil
+ end
+
+ it "uses the same anonymous module for future refines of the same class" do
+ selves = []
+ mod = Module.new do
+ refine String do
+ selves << self
+ end
+ end
+
+ mod.module_eval do
+ refine String do
+ selves << self
+ end
+ end
+
+ selves[0].should == selves[1]
+ end
+
+ it "adds methods defined in its block to the anonymous module's public instance methods" do
+ inner_self = nil
+ mod = Module.new do
+ refine String do
+ def blah
+ "blah"
+ end
+ inner_self = self
+ end
+ end
+
+ inner_self.public_instance_methods.should include(:blah)
+ end
+
+ it "returns created anonymous module" do
+ inner_self = nil
+ result = nil
+ mod = Module.new do
+ result = refine String do
+ inner_self = self
+ end
+ end
+
+ result.should == inner_self
+ end
+
+ it "raises ArgumentError if not passed an argument" do
+ lambda do
+ Module.new do
+ refine {}
+ end
+ end.should raise_error(ArgumentError)
+ end
+
+ it "raises TypeError if not passed a class" do
+ lambda do
+ Module.new do
+ refine("foo") {}
+ end
+ end.should raise_error(TypeError)
+ end
+
+ ruby_version_is "" ... "2.4" do
+ it "raises TypeError if passed a module" do
+ lambda do
+ Module.new do
+ refine(Enumerable) {}
+ end
+ end.should raise_error(TypeError)
+ end
+ end
+
+ ruby_version_is "2.4" do
+ it "accepts a module as argument" do
+ inner_self = nil
+ Module.new do
+ refine(Enumerable) do
+ def blah
+ end
+ inner_self = self
+ end
+ end
+
+ inner_self.public_instance_methods.should include(:blah)
+ end
+ end
+
+ it "raises ArgumentError if not given a block" do
+ lambda do
+ Module.new do
+ refine String
+ end
+ end.should raise_error(ArgumentError)
+ end
+
+ it "applies refinements to calls in the refine block" do
+ result = nil
+ Module.new do
+ refine(String) do
+ def foo; "foo"; end
+ result = "hello".foo
+ end
+ end
+ result.should == "foo"
+ end
+
+ it "doesn't apply refinements outside the refine block" do
+ Module.new do
+ refine(String) {def foo; "foo"; end}
+ -> () {
+ "hello".foo
+ }.should raise_error(NoMethodError)
+ end
+ end
+
+ it "does not apply refinements to external scopes not using the module" do
+ Module.new do
+ refine(String) {def foo; 'foo'; end}
+ end
+
+ lambda {"hello".foo}.should raise_error(NoMethodError)
+ end
+
+ # When defining multiple refinements in the same module,
+ # inside a refine block all refinements from the same
+ # module are active when a refined method is called
+ it "makes available all refinements from the same module" do
+ refinement = Module.new do
+ refine Integer do
+ def to_json_format
+ to_s
+ end
+ end
+
+ refine Array do
+ def to_json_format
+ "[" + map { |i| i.to_json_format }.join(", ") + "]"
+ end
+ end
+
+ refine Hash do
+ def to_json_format
+ "{" + map { |k, v| k.to_s.dump + ": " + v.to_json_format }.join(", ") + "}"
+ end
+ end
+ end
+
+ result = nil
+
+ Module.new do
+ using refinement
+
+ result = [{1 => 2}, {3 => 4}].to_json_format
+ end
+
+ result.should == '[{"1": 2}, {"3": 4}]'
+ end
+
+ it "does not make available methods from another refinement module" do
+ refinery_integer = Module.new do
+ refine Integer do
+ def to_json_format
+ to_s
+ end
+ end
+ end
+
+ refinery_array = Module.new do
+ refine Array do
+ def to_json_format
+ "[" + map { |i| i.to_json_format }.join(",") + "]"
+ end
+ end
+ end
+
+ result = nil
+
+ -> () {
+ Module.new do
+ using refinery_integer
+ using refinery_array
+
+ [1, 2].to_json_format
+ end
+ }.should raise_error(NoMethodError)
+ end
+
+ # method lookup:
+ # * The prepended modules from the refinement for C
+ # * The refinement for C
+ # * The included modules from the refinement for C
+ # * The prepended modules of C
+ # * C
+ # * The included modules of C
+ describe "method lookup" do
+ it "looks in the object singleton class first" do
+ refinement = Module.new do
+ refine ModuleSpecs::ClassWithFoo do
+ def foo; "foo from refinement"; end
+ end
+ end
+
+ result = nil
+ Module.new do
+ using refinement
+
+ obj = ModuleSpecs::ClassWithFoo.new
+ class << obj
+ def foo; "foo from singleton class"; end
+ end
+ result = obj.foo
+ end
+
+ result.should == "foo from singleton class"
+ end
+
+ it "looks in prepended modules from the refinement first" do
+ refinement = Module.new do
+ refine ModuleSpecs::ClassWithFoo do
+ include ModuleSpecs::IncludedModule
+ prepend ModuleSpecs::PrependedModule
+
+ def foo; "foo from refinement"; end
+ end
+ end
+
+ result = nil
+ Module.new do
+ using refinement
+ result = ModuleSpecs::ClassWithFoo.new.foo
+ end
+
+ result.should == "foo from prepended module"
+ end
+
+ it "looks in refinement then" do
+ refinement = Module.new do
+ refine(ModuleSpecs::ClassWithFoo) do
+ include ModuleSpecs::IncludedModule
+
+ def foo; "foo from refinement"; end
+ end
+ end
+
+ result = nil
+ Module.new do
+ using refinement
+ result = ModuleSpecs::ClassWithFoo.new.foo
+ end
+
+ result.should == "foo from refinement"
+ end
+
+ it "looks in included modules from the refinement then" do
+ refinement = Module.new do
+ refine ModuleSpecs::ClassWithFoo do
+ include ModuleSpecs::IncludedModule
+ end
+ end
+
+ result = nil
+ Module.new do
+ using refinement
+ result = ModuleSpecs::ClassWithFoo.new.foo
+ end
+
+ result.should == "foo from included module"
+ end
+
+ it "looks in the class then" do
+ refinement = Module.new do
+ refine(ModuleSpecs::ClassWithFoo) { }
+ end
+
+ result = nil
+ Module.new do
+ using refinement
+ result = ModuleSpecs::ClassWithFoo.new.foo
+ end
+
+ result.should == "foo"
+ end
+ end
+
+
+ # methods in a subclass have priority over refinements in a superclass
+ it "does not override methods in subclasses" do
+ subclass = Class.new(ModuleSpecs::ClassWithFoo) do
+ def foo; "foo from subclass"; end
+ end
+
+ refinement = Module.new do
+ refine ModuleSpecs::ClassWithFoo do
+ def foo; "foo from refinement"; end
+ end
+ end
+
+ result = nil
+ Module.new do
+ using refinement
+ result = subclass.new.foo
+ end
+
+ result.should == "foo from subclass"
+ end
+
+ context "for methods accesses indirectly" do
+ ruby_version_is "" ... "2.4" do
+ it "is not honored by Kernel#send" do
+ refinement = Module.new do
+ refine ModuleSpecs::ClassWithFoo do
+ def foo; "foo from refinement"; end
+ end
+ end
+
+ result = nil
+ Module.new do
+ using refinement
+ result = ModuleSpecs::ClassWithFoo.new.send :foo
+ end
+
+ result.should == "foo"
+ end
+
+ it "is not honored by BasicObject#__send__" do
+ refinement = Module.new do
+ refine ModuleSpecs::ClassWithFoo do
+ def foo; "foo from refinement"; end
+ end
+ end
+
+ result = nil
+ Module.new do
+ using refinement
+ result = ModuleSpecs::ClassWithFoo.new.__send__ :foo
+ end
+
+ result.should == "foo"
+ end
+
+ it "is not honored by Symbol#to_proc" do
+ refinement = Module.new do
+ refine Integer do
+ def to_s
+ "(#{super})"
+ end
+ end
+ end
+
+ result = nil
+ Module.new do
+ using refinement
+ result = [1, 2, 3].map(&:to_s)
+ end
+
+ result.should == ["1", "2", "3"]
+ end
+ end
+
+ ruby_version_is "2.4" do
+ it "is honored by Kernel#send" do
+ refinement = Module.new do
+ refine ModuleSpecs::ClassWithFoo do
+ def foo; "foo from refinement"; end
+ end
+ end
+
+ result = nil
+ Module.new do
+ using refinement
+ result = ModuleSpecs::ClassWithFoo.new.send :foo
+ end
+
+ result.should == "foo from refinement"
+ end
+
+ it "is honored by BasicObject#__send__" do
+ refinement = Module.new do
+ refine ModuleSpecs::ClassWithFoo do
+ def foo; "foo from refinement"; end
+ end
+ end
+
+ result = nil
+ Module.new do
+ using refinement
+ result = ModuleSpecs::ClassWithFoo.new.__send__ :foo
+ end
+
+ result.should == "foo from refinement"
+ end
+
+ it "is honored by Symbol#to_proc" do
+ refinement = Module.new do
+ refine Integer do
+ def to_s
+ "(#{super})"
+ end
+ end
+ end
+
+ result = nil
+ Module.new do
+ using refinement
+ result = [1, 2, 3].map(&:to_s)
+ end
+
+ result.should == ["(1)", "(2)", "(3)"]
+ end
+ end
+
+ it "is honored by Kernel#binding" do
+ refinement = Module.new do
+ refine String do
+ def to_s
+ "hello from refinement"
+ end
+ end
+ end
+
+ klass = Class.new do
+ using refinement
+
+ def foo
+ "foo".to_s
+ end
+
+ def get_binding
+ binding
+ end
+ end
+
+ result = Kernel.eval("self.foo()", klass.new.get_binding)
+ result.should == "hello from refinement"
+ end
+
+ it "is not honored by Kernel#method" do
+ klass = Class.new
+ refinement = Module.new do
+ refine klass do
+ def foo; end
+ end
+ end
+
+ -> {
+ Module.new do
+ using refinement
+ klass.new.method(:foo)
+ end
+ }.should raise_error(NameError, /undefined method `foo'/)
+ end
+
+ it "is not honored by Kernel#respond_to?" do
+ klass = Class.new
+ refinement = Module.new do
+ refine klass do
+ def foo; end
+ end
+ end
+
+ result = nil
+ Module.new do
+ using refinement
+ result = klass.new.respond_to?(:foo)
+ end
+
+ result.should == false
+ end
+ end
+
+ context "when super is called in a refinement" do
+ it "looks in the included to refinery module" do
+ refinement = Module.new do
+ refine ModuleSpecs::ClassWithFoo do
+ include ModuleSpecs::IncludedModule
+
+ def foo
+ super
+ end
+ end
+ end
+
+ result = nil
+ Module.new do
+ using refinement
+ result = ModuleSpecs::ClassWithFoo.new.foo
+ end
+
+ result.should == "foo from included module"
+ end
+
+ it "looks in the refined class" do
+ refinement = Module.new do
+ refine ModuleSpecs::ClassWithFoo do
+ def foo
+ super
+ end
+ end
+ end
+
+ result = nil
+ Module.new do
+ using refinement
+ result = ModuleSpecs::ClassWithFoo.new.foo
+ end
+
+ result.should == "foo"
+ end
+
+ # super in a method of a refinement invokes the method in the refined
+ # class even if there is another refinement which has been activated
+ # in the same context.
+ it "looks in the refined class even if there is another active refinement" do
+ refinement = Module.new do
+ refine ModuleSpecs::ClassWithFoo do
+ def foo
+ "foo from refinement"
+ end
+ end
+ end
+
+ refinement_with_super = Module.new do
+ refine ModuleSpecs::ClassWithFoo do
+ def foo
+ super
+ end
+ end
+ end
+
+ result = nil
+ Module.new do
+ using refinement
+ using refinement_with_super
+ result = ModuleSpecs::ClassWithFoo.new.foo
+ end
+
+ result.should == "foo"
+ end
+ end
+
+ # Refinements are inherited by module inclusion.
+ # That is, using activates all refinements in the ancestors of the specified module.
+ # Refinements in a descendant have priority over refinements in an ancestor.
+ context "module inclusion" do
+ it "activates all refinements from all ancestors" do
+ refinement_included = Module.new do
+ refine Integer do
+ def to_json_format
+ to_s
+ end
+ end
+ end
+
+ refinement = Module.new do
+ include refinement_included
+
+ refine Array do
+ def to_json_format
+ "[" + map { |i| i.to_s }.join(", ") + "]"
+ end
+ end
+ end
+
+ result = nil
+ Module.new do
+ using refinement
+ result = [5.to_json_format, [1, 2, 3].to_json_format]
+ end
+
+ result.should == ["5", "[1, 2, 3]"]
+ end
+
+ it "overrides methods of ancestors by methods in descendants" do
+ refinement_included = Module.new do
+ refine Integer do
+ def to_json_format
+ to_s
+ end
+ end
+ end
+
+ refinement = Module.new do
+ include refinement_included
+
+ refine Integer do
+ def to_json_format
+ "hello from refinement"
+ end
+ end
+ end
+
+ result = nil
+ Module.new do
+ using refinement
+ result = 5.to_json_format
+ end
+
+ result.should == "hello from refinement"
+ end
+ end
+end
+
diff --git a/spec/ruby/core/module/using_spec.rb b/spec/ruby/core/module/using_spec.rb
new file mode 100644
index 0000000000..32e8f8f96b
--- /dev/null
+++ b/spec/ruby/core/module/using_spec.rb
@@ -0,0 +1,276 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/using', __FILE__)
+
+describe "Module#using" do
+ it "imports class refinements from module into the current class/module" do
+ refinement = Module.new do
+ refine Integer do
+ def foo; "foo"; end
+ end
+ end
+
+ result = nil
+ Module.new do
+ using refinement
+ result = 1.foo
+ end
+
+ result.should == "foo"
+ end
+
+ it "accepts module as argument" do
+ refinement = Module.new do
+ refine Integer do
+ def foo; "foo"; end
+ end
+ end
+
+ -> () {
+ Module.new do
+ using refinement
+ end
+ }.should_not raise_error
+ end
+
+ it "accepts module without refinements" do
+ mod = Module.new
+
+ -> () {
+ Module.new do
+ using mod
+ end
+ }.should_not raise_error
+ end
+
+ it "does not accept class" do
+ klass = Class.new
+
+ -> () {
+ Module.new do
+ using klass
+ end
+ }.should raise_error(TypeError)
+ end
+
+ it "raises TypeError if passed something other than module" do
+ -> () {
+ Module.new do
+ using "foo"
+ end
+ }.should raise_error(TypeError)
+ end
+
+ it "returns self" do
+ refinement = Module.new
+
+ result = nil
+ mod = Module.new do
+ result = using refinement
+ end
+
+ result.should equal(mod)
+ end
+
+ it "works in classes too" do
+ refinement = Module.new do
+ refine Integer do
+ def foo; "foo"; end
+ end
+ end
+
+ result = nil
+ Class.new do
+ using refinement
+ result = 1.foo
+ end
+
+ result.should == "foo"
+ end
+
+ it "raises error in method scope" do
+ mod = Module.new do
+ def self.foo
+ using ModuleSpecs::EmptyRefinement
+ end
+ end
+
+ -> () {
+ mod.foo
+ }.should raise_error(RuntimeError, /Module#using is not permitted in methods/)
+ end
+
+ it "activates refinement even for existed objects" do
+ result = nil
+
+ Module.new do
+ klass = Class.new do
+ def foo; "foo"; end
+ end
+
+ refinement = Module.new do
+ refine klass do
+ def foo; "foo from refinement"; end
+ end
+ end
+
+ obj = klass.new
+ using refinement
+ result = obj.foo
+ end
+
+ result.should == "foo from refinement"
+ end
+
+ it "activates updates when refinement reopens later" do
+ result = nil
+
+ Module.new do
+ klass = Class.new do
+ def foo; "foo"; end
+ end
+
+ refinement = Module.new do
+ refine klass do
+ def foo; "foo from refinement"; end
+ end
+ end
+
+ using refinement
+
+ refinement.class_eval do
+ refine klass do
+ def foo; "foo from reopened refinement"; end
+ end
+ end
+
+ obj = klass.new
+ result = obj.foo
+ end
+
+ result.should == "foo from reopened refinement"
+ end
+
+ describe "scope of refinement" do
+ it "is active until the end of current class/module" do
+ ScratchPad.record []
+
+ Module.new do
+ Class.new do
+ using ModuleSpecs::RefinementForStringToS
+ ScratchPad << "1".to_s
+ end
+
+ ScratchPad << "1".to_s
+ end
+
+ ScratchPad.recorded.should == ["hello from refinement", "1"]
+ end
+
+ # Refinements are lexical in scope.
+ # Refinements are only active within a scope after the call to using.
+ # Any code before the using statement will not have the refinement activated.
+ it "is not active before the `using` call" do
+ ScratchPad.record []
+
+ Module.new do
+ Class.new do
+ ScratchPad << "1".to_s
+ using ModuleSpecs::RefinementForStringToS
+ ScratchPad << "1".to_s
+ end
+ end
+
+ ScratchPad.recorded.should == ["1", "hello from refinement"]
+ end
+
+ # If you call a method that is defined outside the current scope
+ # the refinement will be deactivated
+ it "is not active for code defined outside the current scope" do
+ result = nil
+
+ Module.new do
+ klass = Class.new do
+ def foo; "foo"; end
+ end
+
+ refinement = Module.new do
+ refine klass do
+ def foo; "foo from refinement"; end
+ end
+ end
+
+ def self.call_foo(c)
+ c.foo
+ end
+
+ using refinement
+
+ result = call_foo(klass.new)
+ end
+
+ result.should == "foo"
+ end
+
+ # If a method is defined in a scope where a refinement is active
+ # the refinement will be active when the method is called.
+ it "is active for method defined in a scope wherever it's called" do
+ klass = Class.new do
+ def foo; "foo"; end
+ end
+
+ mod = Module.new do
+ refinement = Module.new do
+ refine klass do
+ def foo; "foo from refinement"; end
+ end
+ end
+
+ using refinement
+
+ def self.call_foo(c)
+ c.foo
+ end
+ end
+
+ c = klass.new
+ mod.call_foo(c).should == "foo from refinement"
+ end
+
+ it "is not active if `using` call is not evaluated" do
+ result = nil
+
+ Module.new do
+ if false
+ using ModuleSpecs::RefinementForStringToS
+ end
+ result = "1".to_s
+ end
+
+ result.should == "1"
+ end
+
+ # The refinements in module are not activated automatically
+ # if the class is reopened later
+ it "is not active when class/module reopens" do
+ refinement = Module.new do
+ refine String do
+ def to_s
+ "hello from refinement"
+ end
+ end
+ end
+
+ result = []
+ klass = Class.new do
+ using refinement
+ result << "1".to_s
+ end
+
+ klass.class_eval do
+ result << "1".to_s
+ end
+
+ result.should == ["hello from refinement", "1"]
+ end
+ end
+end
diff --git a/spec/ruby/core/mutex/lock_spec.rb b/spec/ruby/core/mutex/lock_spec.rb
index 98deabe056..b5c2b168e8 100644
--- a/spec/ruby/core/mutex/lock_spec.rb
+++ b/spec/ruby/core/mutex/lock_spec.rb
@@ -33,14 +33,9 @@ describe "Mutex#lock" do
# related to this ML thread.
it "raises a ThreadError when used recursively" do
m = Mutex.new
-
- th = Thread.new do
- m.lock
+ m.lock
+ -> {
m.lock
- end
-
- lambda do
- th.join
- end.should raise_error(ThreadError)
+ }.should raise_error(ThreadError)
end
end
diff --git a/spec/ruby/core/nil/dup_spec.rb b/spec/ruby/core/nil/dup_spec.rb
new file mode 100644
index 0000000000..10b1209736
--- /dev/null
+++ b/spec/ruby/core/nil/dup_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+ruby_version_is '2.4' do
+ describe "NilClass#dup" do
+ it "returns self" do
+ nil.dup.should equal(nil)
+ end
+ end
+end
diff --git a/spec/ruby/core/numeric/coerce_spec.rb b/spec/ruby/core/numeric/coerce_spec.rb
index 9b6297d5da..820d900dd5 100644
--- a/spec/ruby/core/numeric/coerce_spec.rb
+++ b/spec/ruby/core/numeric/coerce_spec.rb
@@ -17,7 +17,7 @@ describe "Numeric#coerce" do
# I (emp) think that this behavior is actually a bug in MRI. It's here as documentation
# of the behavior until we find out if it's a bug.
quarantine! do
- it "considers the presense of a metaclass when checking the class of the objects" do
+ it "considers the presence of a metaclass when checking the class of the objects" do
a = NumericSpecs::Subclass.new
b = NumericSpecs::Subclass.new
diff --git a/spec/ruby/core/numeric/finite_spec.rb b/spec/ruby/core/numeric/finite_spec.rb
new file mode 100644
index 0000000000..9fb2252845
--- /dev/null
+++ b/spec/ruby/core/numeric/finite_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+ruby_version_is "2.4" do
+ describe "Numeric#finite?" do
+ it "returns true by default" do
+ o = mock_numeric("finite")
+ o.finite?.should be_true
+ end
+ end
+end
diff --git a/spec/ruby/core/numeric/infinite_spec.rb b/spec/ruby/core/numeric/infinite_spec.rb
new file mode 100644
index 0000000000..a527cb4370
--- /dev/null
+++ b/spec/ruby/core/numeric/infinite_spec.rb
@@ -0,0 +1,10 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+ruby_version_is "2.4" do
+ describe "Numeric#infinite?" do
+ it "returns nil by default" do
+ o = mock_numeric("infinite")
+ o.infinite?.should == nil
+ end
+ end
+end
diff --git a/spec/ruby/core/process/wait2_spec.rb b/spec/ruby/core/process/wait2_spec.rb
index 8e1ac763f1..d1f3a47b7f 100644
--- a/spec/ruby/core/process/wait2_spec.rb
+++ b/spec/ruby/core/process/wait2_spec.rb
@@ -5,8 +5,11 @@ describe "Process.wait2" do
# HACK: this kludge is temporarily necessary because some
# misbehaving spec somewhere else does not clear processes
begin
+ Process.wait(-1, Process::WNOHANG)
+ $stderr.puts "Leaked process before wait2 specs! Waiting for it"
leaked = Process.waitall
- puts "leaked before wait2 specs: #{leaked}" unless leaked.empty?
+ $stderr.puts "leaked before wait2 specs: #{leaked}"
+ rescue Errno::ECHILD # No child processes
rescue NotImplementedError
end
end
diff --git a/spec/ruby/core/random/bytes_spec.rb b/spec/ruby/core/random/bytes_spec.rb
index 2434a4e72e..d954261329 100644
--- a/spec/ruby/core/random/bytes_spec.rb
+++ b/spec/ruby/core/random/bytes_spec.rb
@@ -19,14 +19,14 @@ describe "Random#bytes" do
end
# Should double check this is official spec
- it "returns the same numeric output for a given seed accross all implementations and platforms" do
+ it "returns the same numeric output for a given seed across all implementations and platforms" do
rnd = Random.new(33)
rnd.bytes(2).should == "\x14\\"
rnd.bytes(1000) # skip some
rnd.bytes(2).should == "\xA1p"
end
- it "returns the same numeric output for a given huge seed accross all implementations and platforms" do
+ it "returns the same numeric output for a given huge seed across all implementations and platforms" do
rnd = Random.new(bignum_value ** 4)
rnd.bytes(2).should == "_\x91"
rnd.bytes(1000) # skip some
diff --git a/spec/ruby/core/string/capitalize_spec.rb b/spec/ruby/core/string/capitalize_spec.rb
index e2d2b68caa..497e1453cd 100644
--- a/spec/ruby/core/string/capitalize_spec.rb
+++ b/spec/ruby/core/string/capitalize_spec.rb
@@ -44,6 +44,14 @@ describe "String#capitalize!" do
a.should == "Hello"
end
+ ruby_version_is '2.4' do
+ it "capitalizes self in place for all of Unicode" do
+ a = "äöü"
+ a.capitalize!.should equal(a)
+ a.should == "Äöü"
+ end
+ end
+
it "returns nil when no changes are made" do
a = "Hello"
a.capitalize!.should == nil
diff --git a/spec/ruby/core/string/casecmp_spec.rb b/spec/ruby/core/string/casecmp_spec.rb
index fdb888ff2b..c77d97815c 100644
--- a/spec/ruby/core/string/casecmp_spec.rb
+++ b/spec/ruby/core/string/casecmp_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: ascii-8bit -*-
+# -*- encoding: utf-8 -*-
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes.rb', __FILE__)
@@ -40,10 +40,10 @@ describe "String#casecmp independent of case" do
describe "in UTF-8 mode" do
describe "for non-ASCII characters" do
before :each do
- @upper_a_tilde = "\xc3\x83"
- @lower_a_tilde = "\xc3\xa3"
- @upper_a_umlaut = "\xc3\x84"
- @lower_a_umlaut = "\xc3\xa4"
+ @upper_a_tilde = "Ã"
+ @lower_a_tilde = "ã"
+ @upper_a_umlaut = "Ä"
+ @lower_a_umlaut = "ä"
end
it "returns -1 when numerically less than other" do
@@ -118,3 +118,67 @@ describe "String#casecmp independent of case" do
end
end
end
+
+ruby_version_is "2.4" do
+ describe 'String#casecmp? independent of case' do
+ it 'returns true when equal to other' do
+ 'abc'.casecmp?('abc').should == true
+ 'abc'.casecmp?('ABC').should == true
+ end
+
+ it 'returns false when not equal to other' do
+ 'abc'.casecmp?('DEF').should == false
+ 'abc'.casecmp?('def').should == false
+ end
+
+ it "tries to convert other to string using to_str" do
+ other = mock('x')
+ other.should_receive(:to_str).and_return("abc")
+
+ "abc".casecmp?(other).should == true
+ end
+
+ describe 'for UNICODE characters' do
+ it 'returns true when downcase(:fold) on unicode' do
+ 'äöü'.casecmp?('ÄÖÜ').should == true
+ end
+ end
+
+ describe "when comparing a subclass instance" do
+ it 'returns true when equal to other' do
+ a = StringSpecs::MyString.new "a"
+ 'a'.casecmp?(a).should == true
+ 'A'.casecmp?(a).should == true
+ end
+
+ it 'returns false when not equal to other' do
+ b = StringSpecs::MyString.new "a"
+ 'b'.casecmp?(b).should == false
+ 'B'.casecmp?(b).should == false
+ end
+ end
+
+ describe "in UTF-8 mode" do
+ describe "for non-ASCII characters" do
+ before :each do
+ @upper_a_tilde = "Ã"
+ @lower_a_tilde = "ã"
+ @upper_a_umlaut = "Ä"
+ @lower_a_umlaut = "ä"
+ end
+
+ it "returns true when they are the same with normalized case" do
+ @upper_a_tilde.casecmp?(@lower_a_tilde).should == true
+ end
+
+ it "returns false when they are unrelated" do
+ @upper_a_tilde.casecmp?(@upper_a_umlaut).should == false
+ end
+
+ it "returns true when they have the same bytes" do
+ @upper_a_tilde.casecmp?(@upper_a_tilde).should == true
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/string/downcase_spec.rb b/spec/ruby/core/string/downcase_spec.rb
index 9ebc4f2bd1..f591c0fa09 100644
--- a/spec/ruby/core/string/downcase_spec.rb
+++ b/spec/ruby/core/string/downcase_spec.rb
@@ -46,6 +46,14 @@ describe "String#downcase!" do
a.should == "hello"
end
+ ruby_version_is '2.4' do
+ it "modifies self in place for all of Unicode" do
+ a = "ÄÖÜ"
+ a.downcase!.should equal(a)
+ a.should == "äöü"
+ end
+ end
+
it "returns nil if no modifications were made" do
a = "hello"
a.downcase!.should == nil
diff --git a/spec/ruby/core/string/lines_spec.rb b/spec/ruby/core/string/lines_spec.rb
index 6aa47ea728..e5f24816af 100644
--- a/spec/ruby/core/string/lines_spec.rb
+++ b/spec/ruby/core/string/lines_spec.rb
@@ -10,4 +10,13 @@ describe "String#lines" do
ary = "hello world".send(@method, ' ')
ary.should == ["hello ", "world"]
end
+
+ ruby_version_is '2.4' do
+ context "when `chomp` keyword argument is passed" do
+ it "removes new line characters" do
+ "hello \nworld\n".lines(chomp: true).should == ["hello ", "world"]
+ "hello \r\nworld\r\n".lines(chomp: true).should == ["hello ", "world"]
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/string/new_spec.rb b/spec/ruby/core/string/new_spec.rb
index 0a246f6f53..b429ac48d2 100644
--- a/spec/ruby/core/string/new_spec.rb
+++ b/spec/ruby/core/string/new_spec.rb
@@ -15,6 +15,13 @@ describe "String.new" do
end
end
+ ruby_version_is "2.4" do
+ it "accepts a capacity argument" do
+ String.new("", capacity: 100_000).should == ""
+ String.new("abc", capacity: 100_000).should == "abc"
+ end
+ end
+
it "returns a fully-formed String" do
str = String.new
str.size.should == 0
diff --git a/spec/ruby/core/string/shared/chars.rb b/spec/ruby/core/string/shared/chars.rb
index 2f7280a95f..c1cf324dc5 100644
--- a/spec/ruby/core/string/shared/chars.rb
+++ b/spec/ruby/core/string/shared/chars.rb
@@ -42,10 +42,8 @@ describe :string_chars, shared: true do
it "returns a different character if the String is transcoded" do
s = "\u{20AC}".force_encoding('UTF-8')
s.encode('UTF-8').send(@method).to_a.should == ["\u{20AC}".force_encoding('UTF-8')]
- s.encode('iso-8859-15').send(@method).to_a.should == [
- [0xA4].pack('C').force_encoding('iso-8859-15')]
- s.encode('iso-8859-15').encode('UTF-8').send(@method).to_a.should == [
- "\u{20AC}".force_encoding('UTF-8')]
+ s.encode('iso-8859-15').send(@method).to_a.should == [[0xA4].pack('C').force_encoding('iso-8859-15')]
+ s.encode('iso-8859-15').encode('UTF-8').send(@method).to_a.should == ["\u{20AC}".force_encoding('UTF-8')]
end
it "uses the String's encoding to determine what characters it contains" do
diff --git a/spec/ruby/core/string/shared/codepoints.rb b/spec/ruby/core/string/shared/codepoints.rb
index 1ee13c82f4..68f82b4468 100644
--- a/spec/ruby/core/string/shared/codepoints.rb
+++ b/spec/ruby/core/string/shared/codepoints.rb
@@ -48,7 +48,7 @@ describe :string_codepoints, shared: true do
s.should == s2
end
- it "is synonomous with #bytes for Strings which are single-byte optimisable" do
+ it "is synonymous with #bytes for Strings which are single-byte optimisable" do
s = "(){}".encode('ascii')
s.ascii_only?.should be_true
s.send(@method).to_a.should == s.bytes.to_a
diff --git a/spec/ruby/core/string/shared/each_line.rb b/spec/ruby/core/string/shared/each_line.rb
index fe8b76b47b..dee741e270 100644
--- a/spec/ruby/core/string/shared/each_line.rb
+++ b/spec/ruby/core/string/shared/each_line.rb
@@ -133,4 +133,18 @@ end
it "raises a TypeError when the separator is a symbol" do
lambda { "hello world".send(@method, :o).to_a }.should raise_error(TypeError)
end
+
+ ruby_version_is '2.4' do
+ context "when `chomp` keyword argument is passed" do
+ it "removes new line characters" do
+ a = []
+ "hello \nworld\n".send(@method, chomp: true) { |s| a << s }
+ a.should == ["hello ", "world"]
+
+ a = []
+ "hello \r\nworld\r\n".send(@method, chomp: true) { |s| a << s }
+ a.should == ["hello ", "world"]
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/string/shared/to_sym.rb b/spec/ruby/core/string/shared/to_sym.rb
index 501247078d..1180d64712 100644
--- a/spec/ruby/core/string/shared/to_sym.rb
+++ b/spec/ruby/core/string/shared/to_sym.rb
@@ -1,24 +1,63 @@
describe :string_to_sym, shared: true do
it "returns the symbol corresponding to self" do
- "Koala".send(@method).should == :Koala
- 'cat'.send(@method).should == :cat
- '@cat'.send(@method).should == :@cat
- 'cat and dog'.send(@method).should == :"cat and dog"
- "abc=".send(@method).should == :abc=
+ "Koala".send(@method).should equal :Koala
+ 'cat'.send(@method).should equal :cat
+ '@cat'.send(@method).should equal :@cat
+ 'cat and dog'.send(@method).should equal :"cat and dog"
+ "abc=".send(@method).should equal :abc=
end
it "does not special case +(binary) and -(binary)" do
- "+(binary)".send(@method).should == :"+(binary)"
- "-(binary)".send(@method).should == :"-(binary)"
+ "+(binary)".send(@method).should equal :"+(binary)"
+ "-(binary)".send(@method).should equal :"-(binary)"
end
it "does not special case certain operators" do
- [ ["!@", :"!@"],
- ["~@", :"~@"],
- ["!(unary)", :"!(unary)"],
- ["~(unary)", :"~(unary)"],
- ["+(unary)", :"+(unary)"],
- ["-(unary)", :"-(unary)"]
- ].should be_computed_by(@method)
+ "!@".send(@method).should equal :"!@"
+ "~@".send(@method).should equal :"~@"
+ "!(unary)".send(@method).should equal :"!(unary)"
+ "~(unary)".send(@method).should equal :"~(unary)"
+ "+(unary)".send(@method).should equal :"+(unary)"
+ "-(unary)".send(@method).should equal :"-(unary)"
+ end
+
+ it "returns a US-ASCII Symbol for a UTF-8 String containing only US-ASCII characters" do
+ sym = "foobar".send(@method)
+ sym.encoding.should == Encoding::US_ASCII
+ sym.should equal :"foobar"
+ end
+
+ it "returns a US-ASCII Symbol for a binary String containing only US-ASCII characters" do
+ sym = "foobar".b.send(@method)
+ sym.encoding.should == Encoding::US_ASCII
+ sym.should equal :"foobar"
+ end
+
+ it "returns a UTF-8 Symbol for a UTF-8 String containing non US-ASCII characters" do
+ sym = "il était une fois".send(@method)
+ sym.encoding.should == Encoding::UTF_8
+ sym.should equal :"il était une #{'fois'}"
+ end
+
+ it "returns a UTF-16LE Symbol for a UTF-16LE String containing non US-ASCII characters" do
+ utf16_str = "UtéF16".encode(Encoding::UTF_16LE)
+ sym = utf16_str.send(@method)
+ sym.encoding.should == Encoding::UTF_16LE
+ sym.to_s.should == utf16_str
+ end
+
+ it "returns a binary Symbol for a binary String containing non US-ASCII characters" do
+ binary_string = "binarí".b
+ sym = binary_string.send(@method)
+ sym.encoding.should == Encoding::BINARY
+ sym.to_s.should == binary_string
+ end
+
+ it "raises an EncodingError for UTF-8 String containing invalid bytes" do
+ invalid_utf8 = "\xC3"
+ invalid_utf8.valid_encoding?.should == false
+ -> {
+ invalid_utf8.send(@method)
+ }.should raise_error(EncodingError, /invalid/)
end
end
diff --git a/spec/ruby/core/string/swapcase_spec.rb b/spec/ruby/core/string/swapcase_spec.rb
index e9af647727..c2b583acab 100644
--- a/spec/ruby/core/string/swapcase_spec.rb
+++ b/spec/ruby/core/string/swapcase_spec.rb
@@ -41,6 +41,14 @@ describe "String#swapcase!" do
a.should == "CyBeR_pUnK11"
end
+ ruby_version_is '2.4' do
+ it "modifies self in place for all of Unicode" do
+ a = "äÖü"
+ a.swapcase!.should equal(a)
+ a.should == "ÄöÜ"
+ end
+ end
+
it "returns nil if no modifications were made" do
a = "+++---111222???"
a.swapcase!.should == nil
diff --git a/spec/ruby/core/string/unpack1_spec.rb b/spec/ruby/core/string/unpack1_spec.rb
new file mode 100644
index 0000000000..6941bc1173
--- /dev/null
+++ b/spec/ruby/core/string/unpack1_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+ruby_version_is "2.4" do
+ describe "String#unpack1" do
+ it "returns the first value of #unpack" do
+ "ABCD".unpack1('x3C').should == "ABCD".unpack('x3C')[0]
+ "\u{3042 3044 3046}".unpack1("U*").should == 0x3042
+ "aG9nZWZ1Z2E=".unpack1("m").should == "hogefuga"
+ "A".unpack1("B*").should == "01000001"
+ end
+ end
+end
diff --git a/spec/ruby/core/string/upcase_spec.rb b/spec/ruby/core/string/upcase_spec.rb
index 2fdcce86b9..0094380664 100644
--- a/spec/ruby/core/string/upcase_spec.rb
+++ b/spec/ruby/core/string/upcase_spec.rb
@@ -46,6 +46,15 @@ describe "String#upcase!" do
a.should == "HELLO"
end
+
+ ruby_version_is '2.4' do
+ it "modifies self in place for all of Unicode" do
+ a = "äöü"
+ a.upcase!.should equal(a)
+ a.should == "ÄÖÜ"
+ end
+ end
+
it "returns nil if no modifications were made" do
a = "HELLO"
a.upcase!.should == nil
diff --git a/spec/ruby/core/struct/initialize_spec.rb b/spec/ruby/core/struct/initialize_spec.rb
index 59fc5ef9aa..989459114a 100644
--- a/spec/ruby/core/struct/initialize_spec.rb
+++ b/spec/ruby/core/struct/initialize_spec.rb
@@ -37,7 +37,7 @@ describe "Struct#initialize" do
car.make.should == nil # still nil despite override in Honda#initialize b/c of super order
end
- it "can be overriden" do
+ it "can be overridden" do
StructClasses::SubclassX.new(:y).new.key.should == :value
end
end
diff --git a/spec/ruby/core/symbol/capitalize_spec.rb b/spec/ruby/core/symbol/capitalize_spec.rb
index cf7e8a007f..73850a2a8c 100644
--- a/spec/ruby/core/symbol/capitalize_spec.rb
+++ b/spec/ruby/core/symbol/capitalize_spec.rb
@@ -21,6 +21,13 @@ describe "Symbol#capitalize" do
end
end
+ ruby_version_is '2.4' do
+ it "capitalizes the first character if it is Unicode" do
+ :"äöü".capitalize.should == :"Äöü"
+ :"aou".capitalize.should == :"Aou"
+ end
+ end
+
it "converts subsequent uppercase ASCII characters to their lowercase equivalents" do
:lOWER.capitalize.should == :Lower
end
diff --git a/spec/ruby/core/symbol/casecmp_spec.rb b/spec/ruby/core/symbol/casecmp_spec.rb
index 942bd15998..352c5b99cb 100644
--- a/spec/ruby/core/symbol/casecmp_spec.rb
+++ b/spec/ruby/core/symbol/casecmp_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# -*- encoding: utf-8 -*-
require File.expand_path('../../../spec_helper', __FILE__)
describe "Symbol#casecmp with Symbol" do
@@ -11,10 +11,10 @@ describe "Symbol#casecmp with Symbol" do
it "doesn't consider non-ascii characters equal that aren't" do
# -- Latin-1 --
- upper_a_tilde = :"\xC3"
- upper_a_umlaut = :"\xC4"
- lower_a_tilde = :"\xE3"
- lower_a_umlaut = :"\xE4"
+ upper_a_tilde = "\xC3".b.to_sym
+ upper_a_umlaut = "\xC4".b.to_sym
+ lower_a_tilde = "\xE3".b.to_sym
+ lower_a_umlaut = "\xE4".b.to_sym
lower_a_tilde.casecmp(lower_a_umlaut).should_not == 0
lower_a_umlaut.casecmp(lower_a_tilde).should_not == 0
@@ -22,10 +22,10 @@ describe "Symbol#casecmp with Symbol" do
upper_a_umlaut.casecmp(upper_a_tilde).should_not == 0
# -- UTF-8 --
- upper_a_tilde = :"\xC3\x83"
- upper_a_umlaut = :"\xC3\x84"
- lower_a_tilde = :"\xC3\xA3"
- lower_a_umlaut = :"\xC3\xA4"
+ upper_a_tilde = :"Ã"
+ lower_a_tilde = :"ã"
+ upper_a_umlaut = :"Ä"
+ lower_a_umlaut = :"ä"
lower_a_tilde.casecmp(lower_a_umlaut).should_not == 0
lower_a_umlaut.casecmp(lower_a_tilde).should_not == 0
@@ -35,10 +35,10 @@ describe "Symbol#casecmp with Symbol" do
it "doesn't do case mapping for non-ascii characters" do
# -- Latin-1 --
- upper_a_tilde = :"\xC3"
- upper_a_umlaut = :"\xC4"
- lower_a_tilde = :"\xE3"
- lower_a_umlaut = :"\xE4"
+ upper_a_tilde = "\xC3".b.to_sym
+ upper_a_umlaut = "\xC4".b.to_sym
+ lower_a_tilde = "\xE3".b.to_sym
+ lower_a_umlaut = "\xE4".b.to_sym
upper_a_tilde.casecmp(lower_a_tilde).should == -1
upper_a_umlaut.casecmp(lower_a_umlaut).should == -1
@@ -46,10 +46,10 @@ describe "Symbol#casecmp with Symbol" do
lower_a_umlaut.casecmp(upper_a_umlaut).should == 1
# -- UTF-8 --
- upper_a_tilde = :"\xC3\x83"
- upper_a_umlaut = :"\xC3\x84"
- lower_a_tilde = :"\xC3\xA3"
- lower_a_umlaut = :"\xC3\xA4"
+ upper_a_tilde = :"Ã"
+ lower_a_tilde = :"ã"
+ upper_a_umlaut = :"Ä"
+ lower_a_umlaut = :"ä"
upper_a_tilde.casecmp(lower_a_tilde).should == -1
upper_a_umlaut.casecmp(lower_a_umlaut).should == -1
@@ -72,3 +72,75 @@ describe "Symbol#casecmp" do
:abc.casecmp(obj).should be_nil
end
end
+
+ruby_version_is "2.4" do
+ describe 'Symbol#casecmp?' do
+ it "compares symbols without regard to case" do
+ :abcdef.casecmp?(:abcde).should == false
+ :aBcDeF.casecmp?(:abcdef).should == true
+ :abcdef.casecmp?(:abcdefg).should == false
+ :abcdef.casecmp?(:ABCDEF).should == true
+ end
+
+ it "doesn't consider non-ascii characters equal that aren't" do
+ # -- Latin-1 --
+ upper_a_tilde = "\xC3".b.to_sym
+ upper_a_umlaut = "\xC4".b.to_sym
+ lower_a_tilde = "\xE3".b.to_sym
+ lower_a_umlaut = "\xE4".b.to_sym
+
+ lower_a_tilde.casecmp?(lower_a_umlaut).should_not == true
+ lower_a_umlaut.casecmp?(lower_a_tilde).should_not == true
+ upper_a_tilde.casecmp?(upper_a_umlaut).should_not == true
+ upper_a_umlaut.casecmp?(upper_a_tilde).should_not == true
+
+ # -- UTF-8 --
+ upper_a_tilde = :"Ã"
+ lower_a_tilde = :"ã"
+ upper_a_umlaut = :"Ä"
+ lower_a_umlaut = :"ä"
+
+ lower_a_tilde.casecmp?(lower_a_umlaut).should_not == true
+ lower_a_umlaut.casecmp?(lower_a_tilde).should_not == true
+ upper_a_tilde.casecmp?(upper_a_umlaut).should_not == true
+ upper_a_umlaut.casecmp?(upper_a_tilde).should_not == true
+ end
+
+ it "doesn't do case mapping for non-ascii and non-unicode characters" do
+ # -- Latin-1 --
+ upper_a_tilde = "\xC3".b.to_sym
+ upper_a_umlaut = "\xC4".b.to_sym
+ lower_a_tilde = "\xE3".b.to_sym
+ lower_a_umlaut = "\xE4".b.to_sym
+
+ upper_a_tilde.casecmp?(lower_a_tilde).should == false
+ upper_a_umlaut.casecmp?(lower_a_umlaut).should == false
+ lower_a_tilde.casecmp?(upper_a_tilde).should == false
+ lower_a_umlaut.casecmp?(upper_a_umlaut).should == false
+ end
+
+ it 'does case mapping for unicode characters' do
+ # -- UTF-8 --
+ upper_a_tilde = :"Ã"
+ lower_a_tilde = :"ã"
+ upper_a_umlaut = :"Ä"
+ lower_a_umlaut = :"ä"
+
+ upper_a_tilde.casecmp?(lower_a_tilde).should == true
+ upper_a_umlaut.casecmp?(lower_a_umlaut).should == true
+ lower_a_tilde.casecmp?(upper_a_tilde).should == true
+ lower_a_umlaut.casecmp?(upper_a_umlaut).should == true
+ end
+
+ it 'returns nil when comparing characters with different encodings' do
+ # -- Latin-1 --
+ upper_a_tilde = "\xC3".b.to_sym
+
+ # -- UTF-8 --
+ lower_a_tilde = :"ã"
+
+ upper_a_tilde.casecmp?(lower_a_tilde).should == nil
+ lower_a_tilde.casecmp?(upper_a_tilde).should == nil
+ end
+ end
+end
diff --git a/spec/ruby/core/symbol/downcase_spec.rb b/spec/ruby/core/symbol/downcase_spec.rb
index 0b2422ad3e..6eb19e087a 100644
--- a/spec/ruby/core/symbol/downcase_spec.rb
+++ b/spec/ruby/core/symbol/downcase_spec.rb
@@ -20,6 +20,13 @@ describe "Symbol#downcase" do
end
end
+ ruby_version_is '2.4' do
+ it "uncapitalizes all Unicode characters" do
+ "ÄÖÜ".to_sym.downcase.should == :"äöü"
+ "AOU".to_sym.downcase.should == :"aou"
+ end
+ end
+
it "leaves non-alphabetic ASCII characters as they were" do
"Glark?!?".to_sym.downcase.should == :"glark?!?"
end
diff --git a/spec/ruby/core/symbol/dup_spec.rb b/spec/ruby/core/symbol/dup_spec.rb
new file mode 100644
index 0000000000..2ca4d84078
--- /dev/null
+++ b/spec/ruby/core/symbol/dup_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+ruby_version_is '2.4' do
+ describe "Symbol#dup" do
+ it "returns self" do
+ :a_symbol.dup.should equal(:a_symbol)
+ end
+ end
+end
diff --git a/spec/ruby/core/symbol/swapcase_spec.rb b/spec/ruby/core/symbol/swapcase_spec.rb
index fdc42ec477..3124f782bc 100644
--- a/spec/ruby/core/symbol/swapcase_spec.rb
+++ b/spec/ruby/core/symbol/swapcase_spec.rb
@@ -28,6 +28,13 @@ describe "Symbol#swapcase" do
end
end
+ ruby_version_is '2.4' do
+ it "swaps the case for Unicode characters" do
+ "äÖü".to_sym.swapcase.should == :"ÄöÜ"
+ "aOu".to_sym.swapcase.should == :"AoU"
+ end
+ end
+
it "leaves non-alphabetic ASCII characters as they were" do
"Glark?!?".to_sym.swapcase.should == :"gLARK?!?"
end
diff --git a/spec/ruby/core/symbol/upcase_spec.rb b/spec/ruby/core/symbol/upcase_spec.rb
index fce62af100..fe2c88d294 100644
--- a/spec/ruby/core/symbol/upcase_spec.rb
+++ b/spec/ruby/core/symbol/upcase_spec.rb
@@ -16,6 +16,13 @@ describe "Symbol#upcase" do
end
end
+ ruby_version_is '2.4' do
+ it "capitalizes all Unicode characters" do
+ "äöü".to_sym.upcase.should == :"ÄÖÜ"
+ "aou".to_sym.upcase.should == :"AOU"
+ end
+ end
+
it "leaves non-alphabetic ASCII characters as they were" do
"Glark?!?".to_sym.upcase.should == :"GLARK?!?"
end
diff --git a/spec/ruby/core/thread/element_set_spec.rb b/spec/ruby/core/thread/element_set_spec.rb
index 47b4d06328..b76078f685 100644
--- a/spec/ruby/core/thread/element_set_spec.rb
+++ b/spec/ruby/core/thread/element_set_spec.rb
@@ -9,12 +9,12 @@ describe "Thread#[]=" do
it "raises a RuntimeError if the thread is frozen" do
running = false
t = Thread.new do
- Thread.pass until running
t.freeze
- t[:foo] = "bar"
+ -> {
+ t[:foo] = "bar"
+ }.should raise_error(RuntimeError, /frozen/)
end
- running = true
- lambda { t.join }.should raise_error(RuntimeError)
+ t.join
end
it "raises exceptions on the wrong type of keys" do
diff --git a/spec/ruby/core/thread/fixtures/classes.rb b/spec/ruby/core/thread/fixtures/classes.rb
index b572c8dd82..601e515e3e 100644
--- a/spec/ruby/core/thread/fixtures/classes.rb
+++ b/spec/ruby/core/thread/fixtures/classes.rb
@@ -120,7 +120,10 @@ module ThreadSpecs
end
def self.status_of_thread_with_uncaught_exception
- t = Thread.new { raise "error" }
+ t = Thread.new {
+ Thread.current.report_on_exception = false
+ raise "error"
+ }
begin
t.join
rescue RuntimeError
@@ -159,6 +162,7 @@ module ThreadSpecs
def self.dying_thread_ensures(kill_method_name=:kill)
Thread.new do
+ Thread.current.report_on_exception = false
begin
Thread.current.send(kill_method_name)
ensure
@@ -169,6 +173,7 @@ module ThreadSpecs
def self.dying_thread_with_outer_ensure(kill_method_name=:kill)
Thread.new do
+ Thread.current.report_on_exception = false
begin
begin
Thread.current.send(kill_method_name)
diff --git a/spec/ruby/core/thread/join_spec.rb b/spec/ruby/core/thread/join_spec.rb
index a6dd2da9a3..249b3d333e 100644
--- a/spec/ruby/core/thread/join_spec.rb
+++ b/spec/ruby/core/thread/join_spec.rb
@@ -46,7 +46,10 @@ describe "Thread#join" do
end
it "raises any exceptions encountered in the thread body" do
- t = Thread.new { raise NotImplementedError.new("Just kidding") }
+ t = Thread.new {
+ Thread.current.report_on_exception = false
+ raise NotImplementedError.new("Just kidding")
+ }
lambda { t.join }.should raise_error(NotImplementedError)
end
diff --git a/spec/ruby/core/thread/key_spec.rb b/spec/ruby/core/thread/key_spec.rb
index 6cdfc3ca7f..d82a21ab39 100644
--- a/spec/ruby/core/thread/key_spec.rb
+++ b/spec/ruby/core/thread/key_spec.rb
@@ -9,7 +9,7 @@ describe "Thread#key?" do
@th.join
end
- it "tests for existance of thread local variables using symbols or strings" do
+ it "tests for existence of thread local variables using symbols or strings" do
@th.key?(:oliver).should == true
@th.key?("oliver").should == true
@th.key?(:stanley).should == false
diff --git a/spec/ruby/core/thread/raise_spec.rb b/spec/ruby/core/thread/raise_spec.rb
index 93e0f048b1..8724d26202 100644
--- a/spec/ruby/core/thread/raise_spec.rb
+++ b/spec/ruby/core/thread/raise_spec.rb
@@ -51,6 +51,7 @@ describe "Thread#raise on a sleeping thread" do
it "is captured and raised by Thread#value" do
t = Thread.new do
+ Thread.current.report_on_exception = false
sleep
end
@@ -62,6 +63,7 @@ describe "Thread#raise on a sleeping thread" do
it "raises a RuntimeError when called with no arguments inside rescue" do
t = Thread.new do
+ Thread.current.report_on_exception = false
begin
1/0
rescue ZeroDivisionError
@@ -113,6 +115,7 @@ describe "Thread#raise on a running thread" do
it "can go unhandled" do
t = Thread.new do
+ Thread.current.report_on_exception = false
loop { Thread.pass }
end
@@ -123,6 +126,7 @@ describe "Thread#raise on a running thread" do
it "raises the given argument even when there is an active exception" do
raised = false
t = Thread.new do
+ Thread.current.report_on_exception = false
begin
1/0
rescue ZeroDivisionError
@@ -142,6 +146,7 @@ describe "Thread#raise on a running thread" do
it "raises a RuntimeError when called with no arguments inside rescue" do
raised = false
t = Thread.new do
+ Thread.current.report_on_exception = false
begin
1/0
rescue ZeroDivisionError
@@ -164,6 +169,7 @@ describe "Thread#raise on same thread" do
it "raises a RuntimeError when called with no arguments inside rescue" do
t = Thread.new do
+ Thread.current.report_on_exception = false
begin
1/0
rescue ZeroDivisionError
diff --git a/spec/ruby/core/thread/report_on_exception_spec.rb b/spec/ruby/core/thread/report_on_exception_spec.rb
new file mode 100644
index 0000000000..4128dad470
--- /dev/null
+++ b/spec/ruby/core/thread/report_on_exception_spec.rb
@@ -0,0 +1,102 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+ruby_version_is "2.4" do
+ describe "Thread.report_on_exception" do
+ it "defaults to false" do
+ ruby_exe("p Thread.report_on_exception").should == "false\n"
+ end
+ end
+
+ describe "Thread.report_on_exception=" do
+ before :each do
+ @report_on_exception = Thread.report_on_exception
+ end
+
+ after :each do
+ Thread.report_on_exception = @report_on_exception
+ end
+
+ it "changes the default value for new threads" do
+ Thread.report_on_exception = true
+ Thread.report_on_exception.should == true
+ t = Thread.new {}
+ t.join
+ t.report_on_exception.should == true
+ end
+ end
+
+ describe "Thread#report_on_exception" do
+ it "returns whether the Thread will print a backtrace if it exits with an exception" do
+ t = Thread.new { Thread.current.report_on_exception = true }
+ t.join
+ t.report_on_exception.should == true
+
+ t = Thread.new { Thread.current.report_on_exception = false }
+ t.join
+ t.report_on_exception.should == false
+ end
+ end
+
+ describe "Thread#report_on_exception=" do
+ describe "when set to true" do
+ it "prints a backtrace on $stderr if it terminates with an exception" do
+ t = nil
+ -> {
+ t = Thread.new {
+ Thread.current.report_on_exception = true
+ raise RuntimeError, "Thread#report_on_exception specs"
+ }
+ Thread.pass while t.alive?
+ }.should output("", /Thread.+terminated with exception.+Thread#report_on_exception specs/m)
+
+ -> {
+ t.join
+ }.should raise_error(RuntimeError, "Thread#report_on_exception specs")
+ end
+ end
+
+ describe "when set to false" do
+ it "lets the thread terminates silently with an exception" do
+ t = nil
+ -> {
+ t = Thread.new {
+ Thread.current.report_on_exception = false
+ raise RuntimeError, "Thread#report_on_exception specs"
+ }
+ Thread.pass while t.alive?
+ }.should output("", "")
+
+ -> {
+ t.join
+ }.should raise_error(RuntimeError, "Thread#report_on_exception specs")
+ end
+ end
+
+ ruby_bug "#13163", "2.4"..."2.5" do
+ describe "when used in conjunction with Thread#abort_on_exception" do
+ it "first reports then send the exception back to the main Thread" do
+ t = nil
+ mutex = Mutex.new
+ mutex.lock
+ -> {
+ t = Thread.new {
+ Thread.current.abort_on_exception = true
+ Thread.current.report_on_exception = true
+ mutex.lock
+ mutex.unlock
+ raise RuntimeError, "Thread#report_on_exception specs"
+ }
+
+ -> {
+ mutex.sleep(5)
+ }.should raise_error(RuntimeError, "Thread#report_on_exception specs")
+ }.should output("", /Thread.+terminated with exception.+Thread#report_on_exception specs/m)
+
+ -> {
+ t.join
+ }.should raise_error(RuntimeError, "Thread#report_on_exception specs")
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/thread/shared/exit.rb b/spec/ruby/core/thread/shared/exit.rb
index f15da360fd..0c9198c538 100644
--- a/spec/ruby/core/thread/shared/exit.rb
+++ b/spec/ruby/core/thread/shared/exit.rb
@@ -112,7 +112,7 @@ describe :thread_exit, shared: true do
quarantine! do
- it "propogates inner exception to Thread.join if there is an outer ensure clause" do
+ it "propagates inner exception to Thread.join if there is an outer ensure clause" do
thread = ThreadSpecs.dying_thread_with_outer_ensure(@method) { }
lambda { thread.join }.should raise_error(RuntimeError, "In dying thread")
end
diff --git a/spec/ruby/core/thread/value_spec.rb b/spec/ruby/core/thread/value_spec.rb
index 82c0cbf762..3d900959df 100644
--- a/spec/ruby/core/thread/value_spec.rb
+++ b/spec/ruby/core/thread/value_spec.rb
@@ -7,7 +7,10 @@ describe "Thread#value" do
end
it "re-raises an error for an uncaught exception" do
- t = Thread.new { raise "Hello" }
+ t = Thread.new {
+ Thread.current.report_on_exception = false
+ raise "Hello"
+ }
lambda { t.value }.should raise_error(RuntimeError, "Hello")
end
diff --git a/spec/ruby/core/time/shared/now.rb b/spec/ruby/core/time/shared/now.rb
index f570aeedd2..c35115fcf4 100644
--- a/spec/ruby/core/time/shared/now.rb
+++ b/spec/ruby/core/time/shared/now.rb
@@ -5,4 +5,16 @@ describe :time_now, shared: true do
TimeSpecs::SubTime.send(@method).should be_an_instance_of(TimeSpecs::SubTime)
TimeSpecs::MethodHolder.send(@method).should be_an_instance_of(Time)
end
+
+ it "sets the current time" do
+ now = TimeSpecs::MethodHolder.send(@method)
+ now.to_f.should be_close(Process.clock_gettime(Process::CLOCK_REALTIME), 10.0)
+ end
+
+ it "uses the local timezone" do
+ with_timezone("PDT", -8) do
+ now = TimeSpecs::MethodHolder.send(@method)
+ now.utc_offset.should == (-8 * 60 * 60)
+ end
+ end
end
diff --git a/spec/ruby/core/time/shared/time_params.rb b/spec/ruby/core/time/shared/time_params.rb
index 87b52d9f8d..120d8d3af1 100644
--- a/spec/ruby/core/time/shared/time_params.rb
+++ b/spec/ruby/core/time/shared/time_params.rb
@@ -116,10 +116,8 @@ describe :time_params, shared: true do
end
it "interprets all numerals as base 10" do
- Time.send(@method, "2000", "08", "08", "08", "08", "08").should ==
- Time.send(@method, 2000, 8, 8, 8, 8, 8)
- Time.send(@method, "2000", "09", "09", "09", "09", "09").should ==
- Time.send(@method, 2000, 9, 9, 9, 9, 9)
+ Time.send(@method, "2000", "08", "08", "08", "08", "08").should == Time.send(@method, 2000, 8, 8, 8, 8, 8)
+ Time.send(@method, "2000", "09", "09", "09", "09", "09").should == Time.send(@method, 2000, 9, 9, 9, 9, 9)
end
it "handles fractional seconds as a Float" do
diff --git a/spec/ruby/core/tracepoint/callee_id_spec.rb b/spec/ruby/core/tracepoint/callee_id_spec.rb
new file mode 100644
index 0000000000..b7571027d6
--- /dev/null
+++ b/spec/ruby/core/tracepoint/callee_id_spec.rb
@@ -0,0 +1,20 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require File.expand_path('../fixtures/classes', __FILE__)
+
+ruby_version_is '2.4' do
+ describe "TracePoint#callee_id" do
+ it "returns the called name of the method being called" do
+ a = []
+ obj = TracePointSpec::ClassWithMethodAlias.new
+
+ TracePoint.new(:call) do |tp|
+ a << tp.callee_id
+ end.enable do
+ obj.m_alias
+ end
+
+ a.should == [:m_alias]
+ end
+ end
+end
+
diff --git a/spec/ruby/core/tracepoint/fixtures/classes.rb b/spec/ruby/core/tracepoint/fixtures/classes.rb
new file mode 100644
index 0000000000..fd22ac319d
--- /dev/null
+++ b/spec/ruby/core/tracepoint/fixtures/classes.rb
@@ -0,0 +1,8 @@
+module TracePointSpec
+ class ClassWithMethodAlias
+ def m
+ end
+ alias_method :m_alias, :m
+ end
+end
+
diff --git a/spec/ruby/core/true/dup_spec.rb b/spec/ruby/core/true/dup_spec.rb
new file mode 100644
index 0000000000..cdf60e5bd6
--- /dev/null
+++ b/spec/ruby/core/true/dup_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+
+ruby_version_is '2.4' do
+ describe "TrueClass#dup" do
+ it "returns self" do
+ true.dup.should equal(true)
+ end
+ end
+end
diff --git a/spec/ruby/core/warning/warn_spec.rb b/spec/ruby/core/warning/warn_spec.rb
new file mode 100644
index 0000000000..44e9eb707b
--- /dev/null
+++ b/spec/ruby/core/warning/warn_spec.rb
@@ -0,0 +1,60 @@
+require File.expand_path("../../../spec_helper", __FILE__)
+
+describe "Warning.warn" do
+ ruby_version_is "2.4" do
+ it "complains" do
+ -> {
+ Warning.warn("Chunky bacon!")
+ }.should complain("Chunky bacon!")
+ end
+
+ it "extends itself" do
+ Warning.singleton_class.ancestors.should include(Warning)
+ end
+
+ it "has Warning as the method owner" do
+ ruby_exe("p Warning.method(:warn).owner").should == "Warning\n"
+ end
+
+ it "can be overridden" do
+ code = <<-RUBY
+ $stdout.sync = true
+ $stderr.sync = true
+ def Warning.warn(msg)
+ if msg.start_with?("A")
+ puts msg.upcase
+ else
+ super
+ end
+ end
+ Warning.warn("A warning!")
+ Warning.warn("warning from stderr\n")
+ RUBY
+ ruby_exe(code, args: "2>&1").should == %Q[A WARNING!\nwarning from stderr\n]
+ end
+
+ it "is called by parser warnings" do
+ Warning.should_receive(:warn)
+ verbose = $VERBOSE
+ $VERBOSE = false
+ begin
+ eval "{ key: :value, key: :value2 }"
+ ensure
+ $VERBOSE = verbose
+ end
+ end
+ end
+
+ ruby_version_is "2.5" do
+ it "is called by Kernel.warn" do
+ Warning.should_receive(:warn)
+ verbose = $VERBOSE
+ $VERBOSE = false
+ begin
+ Kernel.warn("Chunky bacon!")
+ ensure
+ $VERBOSE = verbose
+ end
+ end
+ end
+end
diff --git a/spec/ruby/language/README b/spec/ruby/language/README
index b9d969ba1e..74eaf58709 100644
--- a/spec/ruby/language/README
+++ b/spec/ruby/language/README
@@ -6,7 +6,7 @@ execution like 'if' and 'unless', exceptional execution control like 'rescue',
etc. There are also literals for the basic "types" like String, Regexp, Array
and Fixnum.
-Behavorial specifications describe the behavior of concrete entities. Rather
+Behavioral specifications describe the behavior of concrete entities. Rather
than using concepts of computation to organize these spec files, we use
entities of the Ruby language. Consider looking at any syntactic element of a
Ruby program. With (almost) no ambiguity, one can identify it as a literal,
diff --git a/spec/ruby/language/block_spec.rb b/spec/ruby/language/block_spec.rb
index 219d61e2bf..733e90211c 100644
--- a/spec/ruby/language/block_spec.rb
+++ b/spec/ruby/language/block_spec.rb
@@ -687,7 +687,7 @@ describe "Block-local variables" do
end.should raise_error(SyntaxError)
end
- it "need not be preceeded by standard parameters" do
+ it "need not be preceded by standard parameters" do
[1].map {|; foo| foo }.should == [nil]
[1].map {|; glark, bar| [glark, bar] }.should == [[nil, nil]]
end
diff --git a/spec/ruby/language/break_spec.rb b/spec/ruby/language/break_spec.rb
index 794eed2dd9..da3c3bd272 100644
--- a/spec/ruby/language/break_spec.rb
+++ b/spec/ruby/language/break_spec.rb
@@ -63,15 +63,14 @@ describe "The break statement in a captured block" do
describe "from another thread" do
it "raises a LocalJumpError when getting the value from another thread" do
- ScratchPad << :a
thread_with_break = Thread.new do
- ScratchPad << :b
- break :break
- ScratchPad << :c
+ begin
+ break :break
+ rescue LocalJumpError => e
+ e
+ end
end
-
- lambda { thread_with_break.value }.should raise_error(LocalJumpError)
- ScratchPad.recorded.should == [:a, :b]
+ thread_with_break.value.should be_an_instance_of(LocalJumpError)
end
end
end
diff --git a/spec/ruby/language/case_spec.rb b/spec/ruby/language/case_spec.rb
index cb0e8150bf..25f5d0efc4 100644
--- a/spec/ruby/language/case_spec.rb
+++ b/spec/ruby/language/case_spec.rb
@@ -379,4 +379,11 @@ describe "The 'case'-construct with no target expression" do
:called
end.should == :called
end
+
+ it "accepts complex expressions within ()" do
+ case 'a'
+ when (raise if 2+2 == 3; /a/)
+ :called
+ end.should == :called
+ end
end
diff --git a/spec/ruby/language/class_spec.rb b/spec/ruby/language/class_spec.rb
index 354570e5e9..ba4af3d880 100644
--- a/spec/ruby/language/class_spec.rb
+++ b/spec/ruby/language/class_spec.rb
@@ -88,19 +88,17 @@ describe "A class definition" do
end
# [Bug #12367] [ruby-core:75446]
- ruby_version_is "2.4" do # Until backported
- it "raises an error when reopening a class with Object as superclass" do
- module ClassSpecs
- class SuperclassReopenedObject < A
- end
- SuperclassReopenedObject.superclass.should == A
-
- lambda {
- class SuperclassReopenedObject < Object
- end
- }.should raise_error(TypeError, /superclass mismatch/)
- SuperclassReopenedObject.superclass.should == A
+ it "raises an error when reopening a class with Object as superclass" do
+ module ClassSpecs
+ class SuperclassReopenedObject < A
end
+ SuperclassReopenedObject.superclass.should == A
+
+ lambda {
+ class SuperclassReopenedObject < Object
+ end
+ }.should raise_error(TypeError, /superclass mismatch/)
+ SuperclassReopenedObject.superclass.should == A
end
end
diff --git a/spec/ruby/language/constants_spec.rb b/spec/ruby/language/constants_spec.rb
index e68ba495be..1d3cecd9c6 100644
--- a/spec/ruby/language/constants_spec.rb
+++ b/spec/ruby/language/constants_spec.rb
@@ -353,16 +353,27 @@ describe "Constant resolution within methods" do
end
describe "with ||=" do
- it "assignes constant if previously undefined" do
+ it "assigns a scoped constant if previously undefined" do
ConstantSpecs.should_not have_constant(:OpAssignUndefined)
- # Literally opening the module is required to avoid content
- # re-assignment error
module ConstantSpecs
OpAssignUndefined ||= 42
end
ConstantSpecs::OpAssignUndefined.should == 42
+ ConstantSpecs::OpAssignUndefinedOutside ||= 42
+ ConstantSpecs::OpAssignUndefinedOutside.should == 42
ConstantSpecs.send(:remove_const, :OpAssignUndefined)
+ ConstantSpecs.send(:remove_const, :OpAssignUndefinedOutside)
end
+
+ it "assigns a global constant if previously undefined" do
+ OpAssignGlobalUndefined ||= 42
+ ::OpAssignGlobalUndefinedExplicitScope ||= 42
+ OpAssignGlobalUndefined.should == 42
+ ::OpAssignGlobalUndefinedExplicitScope.should == 42
+ Object.send :remove_const, :OpAssignGlobalUndefined
+ Object.send :remove_const, :OpAssignGlobalUndefinedExplicitScope
+ end
+
end
end
diff --git a/spec/ruby/language/defined_spec.rb b/spec/ruby/language/defined_spec.rb
index 458c74258f..1247658381 100644
--- a/spec/ruby/language/defined_spec.rb
+++ b/spec/ruby/language/defined_spec.rb
@@ -725,7 +725,7 @@ describe "The defined? keyword for a top-level constant" do
defined?(::DefinedSpecs).should == "constant"
end
- it "retuns nil if the constant is not defined" do
+ it "returns nil if the constant is not defined" do
defined?(::DefinedSpecsUndefined).should be_nil
end
diff --git a/spec/ruby/language/ensure_spec.rb b/spec/ruby/language/ensure_spec.rb
index 13575fccc5..ae04feb739 100644
--- a/spec/ruby/language/ensure_spec.rb
+++ b/spec/ruby/language/ensure_spec.rb
@@ -11,7 +11,7 @@ describe "An ensure block inside a begin block" do
lambda {
begin
ScratchPad << :begin
- raise "An exception occured!"
+ raise "An exception occurred!"
ensure
ScratchPad << :ensure
end
@@ -25,7 +25,7 @@ describe "An ensure block inside a begin block" do
begin
begin
ScratchPad << :begin
- raise "An exception occured!"
+ raise "An exception occurred!"
rescue
ScratchPad << :rescue
ensure
diff --git a/spec/ruby/language/fixtures/binary_symbol.rb b/spec/ruby/language/fixtures/binary_symbol.rb
new file mode 100644
index 0000000000..2ddf565820
--- /dev/null
+++ b/spec/ruby/language/fixtures/binary_symbol.rb
@@ -0,0 +1,4 @@
+# encoding: binary
+
+p :il_était.to_s.bytes
+puts :il_était.encoding.name
diff --git a/spec/ruby/language/fixtures/super.rb b/spec/ruby/language/fixtures/super.rb
index 4e89d59bed..09a454bdf4 100644
--- a/spec/ruby/language/fixtures/super.rb
+++ b/spec/ruby/language/fixtures/super.rb
@@ -478,20 +478,129 @@ module Super
end
end
- module KeywordArguments
- class A
+ module Keywords
+ class Arguments
def foo(**args)
args
end
end
- class B < A
- def foo(**)
+ # ----
+
+ class RequiredArguments < Arguments
+ def foo(a:)
super
end
end
- class C < A
+ class OptionalArguments < Arguments
+ def foo(b: 'b')
+ super
+ end
+ end
+
+ class PlaceholderArguments < Arguments
+ def foo(**args)
+ super
+ end
+ end
+
+ # ----
+
+ class RequiredAndOptionalArguments < Arguments
+ def foo(a:, b: 'b')
+ super
+ end
+ end
+
+ class RequiredAndPlaceholderArguments < Arguments
+ def foo(a:, **args)
+ super
+ end
+ end
+
+ class OptionalAndPlaceholderArguments < Arguments
+ def foo(b: 'b', **args)
+ super
+ end
+ end
+
+ # ----
+
+ class RequiredAndOptionalAndPlaceholderArguments < Arguments
+ def foo(a:, b: 'b', **args)
+ super
+ end
+ end
+ end
+
+ module RegularAndKeywords
+ class Arguments
+ def foo(a, **options)
+ [a, options]
+ end
+ end
+
+ # -----
+
+ class RequiredArguments < Arguments
+ def foo(a, b:)
+ super
+ end
+ end
+
+ class OptionalArguments < Arguments
+ def foo(a, c: 'c')
+ super
+ end
+ end
+
+ class PlaceholderArguments < Arguments
+ def foo(a, **options)
+ super
+ end
+ end
+
+ # -----
+
+ class RequiredAndOptionalArguments < Arguments
+ def foo(a, b:, c: 'c')
+ super
+ end
+ end
+
+ class RequiredAndPlaceholderArguments < Arguments
+ def foo(a, b:, **options)
+ super
+ end
+ end
+
+ class OptionalAndPlaceholderArguments < Arguments
+ def foo(a, c: 'c', **options)
+ super
+ end
+ end
+
+ # -----
+
+ class RequiredAndOptionalAndPlaceholderArguments < Arguments
+ def foo(a, b:, c: 'c', **options)
+ super
+ end
+ end
+ end
+
+ module SplatAndKeywords
+ class Arguments
+ def foo(*args, **options)
+ [args, options]
+ end
+ end
+
+ class AllArguments < Arguments
+ def foo(*args, **options)
+ super
+ end
end
end
@@ -552,18 +661,4 @@ module Super
end
end
end
-
- module SplatAndKeyword
- class A
- def foo(*args, **options)
- [args, options]
- end
- end
-
- class B < A
- def foo(*args, **options)
- super
- end
- end
- end
end
diff --git a/spec/ruby/language/if_spec.rb b/spec/ruby/language/if_spec.rb
index bd4fdcae81..284d852462 100644
--- a/spec/ruby/language/if_spec.rb
+++ b/spec/ruby/language/if_spec.rb
@@ -1,6 +1,25 @@
require File.expand_path('../../spec_helper', __FILE__)
describe "The if expression" do
+ ruby_version_is '2.4' do
+ describe "accepts multiple assignments in conditional expression" do
+ before(:each) { ScratchPad.record([]) }
+ after(:each) { ScratchPad.clear }
+
+ it 'with non-nil values' do
+ ary = [1, 2]
+ eval "if (a, b = ary); ScratchPad.record [a, b]; end"
+ ScratchPad.recorded.should == [1, 2]
+ end
+
+ it 'with nil values' do
+ ary = nil
+ eval "if (a, b = ary); else; ScratchPad.record [a, b]; end"
+ ScratchPad.recorded.should == [nil, nil]
+ end
+ end
+ end
+
it "evaluates body if expression is true" do
a = []
if true
diff --git a/spec/ruby/language/method_spec.rb b/spec/ruby/language/method_spec.rb
index c92a8ee51b..ca939dbab6 100644
--- a/spec/ruby/language/method_spec.rb
+++ b/spec/ruby/language/method_spec.rb
@@ -1178,7 +1178,7 @@ describe "A method" do
end
evaluate <<-ruby do
- def m a, b=1, *c, d, e:, f: 2, g:, **k, &l
+ def m(a, b=1, *c, d, e:, f: 2, g:, **k, &l)
[a, b, c, d, e, f, g, k, l]
end
ruby
@@ -1188,13 +1188,19 @@ describe "A method" do
end
evaluate <<-ruby do
- def m (a, b = nil, c = nil, d, e: nil, **f)
+ def m(a, b = nil, c = nil, d, e: nil, **f)
[a, b, c, d, e, f]
end
ruby
result = m(1, 2)
result.should == [1, nil, nil, 2, nil, {}]
+
+ result = m(1, 2, {foo: :bar})
+ result.should == [1, nil, nil, 2, nil, {foo: :bar}]
+
+ result = m(1, {foo: :bar})
+ result.should == [1, nil, nil, {foo: :bar}, nil, {}]
end
end
end
diff --git a/spec/ruby/language/optional_assignments_spec.rb b/spec/ruby/language/optional_assignments_spec.rb
index c104d08253..0ab28985ed 100644
--- a/spec/ruby/language/optional_assignments_spec.rb
+++ b/spec/ruby/language/optional_assignments_spec.rb
@@ -207,7 +207,7 @@ describe 'Optional variable assignments' do
Object::A.should == 10
end
- it 'with &&= assignments will fail with non-existant constants' do
+ it 'with &&= assignments will fail with non-existent constants' do
lambda { Object::A &&= 10 }.should raise_error(NameError)
end
@@ -219,7 +219,7 @@ describe 'Optional variable assignments' do
Object::A.should == 30
end
- it 'with operator assignments will fail with non-existant constants' do
+ it 'with operator assignments will fail with non-existent constants' do
lambda { Object::A += 10 }.should raise_error(NameError)
end
end
diff --git a/spec/ruby/language/predefined_spec.rb b/spec/ruby/language/predefined_spec.rb
index a0930eb214..f827fb2eb5 100644
--- a/spec/ruby/language/predefined_spec.rb
+++ b/spec/ruby/language/predefined_spec.rb
@@ -879,6 +879,25 @@ describe "Global variable $-d" do
end
end
+describe "Global variable $VERBOSE" do
+ it "converts truthy values to true" do
+ [true, 1, 0, [], ""].each do |true_value|
+ $VERBOSE = true_value
+ $VERBOSE.should be_true
+ end
+ end
+
+ it "allows false" do
+ $VERBOSE = false
+ $VERBOSE.should be_false
+ end
+
+ it "allows nil without coercing to false" do
+ $VERBOSE = nil
+ $VERBOSE.should be_nil
+ end
+end
+
describe :verbose_global_alias, shared: true do
before :each do
@verbose = $VERBOSE
diff --git a/spec/ruby/language/regexp/character_classes_spec.rb b/spec/ruby/language/regexp/character_classes_spec.rb
index 74568a0beb..ce66d8e65f 100644
--- a/spec/ruby/language/regexp/character_classes_spec.rb
+++ b/spec/ruby/language/regexp/character_classes_spec.rb
@@ -1,3 +1,4 @@
+# coding: utf-8
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../../fixtures/classes', __FILE__)
@@ -607,4 +608,26 @@ describe "Regexp with character classes" do
it "matches unicode Hangul properties" do
"루비(Ruby)".match(/\p{Hangul}+/u).to_a.should == ["루비"]
end
+
+ ruby_version_is "2.4" do
+ it "supports \\X (unicode 9.0 with UTR #51 workarounds)" do
+ # simple emoji without any fancy modifier or ZWJ
+ /\X/.match("\u{1F98A}").to_a.should == ["🦊"]
+
+ # skin tone modifier
+ /\X/.match("\u{1F918}\u{1F3FD}").to_a.should == ["🤘🏽"]
+
+ # emoji joined with ZWJ
+ /\X/.match("\u{1F3F3}\u{FE0F}\u{200D}\u{1F308}").to_a.should == ["🏳️‍🌈"]
+ /\X/.match("\u{1F469}\u{200D}\u{1F469}\u{200D}\u{1F467}\u{200D}\u{1F466}").to_a.should == ["👩‍👩‍👧‍👦"]
+
+ # without the ZWJ
+ /\X+/.match("\u{1F3F3}\u{FE0F}\u{1F308}").to_a.should == ["🏳️🌈"]
+ /\X+/.match("\u{1F469}\u{1F469}\u{1F467}\u{1F466}").to_a.should == ["👩👩👧👦"]
+
+ # both of the ZWJ combined
+ /\X+/.match("\u{1F3F3}\u{FE0F}\u{200D}\u{1F308}\u{1F469}\u{200D}\u{1F469}\u{200D}\u{1F467}\u{200D}\u{1F466}")
+ .to_a.should == ["🏳️‍🌈👩‍👩‍👧‍👦"]
+ end
+ end
end
diff --git a/spec/ruby/language/regexp/modifiers_spec.rb b/spec/ruby/language/regexp/modifiers_spec.rb
index 03dec26f3f..a7052a941c 100644
--- a/spec/ruby/language/regexp/modifiers_spec.rb
+++ b/spec/ruby/language/regexp/modifiers_spec.rb
@@ -39,6 +39,13 @@ describe "Regexps with modifers" do
lambda { eval('/foo/a') }.should raise_error(SyntaxError)
end
+ ruby_version_is "2.4" do
+ it "supports (?~) (absent operator)" do
+ Regexp.new("(?~foo)").match("hello").to_a.should == ["hello"]
+ "foo".scan(Regexp.new("(?~foo)")).should == ["fo","o",""]
+ end
+ end
+
it "supports (?imx-imx) (inline modifiers)" do
/(?i)foo/.match("FOO").to_a.should == ["FOO"]
/foo(?i)/.match("FOO").should be_nil
diff --git a/spec/ruby/language/rescue_spec.rb b/spec/ruby/language/rescue_spec.rb
index 66366cd1a0..281bb8fde8 100644
--- a/spec/ruby/language/rescue_spec.rb
+++ b/spec/ruby/language/rescue_spec.rb
@@ -290,4 +290,11 @@ describe "The rescue keyword" do
:expected
end.should == :expected
end
+
+ ruby_version_is "2.4" do
+ it "allows 'rescue' in method arguments" do
+ two = eval '1.+ (raise("Error") rescue 1)'
+ two.should == 2
+ end
+ end
end
diff --git a/spec/ruby/language/return_spec.rb b/spec/ruby/language/return_spec.rb
index 323f74aad3..6a98fa6d12 100644
--- a/spec/ruby/language/return_spec.rb
+++ b/spec/ruby/language/return_spec.rb
@@ -24,7 +24,14 @@ describe "The return keyword" do
describe "in a Thread" do
it "raises a LocalJumpError if used to exit a thread" do
- lambda { Thread.new { return }.join }.should raise_error(LocalJumpError)
+ t = Thread.new {
+ begin
+ return
+ rescue LocalJumpError => e
+ e
+ end
+ }
+ t.value.should be_an_instance_of(LocalJumpError)
end
end
@@ -242,4 +249,218 @@ describe "The return keyword" do
ReturnSpecs::MethodWithBlock.new.method2.should == [0, 1, 2]
end
end
+
+ ruby_version_is '2.4.2' do
+ describe "at top level" do
+ before :each do
+ @filename = tmp("top_return.rb")
+ ScratchPad.record []
+ end
+
+ after do
+ rm_r @filename
+ end
+
+ it "stops file execution" do
+ ruby_exe(<<-END_OF_CODE).should == "before return\n"
+ puts "before return"
+ return
+
+ puts "after return"
+ END_OF_CODE
+
+ $?.exitstatus.should == 0
+ end
+
+ describe "within if" do
+ it "is allowed" do
+ File.write(@filename, <<-END_OF_CODE)
+ ScratchPad << "before if"
+ if true
+ return
+ end
+
+ ScratchPad << "after if"
+ END_OF_CODE
+
+ load @filename
+ ScratchPad.recorded.should == ["before if"]
+ end
+ end
+
+ describe "within while loop" do
+ it "is allowed" do
+ File.write(@filename, <<-END_OF_CODE)
+ ScratchPad << "before while"
+ while true
+ return
+ end
+
+ ScratchPad << "after while"
+ END_OF_CODE
+
+ load @filename
+ ScratchPad.recorded.should == ["before while"]
+ end
+ end
+
+ describe "within a begin" do
+ it "is allowed in begin block" do
+ File.write(@filename, <<-END_OF_CODE)
+ ScratchPad << "before begin"
+ begin
+ return
+ end
+
+ ScratchPad << "after begin"
+ END_OF_CODE
+
+ load @filename
+ ScratchPad.recorded.should == ["before begin"]
+ end
+
+ it "is allowed in ensure block" do
+ File.write(@filename, <<-END_OF_CODE)
+ ScratchPad << "before begin"
+ begin
+ ensure
+ return
+ end
+
+ ScratchPad << "after begin"
+ END_OF_CODE
+
+ load @filename
+ ScratchPad.recorded.should == ["before begin"]
+ end
+
+ it "is allowed in rescue block" do
+ File.write(@filename, <<-END_OF_CODE)
+ ScratchPad << "before begin"
+ begin
+ raise
+ rescue RuntimeError
+ return
+ end
+
+ ScratchPad << "after begin"
+ END_OF_CODE
+
+ load @filename
+ ScratchPad.recorded.should == ["before begin"]
+ end
+
+ it "fires ensure block before returning" do
+ ruby_exe(<<-END_OF_CODE).should == "within ensure\n"
+ begin
+ return
+ ensure
+ puts "within ensure"
+ end
+
+ puts "after begin"
+ END_OF_CODE
+ end
+
+ ruby_bug "#14061", "2.4"..."2.6" do
+ it "fires ensure block before returning while loads file" do
+ File.write(@filename, <<-END_OF_CODE)
+ ScratchPad << "before begin"
+ begin
+ return
+ ensure
+ ScratchPad << "within ensure"
+ end
+
+ ScratchPad << "after begin"
+ END_OF_CODE
+
+ load @filename
+ ScratchPad.recorded.should == ["before begin", "within ensure"]
+ end
+ end
+
+ it "swallows exception if returns in ensure block" do
+ File.write(@filename, <<-END_OF_CODE)
+ begin
+ raise
+ ensure
+ ScratchPad << "before return"
+ return
+ end
+ END_OF_CODE
+
+ load @filename
+ ScratchPad.recorded.should == ["before return"]
+ end
+ end
+
+ describe "within a block" do
+ it "is allowed" do
+ File.write(@filename, <<-END_OF_CODE)
+ ScratchPad << "before call"
+ proc { return }.call
+
+ ScratchPad << "after call"
+ END_OF_CODE
+
+ load @filename
+ ScratchPad.recorded.should == ["before call"]
+ end
+ end
+
+ describe "within a class" do
+ it "is allowed" do
+ File.write(@filename, <<-END_OF_CODE)
+ class A
+ ScratchPad << "before return"
+ return
+
+ ScratchPad << "after return"
+ end
+ END_OF_CODE
+
+ load @filename
+ ScratchPad.recorded.should == ["before return"]
+ end
+ end
+
+ describe "file loading" do
+ it "stops file loading and execution" do
+ File.write(@filename, <<-END_OF_CODE)
+ ScratchPad << "before return"
+ return
+ ScratchPad << "after return"
+ END_OF_CODE
+
+ load @filename
+ ScratchPad.recorded.should == ["before return"]
+ end
+ end
+
+ describe "file requiring" do
+ it "stops file loading and execution" do
+ File.write(@filename, <<-END_OF_CODE)
+ ScratchPad << "before return"
+ return
+ ScratchPad << "after return"
+ END_OF_CODE
+
+ require @filename
+ ScratchPad.recorded.should == ["before return"]
+ end
+ end
+
+ describe "return with argument" do
+ # https://bugs.ruby-lang.org/issues/14062
+ it "does not affect exit status" do
+ ruby_exe(<<-END_OF_CODE).should == ""
+ return 10
+ END_OF_CODE
+
+ $?.exitstatus.should == 0
+ end
+ end
+ end
+ end
end
diff --git a/spec/ruby/language/super_spec.rb b/spec/ruby/language/super_spec.rb
index fb7e089fb4..3d3f5d6f74 100644
--- a/spec/ruby/language/super_spec.rb
+++ b/spec/ruby/language/super_spec.rb
@@ -9,7 +9,7 @@ describe "The super keyword" do
Super::S1::B.new.bar([]).should == ["B#bar","A#bar"]
end
- it "searches the full inheritence chain" do
+ it "searches the full inheritance chain" do
Super::S2::B.new.foo([]).should == ["B#foo","A#baz"]
Super::S2::B.new.baz([]).should == ["A#baz"]
Super::S2::C.new.foo([]).should == ["B#foo","C#baz","A#baz"]
@@ -32,7 +32,7 @@ describe "The super keyword" do
Super::MS1::B.new.bar([]).should == ["ModB#bar","ModA#bar"]
end
- it "searches the full inheritence chain including modules" do
+ it "searches the full inheritance chain including modules" do
Super::MS2::B.new.foo([]).should == ["ModB#foo","A#baz"]
Super::MS2::B.new.baz([]).should == ["A#baz"]
Super::MS2::C.new.baz([]).should == ["C#baz","A#baz"]
@@ -248,35 +248,112 @@ describe "The super keyword" do
end
describe 'when using keyword arguments' do
- it 'passes any given keyword arguments to the parent' do
- b = Super::KeywordArguments::B.new
- b.foo(:number => 10).should == {:number => 10}
+ before :each do
+ @req = Super::Keywords::RequiredArguments.new
+ @opts = Super::Keywords::OptionalArguments.new
+ @etc = Super::Keywords::PlaceholderArguments.new
+
+ @req_and_opts = Super::Keywords::RequiredAndOptionalArguments.new
+ @req_and_etc = Super::Keywords::RequiredAndPlaceholderArguments.new
+ @opts_and_etc = Super::Keywords::OptionalAndPlaceholderArguments.new
+
+ @req_and_opts_and_etc = Super::Keywords::RequiredAndOptionalAndPlaceholderArguments.new
end
- it "passes any given keyword arguments including optional and required ones to the parent" do
- class Super::KeywordArguments::C
- eval <<-RUBY
- def foo(a:, b: 'b', **)
- super
- end
- RUBY
+ it 'does not pass any arguments to the parent when none are given' do
+ @etc.foo.should == {}
+ end
+
+ it 'passes only required arguments to the parent when no optional arguments are given' do
+ [@req, @req_and_etc].each do |obj|
+ obj.foo(a: 'a').should == {a: 'a'}
+ end
+ end
+
+ it 'passes default argument values to the parent' do
+ [@opts, @opts_and_etc].each do |obj|
+ obj.foo.should == {b: 'b'}
+ end
+
+ [@req_and_opts, @opts_and_etc, @req_and_opts_and_etc].each do |obj|
+ obj.foo(a: 'a').should == {a: 'a', b: 'b'}
+ end
+ end
+
+ it 'passes any given arguments including optional keyword arguments to the parent' do
+ [@etc, @req_and_opts, @req_and_etc, @opts_and_etc, @req_and_opts_and_etc].each do |obj|
+ obj.foo(a: 'a', b: 'b').should == {a: 'a', b: 'b'}
end
- c = Super::KeywordArguments::C.new
- c.foo(a: 'a', c: 'c').should == {a: 'a', b: 'b', c: 'c'}
+ [@etc, @req_and_etc, @opts_and_etc, @req_and_opts_and_etc].each do |obj|
+ obj.foo(a: 'a', b: 'b', c: 'c').should == {a: 'a', b: 'b', c: 'c'}
+ end
end
+ end
- it 'does not pass any keyword arguments to the parent when none are given' do
- b = Super::KeywordArguments::B.new
- b.foo.should == {}
+ describe 'when using regular and keyword arguments' do
+ before :each do
+ @req = Super::RegularAndKeywords::RequiredArguments.new
+ @opts = Super::RegularAndKeywords::OptionalArguments.new
+ @etc = Super::RegularAndKeywords::PlaceholderArguments.new
+
+ @req_and_opts = Super::RegularAndKeywords::RequiredAndOptionalArguments.new
+ @req_and_etc = Super::RegularAndKeywords::RequiredAndPlaceholderArguments.new
+ @opts_and_etc = Super::RegularAndKeywords::OptionalAndPlaceholderArguments.new
+
+ @req_and_opts_and_etc = Super::RegularAndKeywords::RequiredAndOptionalAndPlaceholderArguments.new
end
- describe 'when using splat arguments' do
- it 'passes splat arguments and keyword arguments to the parent' do
- b = Super::SplatAndKeyword::B.new
+ it 'passes only required regular arguments to the parent when no optional keyword arguments are given' do
+ @etc.foo('a').should == ['a', {}]
+ end
- b.foo('bar', baz: true).should == [['bar'], {baz: true}]
+ it 'passes only required regular and keyword arguments to the parent when no optional keyword arguments are given' do
+ [@req, @req_and_etc].each do |obj|
+ obj.foo('a', b: 'b').should == ['a', {b: 'b'}]
end
end
+
+ it 'passes default argument values to the parent' do
+ [@opts, @opts_and_etc].each do |obj|
+ obj.foo('a').should == ['a', {c: 'c'}]
+ end
+
+ [@req_and_opts, @opts_and_etc, @req_and_opts_and_etc].each do |obj|
+ obj.foo('a', b: 'b').should == ['a', {b: 'b', c: 'c'}]
+ end
+ end
+
+ it 'passes any given regular and keyword arguments including optional keyword arguments to the parent' do
+ [@etc, @req_and_opts, @req_and_etc, @opts_and_etc, @req_and_opts_and_etc].each do |obj|
+ obj.foo('a', b: 'b', c: 'c').should == ['a', {b: 'b', c: 'c'}]
+ end
+
+ [@etc, @req_and_etc, @opts_and_etc, @req_and_opts_and_etc].each do |obj|
+ obj.foo('a', b: 'b', c: 'c', d: 'd').should == ['a', {b: 'b', c: 'c', d: 'd'}]
+ end
+ end
+ end
+
+ describe 'when using splat and keyword arguments' do
+ before :each do
+ @all = Super::SplatAndKeywords::AllArguments.new
+ end
+
+ it 'does not pass any arguments to the parent when none are given' do
+ @all.foo.should == [[], {}]
+ end
+
+ it 'passes only splat arguments to the parent when no keyword arguments are given' do
+ @all.foo('a').should == [['a'], {}]
+ end
+
+ it 'passes only keyword arguments to the parent when no splat arguments are given' do
+ @all.foo(b: 'b').should == [[], {b: 'b'}]
+ end
+
+ it 'passes any given splat and keyword arguments to the parent' do
+ @all.foo('a', b: 'b').should == [['a'], {b: 'b'}]
+ end
end
end
diff --git a/spec/ruby/language/symbol_spec.rb b/spec/ruby/language/symbol_spec.rb
index 41be5b2236..90540f7d1d 100644
--- a/spec/ruby/language/symbol_spec.rb
+++ b/spec/ruby/language/symbol_spec.rb
@@ -36,6 +36,11 @@ describe "A Symbol literal" do
}
end
+ it 'inherits the encoding of the magic comment and can have a binary encoding' do
+ ruby_exe(fixture(__FILE__, "binary_symbol.rb"))
+ .should == "[105, 108, 95, 195, 169, 116, 97, 105, 116]\nASCII-8BIT\n"
+ end
+
it "may contain '::' in the string" do
:'Some::Class'.should be_kind_of(Symbol)
end
@@ -90,4 +95,12 @@ describe "A Symbol literal" do
it "can be created from list syntax %I{a b c} with interpolation" do
%I{a b #{"c"}}.should == [:a, :b, :c]
end
+
+ it "with invalid bytes raises an EncodingError at parse time" do
+ ScratchPad.record []
+ -> {
+ eval 'ScratchPad << 1; :"\xC3"'
+ }.should raise_error(EncodingError, /invalid/)
+ ScratchPad.recorded.should == []
+ end
end
diff --git a/spec/ruby/language/throw_spec.rb b/spec/ruby/language/throw_spec.rb
index d78c137708..92f699350c 100644
--- a/spec/ruby/language/throw_spec.rb
+++ b/spec/ruby/language/throw_spec.rb
@@ -68,13 +68,14 @@ describe "The throw keyword" do
lambda { catch(:different) { throw :test, 5 } }.should raise_error(ArgumentError)
end
- it "raises an ArgumentError if used to exit a thread" do
- lambda {
- catch(:what) do
- Thread.new {
+ it "raises an UncaughtThrowError if used to exit a thread" do
+ catch(:what) do
+ t = Thread.new {
+ -> {
throw :what
- }.join
- end
- }.should raise_error(ArgumentError)
+ }.should raise_error(UncaughtThrowError)
+ }
+ t.join
+ end
end
end
diff --git a/spec/ruby/library/bigdecimal/sign_spec.rb b/spec/ruby/library/bigdecimal/sign_spec.rb
index 0d722987b5..85aa74741c 100644
--- a/spec/ruby/library/bigdecimal/sign_spec.rb
+++ b/spec/ruby/library/bigdecimal/sign_spec.rb
@@ -27,7 +27,7 @@ describe "BigDecimal#sign" do
BigDecimal("-Infinity").sign.should == BigDecimal::SIGN_NEGATIVE_INFINITE
end
- it "returns positive zero if BigDecimal equals positve zero" do
+ it "returns positive zero if BigDecimal equals positive zero" do
BigDecimal("0").sign.should == BigDecimal::SIGN_POSITIVE_ZERO
BigDecimal("0E-200000000").sign.should == BigDecimal::SIGN_POSITIVE_ZERO
BigDecimal("0E200000000").sign.should == BigDecimal::SIGN_POSITIVE_ZERO
diff --git a/spec/ruby/library/cgi/cookie/parse_spec.rb b/spec/ruby/library/cgi/cookie/parse_spec.rb
index dc8498dcb4..6f615c0d23 100644
--- a/spec/ruby/library/cgi/cookie/parse_spec.rb
+++ b/spec/ruby/library/cgi/cookie/parse_spec.rb
@@ -10,6 +10,27 @@ describe "CGI::Cookie.parse" do
CGI::Cookie.parse("first cookie=one&two;second cookie=three&four").should == expected
end
+ ruby_version_is ""..."2.4" do
+ it "uses , for cookie separators" do
+ expected = {
+ "first cookie" => ["one", "two"],
+ "second cookie" => ["three", "four"],
+ "third_cookie" => ["five", "six"]
+ }
+ CGI::Cookie.parse("first cookie=one&two;second cookie=three&four,third_cookie=five&six").should == expected
+ end
+ end
+
+ ruby_version_is "2.4" do
+ it "does not use , for cookie separators" do
+ expected = {
+ "first cookie" => ["one", "two"],
+ "second cookie" => ["three", "four,third_cookie=five", "six"]
+ }
+ CGI::Cookie.parse("first cookie=one&two;second cookie=three&four,third_cookie=five&six").should == expected
+ end
+ end
+
it "unescapes the Cookie values" do
cookie = "test-cookie=+%21%22%23%24%25%26%27%28%29%2A%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D%7E"
expected = { "test-cookie" => [ " !\"\#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" ] }
diff --git a/spec/ruby/library/cgi/shared/http_header.rb b/spec/ruby/library/cgi/shared/http_header.rb
index ed65b20abd..b6d81d2e0e 100644
--- a/spec/ruby/library/cgi/shared/http_header.rb
+++ b/spec/ruby/library/cgi/shared/http_header.rb
@@ -13,7 +13,7 @@ describe :cgi_http_header, shared: true do
end
- it "returns a HTTP header specifiying the Content-Type as text/html" do
+ it "returns a HTTP header specifying the Content-Type as text/html" do
@cgi.send(@method).should == "Content-Type: text/html\r\n\r\n"
end
@@ -34,7 +34,7 @@ describe :cgi_http_header, shared: true do
end
- it "returns a HTTP header specifiying the Content-Type as the passed String's content" do
+ it "returns a HTTP header specifying the Content-Type as the passed String's content" do
@cgi.send(@method, "text/plain").should == "Content-Type: text/plain\r\n\r\n"
end
@@ -105,7 +105,7 @@ describe :cgi_http_header, shared: true do
@cgi.send(@method, {}).should == "Content-Type: text/html\r\nSet-Cookie: multiple\r\nSet-Cookie: cookies\r\n\r\n"
end
- it "returns a HTTP header specifiying the Content-Type as text/html when passed an empty Hash" do
+ it "returns a HTTP header specifying the Content-Type as text/html when passed an empty Hash" do
@cgi.send(@method, {}).should == "Content-Type: text/html\r\n\r\n"
end
end
diff --git a/spec/ruby/library/conditionvariable/marshal_dump_spec.rb b/spec/ruby/library/conditionvariable/marshal_dump_spec.rb
new file mode 100644
index 0000000000..f32b784eaa
--- /dev/null
+++ b/spec/ruby/library/conditionvariable/marshal_dump_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'thread'
+
+describe "ConditionVariable#marshal_dump" do
+ it "raises a TypeError" do
+ cv = ConditionVariable.new
+ -> { cv.marshal_dump }.should raise_error(TypeError, /can't dump/)
+ end
+end
diff --git a/spec/ruby/library/csv/liberal_parsing_spec.rb b/spec/ruby/library/csv/liberal_parsing_spec.rb
new file mode 100644
index 0000000000..99cedbcd22
--- /dev/null
+++ b/spec/ruby/library/csv/liberal_parsing_spec.rb
@@ -0,0 +1,21 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'csv'
+
+ruby_version_is '2.4' do
+ describe "CSV#liberal_parsing?" do
+ it "returns true if illegal input is handled" do
+ csv = CSV.new("", liberal_parsing: true)
+ csv.liberal_parsing?.should == true
+ end
+
+ it "returns false if illegal input is not handled" do
+ csv = CSV.new("", liberal_parsing: false)
+ csv.liberal_parsing?.should == false
+ end
+
+ it "returns false by default" do
+ csv = CSV.new("")
+ csv.liberal_parsing?.should == false
+ end
+ end
+end
diff --git a/spec/ruby/library/csv/parse_spec.rb b/spec/ruby/library/csv/parse_spec.rb
index 41d37ca9a4..47d7ebbde1 100644
--- a/spec/ruby/library/csv/parse_spec.rb
+++ b/spec/ruby/library/csv/parse_spec.rb
@@ -78,4 +78,18 @@ describe "CSV.parse" do
result = CSV.parse "foo;bar\nbaz;quz", col_sep: ?;
result.should == [['foo','bar'],['baz','quz']]
end
+
+ it "raises CSV::MalformedCSVError exception if input is illegal" do
+ -> {
+ CSV.parse('"quoted" field')
+ }.should raise_error(CSV::MalformedCSVError)
+ end
+
+ ruby_version_is '2.4' do
+ it "handles illegal input with the liberal_parsing option" do
+ illegal_input = '"Johnson, Dwayne",Dwayne "The Rock" Johnson'
+ result = CSV.parse(illegal_input, liberal_parsing: true)
+ result.should == [["Johnson, Dwayne", 'Dwayne "The Rock" Johnson']]
+ end
+ end
end
diff --git a/spec/ruby/library/csv/readlines_spec.rb b/spec/ruby/library/csv/readlines_spec.rb
index 387730db16..452effd343 100644
--- a/spec/ruby/library/csv/readlines_spec.rb
+++ b/spec/ruby/library/csv/readlines_spec.rb
@@ -20,4 +20,18 @@ describe "CSV#readlines" do
file = CSV.new "a,, b, c"
file.readlines.should == [["a", nil, " b", " c"]]
end
+
+ it "raises CSV::MalformedCSVError exception if input is illegal" do
+ csv = CSV.new('"quoted" field')
+ -> { csv.readlines }.should raise_error(CSV::MalformedCSVError)
+ end
+
+ ruby_version_is '2.4' do
+ it "handles illegal input with the liberal_parsing option" do
+ illegal_input = '"Johnson, Dwayne",Dwayne "The Rock" Johnson'
+ csv = CSV.new(illegal_input, liberal_parsing: true)
+ result = csv.readlines
+ result.should == [["Johnson, Dwayne", 'Dwayne "The Rock" Johnson']]
+ end
+ end
end
diff --git a/spec/ruby/library/date/friday_spec.rb b/spec/ruby/library/date/friday_spec.rb
new file mode 100644
index 0000000000..369b943419
--- /dev/null
+++ b/spec/ruby/library/date/friday_spec.rb
@@ -0,0 +1,12 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#friday?" do
+ it "should be friday" do
+ Date.new(2000, 1, 7).friday?.should be_true
+ end
+
+ it "should not be friday" do
+ Date.new(2000, 1, 8).friday?.should be_false
+ end
+end
diff --git a/spec/ruby/library/date/minus_month_spec.rb b/spec/ruby/library/date/minus_month_spec.rb
index b6b20c5578..fbe5cb8593 100644
--- a/spec/ruby/library/date/minus_month_spec.rb
+++ b/spec/ruby/library/date/minus_month_spec.rb
@@ -3,7 +3,7 @@ require File.expand_path('../../../spec_helper', __FILE__)
describe "Date#<<" do
- it "substracts a number of months from a date" do
+ it "subtracts a number of months from a date" do
d = Date.civil(2007,2,27) << 10
d.should == Date.civil(2006, 4, 27)
end
diff --git a/spec/ruby/library/date/minus_spec.rb b/spec/ruby/library/date/minus_spec.rb
index 09da595872..fd7f3fd14c 100644
--- a/spec/ruby/library/date/minus_spec.rb
+++ b/spec/ruby/library/date/minus_spec.rb
@@ -3,12 +3,12 @@ require File.expand_path('../../../spec_helper', __FILE__)
describe "Date#-" do
- it "substracts a number of days from a Date" do
+ it "subtracts a number of days from a Date" do
d = Date.civil(2007, 5 ,2) - 13
d.should == Date.civil(2007, 4, 19)
end
- it "substracts a negative number of days from a Date" do
+ it "subtracts a negative number of days from a Date" do
d = Date.civil(2007, 4, 19).-(-13)
d.should == Date.civil(2007, 5 ,2)
end
diff --git a/spec/ruby/library/date/monday_spec.rb b/spec/ruby/library/date/monday_spec.rb
new file mode 100644
index 0000000000..f7d968b6d6
--- /dev/null
+++ b/spec/ruby/library/date/monday_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#monday?" do
+ it "should be monday" do
+ Date.new(2000, 1, 3).monday?.should be_true
+ end
+end
diff --git a/spec/ruby/library/date/next_day_spec.rb b/spec/ruby/library/date/next_day_spec.rb
index 1ccb4df257..795bfecf0a 100644
--- a/spec/ruby/library/date/next_day_spec.rb
+++ b/spec/ruby/library/date/next_day_spec.rb
@@ -3,8 +3,12 @@ require 'date'
describe "Date#next_day" do
it "returns the next day" do
- d = Date.new(2000, 1, 5)
- d1 = Date.new(2000, 1, 4).next_day
- d1.should == d
+ d = Date.new(2000, 1, 4).next_day
+ d.should == Date.new(2000, 1, 5)
+ end
+
+ it "returns three days later across months" do
+ d = Date.new(2000, 1, 30).next_day(3)
+ d.should == Date.new(2000, 2, 2)
end
end
diff --git a/spec/ruby/library/date/next_month_spec.rb b/spec/ruby/library/date/next_month_spec.rb
index 22699a39a5..9becd7e37f 100644
--- a/spec/ruby/library/date/next_month_spec.rb
+++ b/spec/ruby/library/date/next_month_spec.rb
@@ -11,4 +11,19 @@ describe "Date#next_month" do
d = Date.new(2000, 7, 1).next_month(3)
d.should == Date.new(2000, 10, 1)
end
+
+ it "returns three months later across years" do
+ d = Date.new(2000, 12, 1).next_month(3)
+ d.should == Date.new(2001, 3, 1)
+ end
+
+ it "returns last day of month two months later" do
+ d = Date.new(2000, 1, 31).next_month(2)
+ d.should == Date.new(2000, 3, 31)
+ end
+
+ it "returns last day of next month when same day does not exist" do
+ d = Date.new(2001, 1, 30).next_month
+ d.should == Date.new(2001, 2, 28)
+ end
end
diff --git a/spec/ruby/library/date/prev_day_spec.rb b/spec/ruby/library/date/prev_day_spec.rb
index 8a42824154..149bfe9fa9 100644
--- a/spec/ruby/library/date/prev_day_spec.rb
+++ b/spec/ruby/library/date/prev_day_spec.rb
@@ -7,8 +7,8 @@ describe "Date#prev_day" do
d.should == Date.new(2000, 7, 1)
end
- it "returns three days ago" do
- d = Date.new(2000, 7, 4).prev_day(3)
- d.should == Date.new(2000, 7, 1)
+ it "returns three days ago across months" do
+ d = Date.new(2000, 7, 2).prev_day(3)
+ d.should == Date.new(2000, 6, 29)
end
end
diff --git a/spec/ruby/library/date/prev_month_spec.rb b/spec/ruby/library/date/prev_month_spec.rb
index eaf7f67ee0..440c17ffc9 100644
--- a/spec/ruby/library/date/prev_month_spec.rb
+++ b/spec/ruby/library/date/prev_month_spec.rb
@@ -11,4 +11,19 @@ describe "Date#prev_month" do
d = Date.new(2000, 10, 1).prev_month(3)
d.should == Date.new(2000, 7, 1)
end
+
+ it "returns three months ago across years" do
+ d = Date.new(2000, 1, 1).prev_month(3)
+ d.should == Date.new(1999, 10, 1)
+ end
+
+ it "returns last day of month two months ago" do
+ d = Date.new(2000, 3, 31).prev_month(2)
+ d.should == Date.new(2000, 1, 31)
+ end
+
+ it "returns last day of previous month when same day does not exist" do
+ d = Date.new(2001, 3, 30).prev_month
+ d.should == Date.new(2001, 2, 28)
+ end
end
diff --git a/spec/ruby/library/date/saturday_spec.rb b/spec/ruby/library/date/saturday_spec.rb
new file mode 100644
index 0000000000..1360050a69
--- /dev/null
+++ b/spec/ruby/library/date/saturday_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#saturday?" do
+ it "should be saturday" do
+ Date.new(2000, 1, 1).saturday?.should be_true
+ end
+end
diff --git a/spec/ruby/library/date/sunday_spec.rb b/spec/ruby/library/date/sunday_spec.rb
new file mode 100644
index 0000000000..d805006264
--- /dev/null
+++ b/spec/ruby/library/date/sunday_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#sunday?" do
+ it "should be sunday" do
+ Date.new(2000, 1, 2).sunday?.should be_true
+ end
+end
diff --git a/spec/ruby/library/date/thursday_spec.rb b/spec/ruby/library/date/thursday_spec.rb
new file mode 100644
index 0000000000..a59ca3f6cf
--- /dev/null
+++ b/spec/ruby/library/date/thursday_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#thursday?" do
+ it "should be thursday" do
+ Date.new(2000, 1, 6).thursday?.should be_true
+ end
+end
diff --git a/spec/ruby/library/date/today_spec.rb b/spec/ruby/library/date/today_spec.rb
index 09e8ed6006..d487be089f 100644
--- a/spec/ruby/library/date/today_spec.rb
+++ b/spec/ruby/library/date/today_spec.rb
@@ -2,5 +2,13 @@ require File.expand_path('../../../spec_helper', __FILE__)
require 'date'
describe "Date.today" do
- it "needs to be reviewed for spec completeness"
+ it "returns a Date object" do
+ Date.today.should be_kind_of Date
+ end
+
+ it "sets Date object to the current date" do
+ today = Date.today
+ now = Time.now
+ (now - today.to_time).should be_close(0.0, 24 * 60 * 60)
+ end
end
diff --git a/spec/ruby/library/date/tuesday_spec.rb b/spec/ruby/library/date/tuesday_spec.rb
new file mode 100644
index 0000000000..10ed6755d1
--- /dev/null
+++ b/spec/ruby/library/date/tuesday_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#tuesday?" do
+ it "should be tuesday" do
+ Date.new(2000, 1, 4).tuesday?.should be_true
+ end
+end
diff --git a/spec/ruby/library/date/wday_spec.rb b/spec/ruby/library/date/wday_spec.rb
index 1d40b0c96c..7303423123 100644
--- a/spec/ruby/library/date/wday_spec.rb
+++ b/spec/ruby/library/date/wday_spec.rb
@@ -2,5 +2,8 @@ require File.expand_path('../../../spec_helper', __FILE__)
require 'date'
describe "Date#wday" do
- it "needs to be reviewed for spec completeness"
+ it "returns the week day as a number starting with Sunday as 0" do
+ w = Date.new(2000, 1, 1).wday
+ w.should == 6
+ end
end
diff --git a/spec/ruby/library/date/wednesday_spec.rb b/spec/ruby/library/date/wednesday_spec.rb
new file mode 100644
index 0000000000..99478f21c2
--- /dev/null
+++ b/spec/ruby/library/date/wednesday_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'date'
+
+describe "Date#wednesday?" do
+ it "should be wednesday" do
+ Date.new(2000, 1, 5).wednesday?.should be_true
+ end
+end
diff --git a/spec/ruby/library/datetime/new_spec.rb b/spec/ruby/library/datetime/new_spec.rb
index a8275a1951..14ef329d56 100644
--- a/spec/ruby/library/datetime/new_spec.rb
+++ b/spec/ruby/library/datetime/new_spec.rb
@@ -42,7 +42,7 @@ describe "DateTime.new" do
DateTime.new(1, 2, 3, 4, 5, 6, 0.7).offset.should == 0.7
end
- it "takes the eigth argument as the date of calendar reform" do
+ it "takes the eighth argument as the date of calendar reform" do
DateTime.new(1, 2, 3, 4, 5, 6, 0.7, Date::ITALY).start().should == Date::ITALY
end
diff --git a/spec/ruby/library/datetime/now_spec.rb b/spec/ruby/library/datetime/now_spec.rb
index e8c93aa604..a5bf590aff 100644
--- a/spec/ruby/library/datetime/now_spec.rb
+++ b/spec/ruby/library/datetime/now_spec.rb
@@ -5,4 +5,21 @@ describe "DateTime.now" do
it "creates an instance of DateTime" do
DateTime.now.should be_an_instance_of(DateTime)
end
+
+ it "sets the current date" do
+ (DateTime.now - Date.today).to_f.should be_close(0.0, 1.0)
+ end
+
+ it "sets the current time" do
+ dt = DateTime.now
+ now = Time.now
+ (dt.to_time - now).should be_close(0.0, 10.0)
+ end
+
+ it "grabs the local timezone" do
+ with_timezone("PDT", -8) do
+ dt = DateTime.now
+ dt.zone.should == "-08:00"
+ end
+ end
end
diff --git a/spec/ruby/library/datetime/to_date_spec.rb b/spec/ruby/library/datetime/to_date_spec.rb
index 915e1ac87a..387eda9229 100644
--- a/spec/ruby/library/datetime/to_date_spec.rb
+++ b/spec/ruby/library/datetime/to_date_spec.rb
@@ -2,5 +2,36 @@ require File.expand_path('../../../spec_helper', __FILE__)
require 'date'
describe "DateTime#to_date" do
- it "needs to be reviewed for spec completeness"
+ it "returns an instance of Date" do
+ dt = DateTime.new(2012, 12, 24, 12, 23, 00, '+05:00')
+ dt.to_date.should be_kind_of(Date)
+ end
+
+ it "maintains the same year" do
+ dt = DateTime.new(2012, 12, 24, 12, 23, 00, '+05:00')
+ dt.to_date.year.should == dt.year
+ end
+
+ it "maintains the same month" do
+ dt = DateTime.new(2012, 12, 24, 12, 23, 00, '+05:00')
+ dt.to_date.mon.should == dt.mon
+ end
+
+ it "maintains the same day" do
+ dt = DateTime.new(2012, 12, 24, 12, 23, 00, '+05:00')
+ dt.to_date.day.should == dt.day
+ end
+
+ it "maintains the same mday" do
+ dt = DateTime.new(2012, 12, 24, 12, 23, 00, '+05:00')
+ dt.to_date.mday.should == dt.mday
+ end
+
+ it "maintains the same julian day regardless of local time or zone" do
+ dt = DateTime.new(2012, 12, 24, 12, 23, 00, '+05:00')
+
+ with_timezone("Pactific/Pago_Pago", -11) do
+ dt.to_date.jd.should == dt.jd
+ end
+ end
end
diff --git a/spec/ruby/library/datetime/to_datetime_spec.rb b/spec/ruby/library/datetime/to_datetime_spec.rb
index e289f8ce36..e4db9558f1 100644
--- a/spec/ruby/library/datetime/to_datetime_spec.rb
+++ b/spec/ruby/library/datetime/to_datetime_spec.rb
@@ -2,5 +2,8 @@ require File.expand_path('../../../spec_helper', __FILE__)
require 'date'
describe "DateTime#to_datetime" do
- it "needs to be reviewed for spec completeness"
+ it "returns itself" do
+ dt = DateTime.new(2012, 12, 24, 12, 23, 00, '+05:00')
+ dt.to_datetime.should == dt
+ end
end
diff --git a/spec/ruby/library/datetime/to_s_spec.rb b/spec/ruby/library/datetime/to_s_spec.rb
index 893cc93283..9d9dfc629f 100644
--- a/spec/ruby/library/datetime/to_s_spec.rb
+++ b/spec/ruby/library/datetime/to_s_spec.rb
@@ -2,5 +2,16 @@ require File.expand_path('../../../spec_helper', __FILE__)
require 'date'
describe "DateTime#to_s" do
- it "needs to be reviewed for spec completeness"
+ it "returns a new String object" do
+ dt = DateTime.new(2012, 12, 24, 1, 2, 3, "+03:00")
+ dt.to_s.should be_kind_of(String)
+ end
+
+ it "maintains timezone regardless of local time" do
+ dt = DateTime.new(2012, 12, 24, 1, 2, 3, "+03:00")
+
+ with_timezone("Pactific/Pago_Pago", -11) do
+ dt.to_s.should == "2012-12-24T01:02:03+03:00"
+ end
+ end
end
diff --git a/spec/ruby/library/datetime/to_time_spec.rb b/spec/ruby/library/datetime/to_time_spec.rb
index aa2902930c..f5b7cb8a23 100644
--- a/spec/ruby/library/datetime/to_time_spec.rb
+++ b/spec/ruby/library/datetime/to_time_spec.rb
@@ -2,5 +2,25 @@ require File.expand_path('../../../spec_helper', __FILE__)
require 'date'
describe "DateTime#to_time" do
- it "needs to be reviewed for spec completeness"
+ it "yields a new Time object" do
+ DateTime.now.to_time.should be_kind_of(Time)
+ end
+
+ ruby_version_is "2.4" do
+ it "preserves the same time regardless of local time or zone" do
+ date = DateTime.new(2012, 12, 24, 12, 23, 00, '+03:00')
+
+ with_timezone("Pactific/Pago_Pago", -11) do
+ time = date.to_time
+
+ time.utc_offset.should == 3 * 3600
+ time.year.should == date.year
+ time.mon.should == date.mon
+ time.day.should == date.day
+ time.hour.should == date.hour
+ time.min.should == date.min
+ time.sec.should == date.sec
+ end
+ end
+ end
end
diff --git a/spec/ruby/library/etc/getlogin_spec.rb b/spec/ruby/library/etc/getlogin_spec.rb
index ae52942a92..43e654bda6 100644
--- a/spec/ruby/library/etc/getlogin_spec.rb
+++ b/spec/ruby/library/etc/getlogin_spec.rb
@@ -11,9 +11,15 @@ describe "Etc.getlogin" do
# make Etc.getlogin to return nil if getlogin(3) returns NULL
envuser, ENV['USER'] = ENV['USER'], nil
if Etc.getlogin
- # Etc.getlogin returns the same result of logname(2)
- # if it returns non NULL
- Etc.getlogin.should == `id -un`.chomp
+ if ENV['TRAVIS'] and platform_is(:darwin)
+ # See https://travis-ci.org/ruby/spec/jobs/285967744
+ # and https://travis-ci.org/ruby/spec/jobs/285999602
+ Etc.getlogin.should be_an_instance_of(String)
+ else
+ # Etc.getlogin returns the same result of logname(2)
+ # if it returns non NULL
+ Etc.getlogin.should == `id -un`.chomp
+ end
else
# Etc.getlogin may return nil if the login name is not set
# because of chroot or sudo or something.
diff --git a/spec/ruby/library/fiber/resume_spec.rb b/spec/ruby/library/fiber/resume_spec.rb
index 8709d01142..389757b7bd 100644
--- a/spec/ruby/library/fiber/resume_spec.rb
+++ b/spec/ruby/library/fiber/resume_spec.rb
@@ -4,7 +4,7 @@ with_feature :fiber_library do
require 'fiber'
describe "Fiber#resume" do
- it "raises a FiberError if the Fiber has transfered control to another Fiber" do
+ it "raises a FiberError if the Fiber has transferred control to another Fiber" do
fiber1 = Fiber.new { true }
fiber2 = Fiber.new { fiber1.transfer; Fiber.yield }
fiber2.resume
diff --git a/spec/ruby/library/fiber/transfer_spec.rb b/spec/ruby/library/fiber/transfer_spec.rb
index 79319a7d39..ad501c1d74 100644
--- a/spec/ruby/library/fiber/transfer_spec.rb
+++ b/spec/ruby/library/fiber/transfer_spec.rb
@@ -35,7 +35,7 @@ with_feature :fiber_library do
states.should == [:start, :end]
end
- it "can transfer control to a Fiber that has transfered to another Fiber" do
+ it "can transfer control to a Fiber that has transferred to another Fiber" do
states = []
fiber1 = Fiber.new { states << :fiber1 }
fiber2 = Fiber.new { states << :fiber2_start; fiber1.transfer; states << :fiber2_end}
diff --git a/spec/ruby/library/getoptlong/terminate_spec.rb b/spec/ruby/library/getoptlong/terminate_spec.rb
index ad9f9a1623..66d318527b 100644
--- a/spec/ruby/library/getoptlong/terminate_spec.rb
+++ b/spec/ruby/library/getoptlong/terminate_spec.rb
@@ -11,7 +11,7 @@ describe "GetoptLong#terminate" do
)
end
- it "terminates option proccessing" do
+ it "terminates option processing" do
argv [ "--size", "10k", "-v", "-q", "a.txt", "b.txt" ] do
@opts.get.should == [ "--size", "10k" ]
@opts.terminate
diff --git a/spec/ruby/library/ipaddr/operator_spec.rb b/spec/ruby/library/ipaddr/operator_spec.rb
index 3f54efd486..6d884780e3 100644
--- a/spec/ruby/library/ipaddr/operator_spec.rb
+++ b/spec/ruby/library/ipaddr/operator_spec.rb
@@ -57,13 +57,20 @@ describe "IPAddr Operator" do
@a.should_not == IPAddr.new("3ffe:505:3::")
end
+ ruby_version_is '2.4' do
+ # https://bugs.ruby-lang.org/issues/12799
+ it "tests for equality correctly if object cannot be converted to IPAddr" do
+ IPAddr.new("1.1.1.1").should_not == "sometext"
+ end
+ end
+
it "sets a mask" do
a = @a.mask(32)
a.to_s.should == "3ffe:505::"
@a.to_s.should == "3ffe:505:2::"
end
- it "checks whether an addres is included in a range" do
+ it "checks whether an address is included in a range" do
@a.should include(IPAddr.new("3ffe:505:2::"))
@a.should include(IPAddr.new("3ffe:505:2::1"))
@a.should_not include(IPAddr.new("3ffe:505:3::"))
diff --git a/spec/ruby/library/logger/logger/new_spec.rb b/spec/ruby/library/logger/logger/new_spec.rb
index 255f686d25..b3eed42f00 100644
--- a/spec/ruby/library/logger/logger/new_spec.rb
+++ b/spec/ruby/library/logger/logger/new_spec.rb
@@ -60,4 +60,61 @@ describe "Logger#new" do
f1.close
rm_r path, "#{path}.0"
end
+
+ ruby_version_is "2.4" do
+ it "receives level symbol as keyword argument" do
+ logger = Logger.new(STDERR, level: :info)
+ logger.level.should == Logger::INFO
+ end
+
+ it "receives level as keyword argument" do
+ logger = Logger.new(STDERR, level: Logger::INFO)
+ logger.level.should == Logger::INFO
+ end
+
+ it "receives progname as keyword argument" do
+ progname = "progname"
+
+ logger = Logger.new(STDERR, progname: progname)
+ logger.progname.should == progname
+ end
+
+ it "receives datetime_format as keyword argument" do
+ datetime_format = "%H:%M:%S"
+
+ logger = Logger.new(STDERR, datetime_format: datetime_format)
+ logger.datetime_format.should == datetime_format
+ end
+
+ it "receives formatter as keyword argument" do
+ formatter = Class.new do
+ def call(_severity, _time, _progname, _msg); end
+ end.new
+
+ logger = Logger.new(STDERR, formatter: formatter)
+ logger.formatter.should == formatter
+ end
+
+ it "receives shift_period_suffix " do
+ shift_period_suffix = "%Y-%m-%d"
+ path = tmp("shift_period_suffix_test.log")
+ now = Time.now
+ tomorrow = Time.at(now.to_i + 60 * 60 * 24)
+ logger = Logger.new(path, 'daily', shift_period_suffix: shift_period_suffix)
+
+ logger.add Logger::INFO, 'message'
+
+ Time.stub!(:now).and_return(tomorrow)
+ logger.add Logger::INFO, 'second message'
+
+ shifted_path = "#{path}.#{now.strftime(shift_period_suffix)}"
+
+ File.exist?(shifted_path).should == true
+
+ logger.close
+
+ rm_r path, shifted_path
+ end
+ end
+
end
diff --git a/spec/ruby/library/matrix/diagonal_spec.rb b/spec/ruby/library/matrix/diagonal_spec.rb
index c88a92b5cd..ddf5a8d292 100644
--- a/spec/ruby/library/matrix/diagonal_spec.rb
+++ b/spec/ruby/library/matrix/diagonal_spec.rb
@@ -63,9 +63,9 @@ describe "Matrix.diagonal?" do
Matrix[[0, 0]],
Matrix.empty(0, 2),
Matrix.empty(2, 0),
- ].each do |rectangual_matrix|
+ ].each do |rectangular_matrix|
lambda {
- rectangual_matrix.diagonal?
+ rectangular_matrix.diagonal?
}.should raise_error(Matrix::ErrDimensionMismatch)
end
end
diff --git a/spec/ruby/library/matrix/hermitian_spec.rb b/spec/ruby/library/matrix/hermitian_spec.rb
index cbfea433c2..e108ba1e34 100644
--- a/spec/ruby/library/matrix/hermitian_spec.rb
+++ b/spec/ruby/library/matrix/hermitian_spec.rb
@@ -10,7 +10,7 @@ describe "Matrix.hermitian?" do
Matrix.empty.hermitian?.should be_true
end
- it "returns false for an assymetric Matrix" do
+ it "returns false for an asymmetric Matrix" do
Matrix[[1, 2],[-2, 1]].hermitian?.should be_false
end
@@ -20,9 +20,9 @@ describe "Matrix.hermitian?" do
Matrix[[0, 0]],
Matrix.empty(0, 2),
Matrix.empty(2, 0),
- ].each do |rectangual_matrix|
+ ].each do |rectangular_matrix|
lambda {
- rectangual_matrix.hermitian?
+ rectangular_matrix.hermitian?
}.should raise_error(Matrix::ErrDimensionMismatch)
end
end
diff --git a/spec/ruby/library/matrix/normal_spec.rb b/spec/ruby/library/matrix/normal_spec.rb
index 140909dcc2..5f0b8e6362 100644
--- a/spec/ruby/library/matrix/normal_spec.rb
+++ b/spec/ruby/library/matrix/normal_spec.rb
@@ -17,9 +17,9 @@ describe "Matrix.normal?" do
Matrix[[0, 0]],
Matrix.empty(0, 2),
Matrix.empty(2, 0),
- ].each do |rectangual_matrix|
+ ].each do |rectangular_matrix|
lambda {
- rectangual_matrix.normal?
+ rectangular_matrix.normal?
}.should raise_error(Matrix::ErrDimensionMismatch)
end
end
diff --git a/spec/ruby/library/matrix/orthogonal_spec.rb b/spec/ruby/library/matrix/orthogonal_spec.rb
index 2e76b5924c..78f5c1be5d 100644
--- a/spec/ruby/library/matrix/orthogonal_spec.rb
+++ b/spec/ruby/library/matrix/orthogonal_spec.rb
@@ -17,9 +17,9 @@ describe "Matrix.orthogonal?" do
Matrix[[0, 0]],
Matrix.empty(0, 2),
Matrix.empty(2, 0),
- ].each do |rectangual_matrix|
+ ].each do |rectangular_matrix|
lambda {
- rectangual_matrix.orthogonal?
+ rectangular_matrix.orthogonal?
}.should raise_error(Matrix::ErrDimensionMismatch)
end
end
diff --git a/spec/ruby/library/matrix/permutation_spec.rb b/spec/ruby/library/matrix/permutation_spec.rb
index 7098c46015..f40de4f58f 100644
--- a/spec/ruby/library/matrix/permutation_spec.rb
+++ b/spec/ruby/library/matrix/permutation_spec.rb
@@ -23,9 +23,9 @@ describe "Matrix#permutation?" do
Matrix[[0, 0]],
Matrix.empty(0, 2),
Matrix.empty(2, 0),
- ].each do |rectangual_matrix|
+ ].each do |rectangular_matrix|
lambda {
- rectangual_matrix.permutation?
+ rectangular_matrix.permutation?
}.should raise_error(Matrix::ErrDimensionMismatch)
end
end
diff --git a/spec/ruby/library/matrix/symmetric_spec.rb b/spec/ruby/library/matrix/symmetric_spec.rb
index 53f962c0e2..c34a323510 100644
--- a/spec/ruby/library/matrix/symmetric_spec.rb
+++ b/spec/ruby/library/matrix/symmetric_spec.rb
@@ -10,7 +10,7 @@ describe "Matrix.symmetric?" do
Matrix.empty.symmetric?.should be_true
end
- it "returns false for an assymetric Matrix" do
+ it "returns false for an asymmetric Matrix" do
Matrix[[1, 2],[-2, 1]].symmetric?.should be_false
end
@@ -20,9 +20,9 @@ describe "Matrix.symmetric?" do
Matrix[[0, 0]],
Matrix.empty(0, 2),
Matrix.empty(2, 0),
- ].each do |rectangual_matrix|
+ ].each do |rectangular_matrix|
lambda {
- rectangual_matrix.symmetric?
+ rectangular_matrix.symmetric?
}.should raise_error(Matrix::ErrDimensionMismatch)
end
end
diff --git a/spec/ruby/library/matrix/unitary_spec.rb b/spec/ruby/library/matrix/unitary_spec.rb
index e322a5a3ce..0ea5586a6d 100644
--- a/spec/ruby/library/matrix/unitary_spec.rb
+++ b/spec/ruby/library/matrix/unitary_spec.rb
@@ -19,9 +19,9 @@ describe "Matrix.unitary?" do
Matrix[[0, 0]],
Matrix.empty(0, 2),
Matrix.empty(2, 0),
- ].each do |rectangual_matrix|
+ ].each do |rectangular_matrix|
lambda {
- rectangual_matrix.unitary?
+ rectangular_matrix.unitary?
}.should raise_error(Matrix::ErrDimensionMismatch)
end
end
diff --git a/spec/ruby/library/net/ftp/fixtures/server.rb b/spec/ruby/library/net/ftp/fixtures/server.rb
index a6741820ff..65339cfaf9 100644
--- a/spec/ruby/library/net/ftp/fixtures/server.rb
+++ b/spec/ruby/library/net/ftp/fixtures/server.rb
@@ -35,7 +35,7 @@ module NetFTPSpecs
response @connect_message || "220 Dummy FTP Server ready!"
begin
- while command = @socket.recv(1024)
+ while command = @socket.gets
command, argument = command.chomp.split(" ", 2)
if command == "QUIT"
@@ -229,8 +229,12 @@ module NetFTPSpecs
end
end
- def stat
- self.response("211 System status, or system help reply. (STAT)")
+ def stat(param = :default)
+ if param == :default
+ self.response("211 System status, or system help reply. (STAT)")
+ else
+ self.response("211 System status, or system help reply. (STAT #{param})")
+ end
end
def stor(file)
diff --git a/spec/ruby/library/net/ftp/status_spec.rb b/spec/ruby/library/net/ftp/status_spec.rb
index 7e9927c3c8..243d3fc175 100644
--- a/spec/ruby/library/net/ftp/status_spec.rb
+++ b/spec/ruby/library/net/ftp/status_spec.rb
@@ -22,6 +22,12 @@ describe "Net::FTP#status" do
@ftp.last_response.should == "211 System status, or system help reply. (STAT)\n"
end
+ ruby_version_is "2.4" do
+ it "sends the STAT command with an optional parameter to the server" do
+ @ftp.status("/pub").should == "211 System status, or system help reply. (STAT /pub)\n"
+ end
+ end
+
it "returns the received information" do
@ftp.status.should == "211 System status, or system help reply. (STAT)\n"
end
diff --git a/spec/ruby/library/net/http/http/fixtures/http_server.rb b/spec/ruby/library/net/http/http/fixtures/http_server.rb
index c2ae2360d3..198fef36fb 100644
--- a/spec/ruby/library/net/http/http/fixtures/http_server.rb
+++ b/spec/ruby/library/net/http/http/fixtures/http_server.rb
@@ -42,6 +42,17 @@ module NetHTTPSpecs
end
end
+ class RequestBasicAuthServlet < SpecServlet
+ def reply(req, res)
+ res.content_type = "text/plain"
+
+ WEBrick::HTTPAuth.basic_auth(req, res, "realm") do |user, pass|
+ res.body = "username: #{user}\npassword: #{pass}"
+ true
+ end
+ end
+ end
+
class << self
@server = nil
@server_thread = nil
@@ -69,6 +80,7 @@ module NetHTTPSpecs
@server.mount('/request', RequestServlet)
@server.mount("/request/body", RequestBodyServlet)
@server.mount("/request/header", RequestHeaderServlet)
+ @server.mount("/request/basic_auth", RequestBasicAuthServlet)
@server_thread = @server.start
end
diff --git a/spec/ruby/library/net/http/http/post_spec.rb b/spec/ruby/library/net/http/http/post_spec.rb
index a50663a01d..66a00f0670 100644
--- a/spec/ruby/library/net/http/http/post_spec.rb
+++ b/spec/ruby/library/net/http/http/post_spec.rb
@@ -1,7 +1,45 @@
require File.expand_path('../../../../../spec_helper', __FILE__)
require 'net/http'
+require 'uri'
require File.expand_path('../fixtures/http_server', __FILE__)
+ruby_version_is '2.4' do
+ describe "Net::HTTP.post" do
+ before :each do
+ NetHTTPSpecs.start_server
+ end
+
+ after :each do
+ NetHTTPSpecs.stop_server
+ end
+
+ it "sends post request to the specified URI and returns response" do
+ response = Net::HTTP.post(
+ URI("http://localhost:#{NetHTTPSpecs.port}/request"),
+ '{ "q": "ruby", "max": "50" }',
+ "Content-Type" => "application/json")
+ response.body.should == "Request type: POST"
+ end
+
+ it "returns a Net::HTTPResponse" do
+ response = Net::HTTP.post(URI("http://localhost:#{NetHTTPSpecs.port}/request"), "test=test")
+ response.should be_kind_of(Net::HTTPResponse)
+ end
+
+ it "sends Content-Type: application/x-www-form-urlencoded by default" do
+ response = Net::HTTP.post(URI("http://localhost:#{NetHTTPSpecs.port}/request/header"), "test=test")
+ response.body.should include('"content-type"=>["application/x-www-form-urlencoded"]')
+ end
+
+ it "does not support HTTP Basic Auth" do
+ response = Net::HTTP.post(
+ URI("http://john:qwerty@localhost:#{NetHTTPSpecs.port}/request/basic_auth"),
+ "test=test")
+ response.body.should == "username: \npassword: "
+ end
+ end
+end
+
describe "Net::HTTP#post" do
before :each do
NetHTTPSpecs.start_server
@@ -36,3 +74,4 @@ describe "Net::HTTP#post" do
end
end
end
+
diff --git a/spec/ruby/library/net/http/http/request_types_spec.rb b/spec/ruby/library/net/http/http/request_types_spec.rb
index 8855a7db66..71fe863bb2 100644
--- a/spec/ruby/library/net/http/http/request_types_spec.rb
+++ b/spec/ruby/library/net/http/http/request_types_spec.rb
@@ -14,7 +14,7 @@ describe "Net::HTTP::Get" do
Net::HTTP::Get::REQUEST_HAS_BODY.should be_false
end
- it "has a Respone Body" do
+ it "has a Response Body" do
Net::HTTP::Get::RESPONSE_HAS_BODY.should be_true
end
end
@@ -32,7 +32,7 @@ describe "Net::HTTP::Head" do
Net::HTTP::Head::REQUEST_HAS_BODY.should be_false
end
- it "has no Respone Body" do
+ it "has no Response Body" do
Net::HTTP::Head::RESPONSE_HAS_BODY.should be_false
end
end
@@ -50,7 +50,7 @@ describe "Net::HTTP::Post" do
Net::HTTP::Post::REQUEST_HAS_BODY.should be_true
end
- it "has a Respone Body" do
+ it "has a Response Body" do
Net::HTTP::Post::RESPONSE_HAS_BODY.should be_true
end
end
@@ -68,7 +68,7 @@ describe "Net::HTTP::Put" do
Net::HTTP::Put::REQUEST_HAS_BODY.should be_true
end
- it "has a Respone Body" do
+ it "has a Response Body" do
Net::HTTP::Put::RESPONSE_HAS_BODY.should be_true
end
end
@@ -86,7 +86,7 @@ describe "Net::HTTP::Delete" do
Net::HTTP::Delete::REQUEST_HAS_BODY.should be_false
end
- it "has a Respone Body" do
+ it "has a Response Body" do
Net::HTTP::Delete::RESPONSE_HAS_BODY.should be_true
end
end
@@ -104,7 +104,7 @@ describe "Net::HTTP::Options" do
Net::HTTP::Options::REQUEST_HAS_BODY.should be_false
end
- it "has no Respone Body" do
+ it "has no Response Body" do
Net::HTTP::Options::RESPONSE_HAS_BODY.should be_true
end
end
@@ -122,7 +122,7 @@ describe "Net::HTTP::Trace" do
Net::HTTP::Trace::REQUEST_HAS_BODY.should be_false
end
- it "has a Respone Body" do
+ it "has a Response Body" do
Net::HTTP::Trace::RESPONSE_HAS_BODY.should be_true
end
end
@@ -140,7 +140,7 @@ describe "Net::HTTP::Propfind" do
Net::HTTP::Propfind::REQUEST_HAS_BODY.should be_true
end
- it "has a Respone Body" do
+ it "has a Response Body" do
Net::HTTP::Propfind::RESPONSE_HAS_BODY.should be_true
end
end
@@ -158,7 +158,7 @@ describe "Net::HTTP::Proppatch" do
Net::HTTP::Proppatch::REQUEST_HAS_BODY.should be_true
end
- it "has a Respone Body" do
+ it "has a Response Body" do
Net::HTTP::Proppatch::RESPONSE_HAS_BODY.should be_true
end
end
@@ -176,7 +176,7 @@ describe "Net::HTTP::Mkcol" do
Net::HTTP::Mkcol::REQUEST_HAS_BODY.should be_true
end
- it "has a Respone Body" do
+ it "has a Response Body" do
Net::HTTP::Mkcol::RESPONSE_HAS_BODY.should be_true
end
end
@@ -194,7 +194,7 @@ describe "Net::HTTP::Copy" do
Net::HTTP::Copy::REQUEST_HAS_BODY.should be_false
end
- it "has a Respone Body" do
+ it "has a Response Body" do
Net::HTTP::Copy::RESPONSE_HAS_BODY.should be_true
end
end
@@ -212,7 +212,7 @@ describe "Net::HTTP::Move" do
Net::HTTP::Move::REQUEST_HAS_BODY.should be_false
end
- it "has a Respone Body" do
+ it "has a Response Body" do
Net::HTTP::Move::RESPONSE_HAS_BODY.should be_true
end
end
@@ -230,7 +230,7 @@ describe "Net::HTTP::Lock" do
Net::HTTP::Lock::REQUEST_HAS_BODY.should be_true
end
- it "has a Respone Body" do
+ it "has a Response Body" do
Net::HTTP::Lock::RESPONSE_HAS_BODY.should be_true
end
end
@@ -248,7 +248,7 @@ describe "Net::HTTP::Unlock" do
Net::HTTP::Unlock::REQUEST_HAS_BODY.should be_true
end
- it "has a Respone Body" do
+ it "has a Response Body" do
Net::HTTP::Unlock::RESPONSE_HAS_BODY.should be_true
end
end
diff --git a/spec/ruby/library/net/http/httpheader/content_length_spec.rb b/spec/ruby/library/net/http/httpheader/content_length_spec.rb
index 009eafde85..d93eb3a608 100644
--- a/spec/ruby/library/net/http/httpheader/content_length_spec.rb
+++ b/spec/ruby/library/net/http/httpheader/content_length_spec.rb
@@ -36,7 +36,7 @@ describe "Net::HTTPHeader#content_length=" do
it "removes the 'Content-Length' entry if passed false or nil" do
@headers["Content-Length"] = "123"
@headers.content_length = nil
- @headers["Content-Lenght"].should be_nil
+ @headers["Content-Length"].should be_nil
end
it "sets the 'Content-Length' entry to the passed value" do
diff --git a/spec/ruby/library/optionparser/order_spec.rb b/spec/ruby/library/optionparser/order_spec.rb
new file mode 100644
index 0000000000..6c6e03ecc8
--- /dev/null
+++ b/spec/ruby/library/optionparser/order_spec.rb
@@ -0,0 +1,32 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'optparse'
+
+describe "OptionParser#order" do
+ ruby_version_is '2.4' do
+ it "accepts `into` keyword argument and stores result in it" do
+ options = {}
+ parser = OptionParser.new do |opts|
+ opts.on("-v", "--[no-]verbose", "Run verbosely")
+ opts.on("-r", "--require LIBRARY", "Require the LIBRARY before executing your script")
+ end
+ parser.order %w[--verbose --require optparse], into: options
+
+ options.should == { verbose: true, require: "optparse" }
+ end
+ end
+end
+
+describe "OptionParser#order!" do
+ ruby_version_is '2.4' do
+ it "accepts `into` keyword argument and stores result in it" do
+ options = {}
+ parser = OptionParser.new do |opts|
+ opts.on("-v", "--[no-]verbose", "Run verbosely")
+ opts.on("-r", "--require LIBRARY", "Require the LIBRARY before executing your script")
+ end
+ parser.order! %w[--verbose --require optparse], into: options
+
+ options.should == { verbose: true, require: "optparse" }
+ end
+ end
+end
diff --git a/spec/ruby/library/optionparser/parse_spec.rb b/spec/ruby/library/optionparser/parse_spec.rb
new file mode 100644
index 0000000000..f13793773c
--- /dev/null
+++ b/spec/ruby/library/optionparser/parse_spec.rb
@@ -0,0 +1,32 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'optparse'
+
+describe "OptionParser#parse" do
+ ruby_version_is '2.4' do
+ it "accepts `into` keyword argument and stores result in it" do
+ options = {}
+ parser = OptionParser.new do |opts|
+ opts.on("-v", "--[no-]verbose", "Run verbosely")
+ opts.on("-r", "--require LIBRARY", "Require the LIBRARY before executing your script")
+ end
+ parser.parse %w[--verbose --require optparse], into: options
+
+ options.should == { verbose: true, require: "optparse" }
+ end
+ end
+end
+
+describe "OptionParser#parse!" do
+ ruby_version_is '2.4' do
+ it "accepts `into` keyword argument and stores result in it" do
+ options = {}
+ parser = OptionParser.new do |opts|
+ opts.on("-v", "--[no-]verbose", "Run verbosely")
+ opts.on("-r", "--require LIBRARY", "Require the LIBRARY before executing your script")
+ end
+ parser.parse! %w[--verbose --require optparse], into: options
+
+ options.should == { verbose: true, require: "optparse" }
+ end
+ end
+end
diff --git a/spec/ruby/library/pathname/empty_spec.rb b/spec/ruby/library/pathname/empty_spec.rb
new file mode 100644
index 0000000000..ffe00c32e4
--- /dev/null
+++ b/spec/ruby/library/pathname/empty_spec.rb
@@ -0,0 +1,34 @@
+require File.expand_path('../../spec_helper', __dir__)
+require 'pathname'
+
+ruby_version_is '2.4' do
+ describe 'Pathname#empty?' do
+ before :all do
+ @file = tmp 'new_file_path_name.txt'
+ touch @file
+ @dir = tmp 'new_directory_path_name'
+ Dir.mkdir @dir
+ end
+
+ after :all do
+ rm_r @file
+ rm_r @dir
+ end
+
+ it 'returns true when file is not empty' do
+ Pathname.new(__FILE__).empty?.should be_false
+ end
+
+ it 'returns false when the directory is not empty' do
+ Pathname.new(__dir__).empty?.should be_false
+ end
+
+ it 'return true when file is empty' do
+ Pathname.new(@file).empty?.should be_true
+ end
+
+ it 'returns true when directory is empty' do
+ Pathname.new(@dir).empty?.should be_true
+ end
+ end
+end
diff --git a/spec/ruby/library/pathname/relative_path_from_spec.rb b/spec/ruby/library/pathname/relative_path_from_spec.rb
index b3bc85e307..416eaa1a50 100644
--- a/spec/ruby/library/pathname/relative_path_from_spec.rb
+++ b/spec/ruby/library/pathname/relative_path_from_spec.rb
@@ -14,7 +14,7 @@ describe "Pathname#relative_path_from" do
lambda { relative_path_str('a', '..') }.should raise_error(ArgumentError)
end
- it "retuns a path relative from root" do
+ it "returns a path relative from root" do
relative_path_str('/usr', '/').should == 'usr'
end
diff --git a/spec/ruby/library/rexml/element/add_attributes_spec.rb b/spec/ruby/library/rexml/element/add_attributes_spec.rb
index aa64b677ca..d4c0f0a6e2 100644
--- a/spec/ruby/library/rexml/element/add_attributes_spec.rb
+++ b/spec/ruby/library/rexml/element/add_attributes_spec.rb
@@ -1,7 +1,7 @@
require 'rexml/document'
require File.expand_path('../../../../spec_helper', __FILE__)
-describe "REXML::Element#add_attribute" do
+describe "REXML::Element#add_attributes" do
before :each do
@person = REXML::Element.new "person"
@person.attributes["name"] = "Bill"
diff --git a/spec/ruby/library/rexml/element/add_text_spec.rb b/spec/ruby/library/rexml/element/add_text_spec.rb
index 5d116ee6d3..2f77b5f9f7 100644
--- a/spec/ruby/library/rexml/element/add_text_spec.rb
+++ b/spec/ruby/library/rexml/element/add_text_spec.rb
@@ -1,7 +1,7 @@
require 'rexml/document'
require File.expand_path('../../../../spec_helper', __FILE__)
-describe "REXML::Element#add_namespace" do
+describe "REXML::Element#add_text" do
before :each do
@name = REXML::Element.new "Name"
end
diff --git a/spec/ruby/library/rexml/element/element_reference_spec.rb b/spec/ruby/library/rexml/element/element_reference_spec.rb
new file mode 100644
index 0000000000..eb01169137
--- /dev/null
+++ b/spec/ruby/library/rexml/element/element_reference_spec.rb
@@ -0,0 +1,22 @@
+require 'rexml/document'
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+describe "REXML::Element#[]" do
+
+ before :each do
+ @doc = REXML::Document.new("<root foo='bar'></root>")
+ @child = REXML::Element.new("child")
+ @doc.root.add_element @child
+ end
+
+ ruby_version_is "2.4" do
+ it "return attribute value if argument is string or symbol" do
+ @doc.root[:foo].should == 'bar'
+ @doc.root['foo'].should == 'bar'
+ end
+
+ it "return nth element if argument is int" do
+ @doc.root[0].should == @child
+ end
+ end
+end
diff --git a/spec/ruby/library/securerandom/base64_spec.rb b/spec/ruby/library/securerandom/base64_spec.rb
index 68e61c9ecb..57db25fa29 100644
--- a/spec/ruby/library/securerandom/base64_spec.rb
+++ b/spec/ruby/library/securerandom/base64_spec.rb
@@ -36,7 +36,7 @@ describe "SecureRandom.base64" do
SecureRandom.base64.length.should < 32 * 2
end
- it "treats nil agrument as default one and generates a random base64 string" do
+ it "treats nil argument as default one and generates a random base64 string" do
SecureRandom.base64(nil).should be_kind_of(String)
SecureRandom.base64(nil).length.should < 32 * 2
end
diff --git a/spec/ruby/library/securerandom/hex_spec.rb b/spec/ruby/library/securerandom/hex_spec.rb
index 691392a7b9..8690d8458c 100644
--- a/spec/ruby/library/securerandom/hex_spec.rb
+++ b/spec/ruby/library/securerandom/hex_spec.rb
@@ -35,7 +35,7 @@ describe "SecureRandom.hex" do
SecureRandom.hex.length.should == 32
end
- it "treats nil agrument as default one and generates a random hex string of length 32" do
+ it "treats nil argument as default one and generates a random hex string of length 32" do
SecureRandom.hex(nil).should be_kind_of(String)
SecureRandom.hex(nil).length.should == 32
end
diff --git a/spec/ruby/library/set/compare_by_identity_spec.rb b/spec/ruby/library/set/compare_by_identity_spec.rb
new file mode 100644
index 0000000000..437af9dd0b
--- /dev/null
+++ b/spec/ruby/library/set/compare_by_identity_spec.rb
@@ -0,0 +1,147 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'set'
+
+ruby_version_is '2.4' do
+ describe "Set#compare_by_identity" do
+ it "compares its members by identity" do
+ a = "a"
+ b1 = "b"
+ b2 = "b"
+
+ set = Set.new
+ set.compare_by_identity
+ set.merge([a, a, b1, b2])
+ set.to_a.sort.should == [a, b1, b2].sort
+ end
+
+ it "causes future comparisons on the receiver to be made by identity" do
+ elt = [1]
+ set = Set.new
+ set << elt
+ set.member?(elt.dup).should be_true
+ set.compare_by_identity
+ set.member?(elt.dup).should be_false
+ end
+
+ it "rehashes internally so that old members can be looked up" do
+ set = Set.new
+ (1..10).each { |k| set << k }
+ o = Object.new
+ def o.hash; 123; end
+ set << o
+ set.compare_by_identity
+ set.member?(o).should be_true
+ end
+
+ it "returns self" do
+ set = Set.new
+ result = set.compare_by_identity
+ result.should equal(set)
+ end
+
+ it "is idempotent and has no effect on an already compare_by_identity set" do
+ set = Set.new.compare_by_identity
+ set << :foo
+ set.compare_by_identity.should equal(set)
+ set.compare_by_identity?.should == true
+ set.to_a.should == [:foo]
+ end
+
+ it "uses the semantics of BasicObject#equal? to determine members identity" do
+ :a.equal?(:a).should == true
+ Set.new.compare_by_identity.merge([:a, :a]).to_a.should == [:a]
+
+ ary1 = [1]
+ ary2 = [1]
+ ary1.equal?(ary2).should == false
+ Set.new.compare_by_identity.merge([ary1, ary2]).to_a.sort.should == [ary1, ary2].sort
+ end
+
+ it "uses #equal? semantics, but doesn't actually call #equal? to determine identity" do
+ set = Set.new.compare_by_identity
+ obj = mock("equal")
+ obj.should_not_receive(:equal?)
+ set << :foo
+ set << obj
+ set.to_a.should == [:foo, obj]
+ end
+
+ it "does not call #hash on members" do
+ elt = mock("element")
+ elt.should_not_receive(:hash)
+ set = Set.new.compare_by_identity
+ set << elt
+ set.member?(elt).should be_true
+ end
+
+ it "regards #dup'd objects as having different identities" do
+ a1 = "a"
+ a2 = a1.dup
+
+ set = Set.new.compare_by_identity
+ set.merge([a1, a2])
+ set.to_a.sort.should == [a1, a2].sort
+ end
+
+ it "regards #clone'd objects as having different identities" do
+ a1 = "a"
+ a2 = a1.clone
+
+ set = Set.new.compare_by_identity
+ set.merge([a1, a2])
+ set.to_a.sort.should == [a1, a2].sort
+ end
+
+ it "raises a RuntimeError on frozen sets" do
+ set = Set.new.freeze
+ lambda {
+ set.compare_by_identity
+ }.should raise_error(RuntimeError, /frozen Hash/)
+ end
+
+ it "persists over #dups" do
+ set = Set.new.compare_by_identity
+ set << :a
+ set_dup = set.dup
+ set_dup.should == set
+ set_dup << :a
+ set_dup.to_a.should == [:a]
+ end
+
+ it "persists over #clones" do
+ set = Set.new.compare_by_identity
+ set << :a
+ set_clone = set.clone
+ set_clone.should == set
+ set_clone << :a
+ set_clone.to_a.should == [:a]
+ end
+
+ it "is not equal to set what does not compare by identity" do
+ Set.new([1, 2]).should == Set.new([1, 2])
+ Set.new([1, 2]).should_not == Set.new([1, 2]).compare_by_identity
+ end
+ end
+end
+
+ruby_version_is '2.4' do
+ describe "Set#compare_by_identity?" do
+ it "returns false by default" do
+ Set.new.compare_by_identity?.should == false
+ end
+
+ it "returns true once #compare_by_identity has been invoked on self" do
+ set = Set.new
+ set.compare_by_identity
+ set.compare_by_identity?.should == true
+ end
+
+ it "returns true when called multiple times on the same set" do
+ set = Set.new
+ set.compare_by_identity
+ set.compare_by_identity?.should == true
+ set.compare_by_identity?.should == true
+ set.compare_by_identity?.should == true
+ end
+ end
+end
diff --git a/spec/ruby/library/set/shared/difference.rb b/spec/ruby/library/set/shared/difference.rb
index 9439715da7..52807709c3 100644
--- a/spec/ruby/library/set/shared/difference.rb
+++ b/spec/ruby/library/set/shared/difference.rb
@@ -3,7 +3,7 @@ describe :set_difference, shared: true do
@set = Set[:a, :b, :c]
end
- it "returns a new Set containting self's elements excluding the elements in the passed Enumerable" do
+ it "returns a new Set containing self's elements excluding the elements in the passed Enumerable" do
@set.send(@method, Set[:a, :b]).should == Set[:c]
@set.send(@method, [:b, :c]).should == Set[:a]
end
diff --git a/spec/ruby/library/set/sortedset/shared/difference.rb b/spec/ruby/library/set/sortedset/shared/difference.rb
index ec57015ac2..cf50ff0eb2 100644
--- a/spec/ruby/library/set/sortedset/shared/difference.rb
+++ b/spec/ruby/library/set/sortedset/shared/difference.rb
@@ -3,7 +3,7 @@ describe :sorted_set_difference, shared: true do
@set = SortedSet["a", "b", "c"]
end
- it "returns a new SortedSet containting self's elements excluding the elements in the passed Enumerable" do
+ it "returns a new SortedSet containing self's elements excluding the elements in the passed Enumerable" do
@set.send(@method, SortedSet["a", "b"]).should == SortedSet["c"]
@set.send(@method, ["b", "c"]).should == SortedSet["a"]
end
diff --git a/spec/ruby/library/shellwords/shellwords_spec.rb b/spec/ruby/library/shellwords/shellwords_spec.rb
index aa35c1a5c3..f8ab0cbd9d 100644
--- a/spec/ruby/library/shellwords/shellwords_spec.rb
+++ b/spec/ruby/library/shellwords/shellwords_spec.rb
@@ -26,4 +26,11 @@ describe "Shellwords#shellwords" do
it "raises ArgumentError when single quoted strings are misquoted" do
lambda { shellwords("a 'b c d e") }.should raise_error(ArgumentError)
end
+
+ ruby_version_is '2.4' do
+ # https://bugs.ruby-lang.org/issues/10055
+ it "matches POSIX sh behavior for backslashes within double quoted strings" do
+ shellsplit('printf "%s\n"').should == ['printf', '%s\n']
+ end
+ end
end
diff --git a/spec/ruby/library/socket/tcpserver/accept_spec.rb b/spec/ruby/library/socket/tcpserver/accept_spec.rb
index f7b017d014..e7a1d87dbe 100644
--- a/spec/ruby/library/socket/tcpserver/accept_spec.rb
+++ b/spec/ruby/library/socket/tcpserver/accept_spec.rb
@@ -48,14 +48,15 @@ describe "TCPServer#accept" do
end
it "can be interrupted by Thread#raise" do
- t = Thread.new { @server.accept }
+ t = Thread.new {
+ -> {
+ @server.accept
+ }.should raise_error(Exception, "interrupted")
+ }
Thread.pass while t.status and t.status != "sleep"
-
- # raise in thread, ensure the raise happens
- ex = Exception.new
- t.raise ex
- lambda { t.join }.should raise_error(Exception)
+ t.raise Exception, "interrupted"
+ t.join
end
it "raises an IOError if the socket is closed" do
diff --git a/spec/ruby/library/socket/tcpserver/new_spec.rb b/spec/ruby/library/socket/tcpserver/new_spec.rb
index ddbe96d89d..adbc3f303e 100644
--- a/spec/ruby/library/socket/tcpserver/new_spec.rb
+++ b/spec/ruby/library/socket/tcpserver/new_spec.rb
@@ -62,7 +62,7 @@ describe "TCPServer.new" do
# pick such a service port that will be able to reliably bind...
end
- it "raises Errno::EADDRNOTAVAIL when the adress is unknown" do
+ it "raises Errno::EADDRNOTAVAIL when the address is unknown" do
lambda { TCPServer.new("1.2.3.4", 0) }.should raise_error(Errno::EADDRNOTAVAIL)
end
diff --git a/spec/ruby/library/socket/unixserver/accept_spec.rb b/spec/ruby/library/socket/unixserver/accept_spec.rb
index 90b22d7eb1..3921dadd9d 100644
--- a/spec/ruby/library/socket/unixserver/accept_spec.rb
+++ b/spec/ruby/library/socket/unixserver/accept_spec.rb
@@ -48,14 +48,14 @@ platform_is_not :windows do
it "can be interrupted by Thread#raise" do
t = Thread.new {
- @server.accept
+ -> {
+ @server.accept
+ }.should raise_error(Exception, "interrupted")
}
- Thread.pass while t.status and t.status != "sleep"
- # raise in thread, ensure the raise happens
- ex = Exception.new
- t.raise ex
- lambda { t.join }.should raise_error(Exception)
+ Thread.pass while t.status and t.status != "sleep"
+ t.raise Exception, "interrupted"
+ t.join
end
end
end
diff --git a/spec/ruby/library/stringio/each_line_spec.rb b/spec/ruby/library/stringio/each_line_spec.rb
index e4deb9b3e9..d770c18e67 100644
--- a/spec/ruby/library/stringio/each_line_spec.rb
+++ b/spec/ruby/library/stringio/each_line_spec.rb
@@ -13,3 +13,9 @@ end
describe "StringIO#each_line when self is not readable" do
it_behaves_like :stringio_each_not_readable, :each_line
end
+
+ruby_version_is "2.4" do
+ describe "StringIO#each_line when passed chomp" do
+ it_behaves_like :stringio_each_chomp, :each_line
+ end
+end
diff --git a/spec/ruby/library/stringio/each_spec.rb b/spec/ruby/library/stringio/each_spec.rb
index 07ad070192..cebaa345d8 100644
--- a/spec/ruby/library/stringio/each_spec.rb
+++ b/spec/ruby/library/stringio/each_spec.rb
@@ -13,3 +13,9 @@ end
describe "StringIO#each when self is not readable" do
it_behaves_like :stringio_each_not_readable, :each
end
+
+ruby_version_is "2.4" do
+ describe "StringIO#each when passed chomp" do
+ it_behaves_like :stringio_each_chomp, :each
+ end
+end
diff --git a/spec/ruby/library/stringio/getc_spec.rb b/spec/ruby/library/stringio/getc_spec.rb
index f7e98d2a33..804502d8ba 100644
--- a/spec/ruby/library/stringio/getc_spec.rb
+++ b/spec/ruby/library/stringio/getc_spec.rb
@@ -5,7 +5,7 @@ require File.expand_path('../shared/getc', __FILE__)
describe "StringIO#getc" do
it_behaves_like :stringio_getc, :getc
- it "returns the charactor at the current position" do
+ it "returns the character at the current position" do
io = StringIO.new("example")
io.send(@method).should == ?e
diff --git a/spec/ruby/library/stringio/getch_spec.rb b/spec/ruby/library/stringio/getch_spec.rb
index c7fdfe9080..d6f652424e 100644
--- a/spec/ruby/library/stringio/getch_spec.rb
+++ b/spec/ruby/library/stringio/getch_spec.rb
@@ -9,7 +9,7 @@ describe "StringIO#getch" do
it_behaves_like :stringio_getc, :getch
- it "returns the charactor at the current position" do
+ it "returns the character at the current position" do
io = StringIO.new("example")
io.send(@method).should == ?e
diff --git a/spec/ruby/library/stringio/gets_spec.rb b/spec/ruby/library/stringio/gets_spec.rb
index 307f564a6e..f94448688b 100644
--- a/spec/ruby/library/stringio/gets_spec.rb
+++ b/spec/ruby/library/stringio/gets_spec.rb
@@ -6,7 +6,7 @@ describe "StringIO#gets when passed [separator]" do
@io = StringIO.new("this>is>an>example")
end
- it "returns the data read till the next occurence of the passed separator" do
+ it "returns the data read till the next occurrence of the passed separator" do
@io.gets(">").should == "this>"
@io.gets(">").should == "is>"
@io.gets(">").should == "an>"
@@ -72,7 +72,7 @@ describe "StringIO#gets when passed no argument" do
@io = StringIO.new("this is\nan example\nfor StringIO#gets")
end
- it "returns the data read till the next occurence of $/ or till eof" do
+ it "returns the data read till the next occurrence of $/ or till eof" do
@io.gets.should == "this is\n"
begin
@@ -236,3 +236,12 @@ describe "StringIO#gets when in write-only mode" do
lambda { io.gets }.should raise_error(IOError)
end
end
+
+ruby_version_is "2.4" do
+ describe "StringIO#gets when passed [chomp]" do
+ it "returns the data read without a trailing newline character" do
+ io = StringIO.new("this>is>an>example\n")
+ io.gets(chomp: true).should == "this>is>an>example"
+ end
+ end
+end \ No newline at end of file
diff --git a/spec/ruby/library/stringio/lines_spec.rb b/spec/ruby/library/stringio/lines_spec.rb
index 550b25549e..c3af802073 100644
--- a/spec/ruby/library/stringio/lines_spec.rb
+++ b/spec/ruby/library/stringio/lines_spec.rb
@@ -13,3 +13,9 @@ end
describe "StringIO#lines when self is not readable" do
it_behaves_like :stringio_each_not_readable, :lines
end
+
+ruby_version_is "2.4" do
+ describe "StringIO#lines when passed chomp" do
+ it_behaves_like :stringio_each_chomp, :lines
+ end
+end
diff --git a/spec/ruby/library/stringio/readline_spec.rb b/spec/ruby/library/stringio/readline_spec.rb
index 90890e3ad1..1deb52c492 100644
--- a/spec/ruby/library/stringio/readline_spec.rb
+++ b/spec/ruby/library/stringio/readline_spec.rb
@@ -7,7 +7,7 @@ describe "StringIO#readline when passed [separator]" do
@io = StringIO.new("this>is>an>example")
end
- it "returns the data read till the next occurence of the passed separator" do
+ it "returns the data read till the next occurrence of the passed separator" do
@io.readline(">").should == "this>"
@io.readline(">").should == "is>"
@io.readline(">").should == "an>"
@@ -60,7 +60,7 @@ describe "StringIO#readline when passed no argument" do
@io = StringIO.new("this is\nan example\nfor StringIO#readline")
end
- it "returns the data read till the next occurence of $/ or till eof" do
+ it "returns the data read till the next occurrence of $/ or till eof" do
@io.readline.should == "this is\n"
begin
@@ -120,3 +120,12 @@ describe "StringIO#readline when in write-only mode" do
lambda { io.readline }.should raise_error(IOError)
end
end
+
+ruby_version_is "2.4" do
+ describe "StringIO#readline when passed [chomp]" do
+ it "returns the data read without a trailing newline character" do
+ io = StringIO.new("this>is>an>example\n")
+ io.readline(chomp: true).should == "this>is>an>example"
+ end
+ end
+end
diff --git a/spec/ruby/library/stringio/readlines_spec.rb b/spec/ruby/library/stringio/readlines_spec.rb
index 215a6cbb2a..11217d1e59 100644
--- a/spec/ruby/library/stringio/readlines_spec.rb
+++ b/spec/ruby/library/stringio/readlines_spec.rb
@@ -90,3 +90,12 @@ describe "StringIO#readlines when in write-only mode" do
lambda { io.readlines }.should raise_error(IOError)
end
end
+
+ruby_version_is "2.4" do
+ describe "StringIO#readlines when passed [chomp]" do
+ it "returns the data read without a trailing newline character" do
+ io = StringIO.new("this>is\nan>example\r\n")
+ io.readlines(chomp: true).should == ["this>is", "an>example"]
+ end
+ end
+end
diff --git a/spec/ruby/library/stringio/shared/each.rb b/spec/ruby/library/stringio/shared/each.rb
index 0fde23634e..55ed27c1c7 100644
--- a/spec/ruby/library/stringio/shared/each.rb
+++ b/spec/ruby/library/stringio/shared/each.rb
@@ -103,3 +103,12 @@ describe :stringio_each_not_readable, shared: true do
lambda { io.send(@method) { |b| b } }.should raise_error(IOError)
end
end
+
+describe :stringio_each_chomp, shared: true do
+ it "yields each line with removed newline characters to the passed block" do
+ seen = []
+ io = StringIO.new("a b \rc d e\n1 2 3 4 5\r\nthe end")
+ io.send(@method, chomp: true) {|s| seen << s }
+ seen.should == ["a b \rc d e", "1 2 3 4 5", "the end"]
+ end
+end
diff --git a/spec/ruby/library/time/to_time_spec.rb b/spec/ruby/library/time/to_time_spec.rb
new file mode 100644
index 0000000000..a02ec31cb9
--- /dev/null
+++ b/spec/ruby/library/time/to_time_spec.rb
@@ -0,0 +1,17 @@
+require File.expand_path('../../../spec_helper', __FILE__)
+require 'time'
+
+ruby_version_is "2.4" do
+ describe "Time#to_time" do
+ it "returns itself in the same timezone" do
+ time = Time.new(2012, 2, 21, 10, 11, 12)
+
+ with_timezone("America/Regina") do
+ time.to_time.should equal time
+ end
+
+ time2 = Time.utc(2012, 2, 21, 10, 11, 12)
+ time2.to_time.should equal time2
+ end
+ end
+end
diff --git a/spec/ruby/library/win32ole/win32ole_method/new_spec.rb b/spec/ruby/library/win32ole/win32ole_method/new_spec.rb
index fc8d1d7691..f904107c6c 100644
--- a/spec/ruby/library/win32ole/win32ole_method/new_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_method/new_spec.rb
@@ -10,7 +10,7 @@ platform_is :windows do
lambda { WIN32OLE_METHOD.new(1, 2) }.should raise_error TypeError
end
- it "raises ArgumentError if only 1 arugment is given" do
+ it "raises ArgumentError if only 1 argument is given" do
lambda { WIN32OLE_METHOD.new("hello") }.should raise_error ArgumentError
lambda { WIN32OLE_METHOD.new(@ole_type) }.should raise_error ArgumentError
end
diff --git a/spec/ruby/library/yaml/shared/each_document.rb b/spec/ruby/library/yaml/shared/each_document.rb
index 5d9d240005..999123dc2a 100644
--- a/spec/ruby/library/yaml/shared/each_document.rb
+++ b/spec/ruby/library/yaml/shared/each_document.rb
@@ -1,5 +1,5 @@
describe :yaml_each_document, shared: true do
- it "calls the block on each succesive document" do
+ it "calls the block on each successive document" do
documents = []
YAML.send(@method, $multidocument) do |doc|
documents << doc
diff --git a/spec/ruby/library/yaml/to_yaml_spec.rb b/spec/ruby/library/yaml/to_yaml_spec.rb
index d129fe2d79..afe583d502 100644
--- a/spec/ruby/library/yaml/to_yaml_spec.rb
+++ b/spec/ruby/library/yaml/to_yaml_spec.rb
@@ -46,7 +46,7 @@ describe "Object#to_yaml" do
nil_klass.to_yaml.should match_yaml("--- \n")
end
- it "returns the YAML represenation of a RegExp object" do
+ it "returns the YAML representation of a RegExp object" do
Regexp.new('^a-z+:\\s+\w+').to_yaml.should match_yaml("--- !ruby/regexp /^a-z+:\\s+\\w+/\n")
end
diff --git a/spec/ruby/optional/capi/encoding_spec.rb b/spec/ruby/optional/capi/encoding_spec.rb
index 9408c0c6c5..d6b0bacd70 100644
--- a/spec/ruby/optional/capi/encoding_spec.rb
+++ b/spec/ruby/optional/capi/encoding_spec.rb
@@ -88,7 +88,7 @@ describe "C-API Encoding function" do
end
it "returns -1 for an non existing encoding" do
- @s.rb_enc_find_index("non-existant-encoding").should == -1
+ @s.rb_enc_find_index("non-existent-encoding").should == -1
end
end
diff --git a/spec/ruby/optional/capi/ext/kernel_spec.c b/spec/ruby/optional/capi/ext/kernel_spec.c
index f126bd0a4a..226354e18a 100644
--- a/spec/ruby/optional/capi/ext/kernel_spec.c
+++ b/spec/ruby/optional/capi/ext/kernel_spec.c
@@ -230,6 +230,19 @@ static VALUE kernel_spec_rb_yield(VALUE self, VALUE obj) {
return rb_yield(obj);
}
+static VALUE kernel_spec_rb_yield_each(int argc, VALUE *args, VALUE self) {
+ int i;
+ for(i = 0; i < 4; i++) {
+ rb_yield(INT2FIX(i));
+ }
+ return INT2FIX(4);
+}
+
+static VALUE kernel_spec_rb_yield_define_each(VALUE self, VALUE cls) {
+ rb_define_method(cls, "each", kernel_spec_rb_yield_each, -1);
+ return Qnil;
+}
+
static int kernel_cb(const void *a, const void *b) {
rb_yield(Qtrue);
return 0;
@@ -392,6 +405,7 @@ void Init_kernel_spec(void) {
#ifdef HAVE_RB_YIELD
rb_define_method(cls, "rb_yield", kernel_spec_rb_yield, 1);
rb_define_method(cls, "rb_yield_indirected", kernel_spec_rb_yield_indirected, 1);
+ rb_define_method(cls, "rb_yield_define_each", kernel_spec_rb_yield_define_each, 1);
#endif
#ifdef HAVE_RB_YIELD_VALUES
diff --git a/spec/ruby/optional/capi/ext/rubyspec.h b/spec/ruby/optional/capi/ext/rubyspec.h
index 12c71d98b0..aab74b88ae 100644
--- a/spec/ruby/optional/capi/ext/rubyspec.h
+++ b/spec/ruby/optional/capi/ext/rubyspec.h
@@ -557,6 +557,7 @@
#define HAVE_RB_STR_SUBSEQ 1
#define HAVE_RB_VSPRINTF 1
#define HAVE_RB_STRING 1
+#define HAVE_SAFE_STRING_VALUE 1
/* Struct */
#define HAVE_RB_STRUCT_AREF 1
diff --git a/spec/ruby/optional/capi/ext/string_spec.c b/spec/ruby/optional/capi/ext/string_spec.c
index 0568b42212..929d69f9e5 100644
--- a/spec/ruby/optional/capi/ext/string_spec.c
+++ b/spec/ruby/optional/capi/ext/string_spec.c
@@ -181,6 +181,10 @@ VALUE string_spec_rb_str_length(VALUE self, VALUE str) {
VALUE string_spec_rb_str_new(VALUE self, VALUE str, VALUE len) {
return rb_str_new(RSTRING_PTR(str), FIX2INT(len));
}
+
+VALUE string_spec_rb_str_new_offset(VALUE self, VALUE str, VALUE offset, VALUE len) {
+ return rb_str_new(RSTRING_PTR(str) + FIX2INT(offset), FIX2INT(len));
+}
#endif
#ifdef HAVE_RB_STR_NEW2
@@ -370,6 +374,13 @@ VALUE string_spec_StringValue(VALUE self, VALUE str) {
}
#endif
+#ifdef HAVE_SAFE_STRING_VALUE
+static VALUE string_spec_SafeStringValue(VALUE self, VALUE str) {
+ SafeStringValue(str);
+ return str;
+}
+#endif
+
#ifdef HAVE_RB_STR_HASH
static VALUE string_spec_rb_str_hash(VALUE self, VALUE str) {
st_index_t val = rb_str_hash(str);
@@ -529,6 +540,7 @@ void Init_string_spec(void) {
#ifdef HAVE_RB_STR_NEW
rb_define_method(cls, "rb_str_new", string_spec_rb_str_new, 2);
+ rb_define_method(cls, "rb_str_new_offset", string_spec_rb_str_new_offset, 3);
#endif
#ifdef HAVE_RB_STR_NEW2
@@ -639,6 +651,10 @@ void Init_string_spec(void) {
rb_define_method(cls, "StringValue", string_spec_StringValue, 1);
#endif
+#ifdef HAVE_SAFE_STRING_VALUE
+ rb_define_method(cls, "SafeStringValue", string_spec_SafeStringValue, 1);
+#endif
+
#ifdef HAVE_RB_STR_HASH
rb_define_method(cls, "rb_str_hash", string_spec_rb_str_hash, 1);
#endif
diff --git a/spec/ruby/optional/capi/kernel_spec.rb b/spec/ruby/optional/capi/kernel_spec.rb
index 47f368b517..73928b3154 100644
--- a/spec/ruby/optional/capi/kernel_spec.rb
+++ b/spec/ruby/optional/capi/kernel_spec.rb
@@ -198,6 +198,16 @@ describe "C-API Kernel function" do
@s.rb_yield_indirected(1) { break 73 }.should == 73
end
end
+
+ it "rb_yield to block passed to enumerator" do
+ enum_class = Class.new do
+ include Enumerable
+ end
+ @s.rb_yield_define_each(enum_class)
+ res = enum_class.new.collect { |i| i * 2}
+ res.should == [0, 2, 4, 6]
+ end
+
end
describe "rb_yield_values" do
diff --git a/spec/ruby/optional/capi/object_spec.rb b/spec/ruby/optional/capi/object_spec.rb
index b16d26ce47..cf7ea2e8cf 100644
--- a/spec/ruby/optional/capi/object_spec.rb
+++ b/spec/ruby/optional/capi/object_spec.rb
@@ -420,6 +420,13 @@ describe "CApiObject" do
@o.rb_class_of(0.1).should == Float
@o.rb_class_of(ObjectTest.new).should == ObjectTest
end
+
+ it "returns the singleton class if it exists" do
+ o = ObjectTest.new
+ @o.rb_class_of(o).should equal ObjectTest
+ s = o.singleton_class
+ @o.rb_class_of(o).should equal s
+ end
end
describe "rb_obj_classname" do
diff --git a/spec/ruby/optional/capi/proc_spec.rb b/spec/ruby/optional/capi/proc_spec.rb
index 1cd8de9a86..ca6163b574 100644
--- a/spec/ruby/optional/capi/proc_spec.rb
+++ b/spec/ruby/optional/capi/proc_spec.rb
@@ -64,7 +64,7 @@ describe "C-API when calling Proc.new from a C function" do
# In the scenarios below: X -> Y means execution context X called to Y.
# For example: Ruby -> C means a Ruby code called a C function.
#
- # X -> Y <- X -> Z means exection context X called Y which returned to X,
+ # X -> Y <- X -> Z means execution context X called Y which returned to X,
# then X called Z.
# For example: C -> Ruby <- C -> Ruby means a C function called into Ruby
# code which returned to C, then C called into Ruby code again.
diff --git a/spec/ruby/optional/capi/spec_helper.rb b/spec/ruby/optional/capi/spec_helper.rb
index 21d2cd04c5..a5f64b51fb 100644
--- a/spec/ruby/optional/capi/spec_helper.rb
+++ b/spec/ruby/optional/capi/spec_helper.rb
@@ -23,11 +23,18 @@ def compile_extension(name)
ext = "#{name}_spec"
lib = "#{object_path}/#{ext}.#{RbConfig::CONFIG['DLEXT']}"
ruby_header = "#{RbConfig::CONFIG['rubyhdrdir']}/ruby.h"
+ libruby_so = RbConfig::CONFIG['LIBRUBY_SO']
+ ruby_library = "#{RbConfig::CONFIG['libdir']}/#{libruby_so}"
+ unless libruby_so and File.exist?(ruby_library)
+ # Statically-compiled lib in the binary
+ ruby_library = RbConfig.ruby
+ end
return lib if File.exist?(lib) and
File.mtime(lib) > File.mtime("#{extension_path}/rubyspec.h") and
File.mtime(lib) > File.mtime("#{extension_path}/#{ext}.c") and
File.mtime(lib) > File.mtime(ruby_header) and
+ File.mtime(lib) > File.mtime(ruby_library) and
true # sentinel
# Copy needed source files to tmpdir
diff --git a/spec/ruby/optional/capi/string_spec.rb b/spec/ruby/optional/capi/string_spec.rb
index 25ef10b6f6..73e6deb498 100644
--- a/spec/ruby/optional/capi/string_spec.rb
+++ b/spec/ruby/optional/capi/string_spec.rb
@@ -100,6 +100,10 @@ describe "C-API String function" do
it "returns an empty string if len is 0" do
@s.rb_str_new("hello", 0).should == ""
end
+
+ it "returns a string from an offset char buffer" do
+ @s.rb_str_new_offset("hello", 1, 3).should == "ell"
+ end
end
describe "rb_str_new2" do
@@ -439,32 +443,53 @@ describe "C-API String function" do
end
end
- describe "StringValue" do
+ describe :string_value_macro, shared: true do
+ before :each do
+ @s = CApiStringSpecs.new
+ end
+
it "does not call #to_str on a String" do
str = "genuine"
str.should_not_receive(:to_str)
- @s.StringValue(str)
+ @s.send(@method, str)
end
it "does not call #to_s on a String" do
str = "genuine"
str.should_not_receive(:to_str)
- @s.StringValue(str)
+ @s.send(@method, str)
end
it "calls #to_str on non-String objects" do
str = mock("fake")
str.should_receive(:to_str).and_return("wannabe")
- @s.StringValue(str)
+ @s.send(@method, str).should == "wannabe"
end
it "does not call #to_s on non-String objects" do
str = mock("fake")
str.should_not_receive(:to_s)
- lambda { @s.StringValue(str) }.should raise_error(TypeError)
+ lambda { @s.send(@method, str) }.should raise_error(TypeError)
end
end
+ describe "StringValue" do
+ it_behaves_like :string_value_macro, :StringValue
+ end
+
+ describe "SafeStringValue" do
+ it "raises for tained string when $SAFE is 1" do
+ Thread.new {
+ $SAFE = 1
+ lambda {
+ @s.SafeStringValue("str".taint)
+ }.should raise_error(SecurityError)
+ }.join
+ end
+
+ it_behaves_like :string_value_macro, :SafeStringValue
+ end
+
describe "rb_str_resize" do
it "reduces the size of the string" do
str = @s.rb_str_resize("test", 2)
diff --git a/spec/ruby/optional/capi/thread_spec.rb b/spec/ruby/optional/capi/thread_spec.rb
index 0ca701e35d..ab3d609bcf 100644
--- a/spec/ruby/optional/capi/thread_spec.rb
+++ b/spec/ruby/optional/capi/thread_spec.rb
@@ -21,7 +21,7 @@ describe "C-API Thread function" do
end
describe "rb_thread_wait_for" do
- it "sleeps the current thread for the give ammount of time" do
+ it "sleeps the current thread for the give amount of time" do
start = Time.now
@t.rb_thread_wait_for(0, 100_000)
(Time.now - start).should be_close(0.1, 0.2)
@@ -78,8 +78,11 @@ describe "C-API Thread function" do
end
it "handles throwing an exception in the thread" do
- proc = lambda { |x| raise "my error" }
- thr = @t.rb_thread_create(proc, nil)
+ prc = lambda { |x|
+ Thread.current.report_on_exception = false
+ raise "my error"
+ }
+ thr = @t.rb_thread_create(prc, nil)
thr.should be_kind_of(Thread)
lambda {
diff --git a/spec/ruby/shared/fiber/resume.rb b/spec/ruby/shared/fiber/resume.rb
index a680839a4b..058ef4e15a 100644
--- a/spec/ruby/shared/fiber/resume.rb
+++ b/spec/ruby/shared/fiber/resume.rb
@@ -10,13 +10,13 @@ describe :fiber_resume, shared: true do
end
it "raises a FiberError if invoked from a different Thread" do
- fiber = Fiber.new { }
- lambda do
- Thread.new do
+ fiber = Fiber.new { 42 }
+ Thread.new do
+ -> {
fiber.resume
- end.join
- end.should raise_error(FiberError)
- fiber.resume
+ }.should raise_error(FiberError)
+ end.join
+ fiber.resume.should == 42
end
it "passes control to the beginning of the block on first invocation" do
diff --git a/spec/ruby/shared/rational/minus.rb b/spec/ruby/shared/rational/minus.rb
index 01c743be72..e23430111e 100644
--- a/spec/ruby/shared/rational/minus.rb
+++ b/spec/ruby/shared/rational/minus.rb
@@ -1,7 +1,7 @@
require File.expand_path('../../../spec_helper', __FILE__)
describe :rational_minus_rat, shared: true do
- it "returns the result of substracting other from self as a Rational" do
+ it "returns the result of subtracting other from self as a Rational" do
(Rational(3, 4) - Rational(0, 1)).should eql(Rational(3, 4))
(Rational(3, 4) - Rational(1, 4)).should eql(Rational(1, 2))
@@ -10,14 +10,14 @@ describe :rational_minus_rat, shared: true do
end
describe :rational_minus_int, shared: true do
- it "returns the result of substracting other from self as a Rational" do
+ it "returns the result of subtracting other from self as a Rational" do
(Rational(3, 4) - 1).should eql(Rational(-1, 4))
(Rational(3, 4) - 2).should eql(Rational(-5, 4))
end
end
describe :rational_minus_float, shared: true do
- it "returns the result of substracting other from self as a Float" do
+ it "returns the result of subtracting other from self as a Float" do
(Rational(3, 4) - 0.2).should eql(0.55)
(Rational(3, 4) - 2.5).should eql(-1.75)
end
diff --git a/spec/ruby/shared/rational/plus.rb b/spec/ruby/shared/rational/plus.rb
index d078a41425..e37c757c13 100644
--- a/spec/ruby/shared/rational/plus.rb
+++ b/spec/ruby/shared/rational/plus.rb
@@ -1,7 +1,7 @@
require File.expand_path('../../../spec_helper', __FILE__)
describe :rational_plus_rat, shared: true do
- it "returns the result of substracting other from self as a Rational" do
+ it "returns the result of subtracting other from self as a Rational" do
(Rational(3, 4) + Rational(0, 1)).should eql(Rational(3, 4))
(Rational(3, 4) + Rational(1, 4)).should eql(Rational(1, 1))
@@ -10,14 +10,14 @@ describe :rational_plus_rat, shared: true do
end
describe :rational_plus_int, shared: true do
- it "returns the result of substracting other from self as a Rational" do
+ it "returns the result of subtracting other from self as a Rational" do
(Rational(3, 4) + 1).should eql(Rational(7, 4))
(Rational(3, 4) + 2).should eql(Rational(11, 4))
end
end
describe :rational_plus_float, shared: true do
- it "returns the result of substracting other from self as a Float" do
+ it "returns the result of subtracting other from self as a Float" do
(Rational(3, 4) + 0.2).should eql(0.95)
(Rational(3, 4) + 2.5).should eql(3.25)
end
diff --git a/spec/ruby/shared/rational/round.rb b/spec/ruby/shared/rational/round.rb
index 8874daceea..c7a4cc6d07 100644
--- a/spec/ruby/shared/rational/round.rb
+++ b/spec/ruby/shared/rational/round.rb
@@ -68,4 +68,29 @@ describe :rational_round, shared: true do
Rational(3, 2).round(2_097_171).should == Rational(3, 2)
end
end
+
+ ruby_version_is "2.4" do
+ describe "with half option" do
+ it "returns an Integer when precision is not passed" do
+ Rational(10, 4).round(half: :up).should == 3
+ Rational(10, 4).round(half: :down).should == 2
+ Rational(10, 4).round(half: :even).should == 2
+ Rational(-10, 4).round(half: :up).should == -3
+ Rational(-10, 4).round(half: :down).should == -2
+ Rational(-10, 4).round(half: :even).should == -2
+ end
+
+ it "returns a Rational when the precision is greater than 0" do
+ Rational(25, 100).round(1, half: :up).should == Rational(3, 10)
+ Rational(25, 100).round(1, half: :down).should == Rational(1, 5)
+ Rational(25, 100).round(1, half: :even).should == Rational(1, 5)
+ Rational(35, 100).round(1, half: :up).should == Rational(2, 5)
+ Rational(35, 100).round(1, half: :down).should == Rational(3, 10)
+ Rational(35, 100).round(1, half: :even).should == Rational(2, 5)
+ Rational(-25, 100).round(1, half: :up).should == Rational(-3, 10)
+ Rational(-25, 100).round(1, half: :down).should == Rational(-1, 5)
+ Rational(-25, 100).round(1, half: :even).should == Rational(-1, 5)
+ end
+ end
+ end
end
diff --git a/spec/ruby/spec_helper.rb b/spec/ruby/spec_helper.rb
index c275e320ec..e7873ce594 100644
--- a/spec/ruby/spec_helper.rb
+++ b/spec/ruby/spec_helper.rb
@@ -3,6 +3,17 @@ root = File.dirname(__FILE__)
dir = "fixtures/code"
CODE_LOADING_DIR = use_realpath ? File.realpath(dir, root) : File.expand_path(dir, root)
+# Enable Thread.report_on_exception by default to catch thread errors earlier
+if Thread.respond_to? :report_on_exception=
+ Thread.report_on_exception = true
+else
+ class Thread
+ def report_on_exception=(value)
+ raise "shim Thread#report_on_exception used with true" if value
+ end
+ end
+end
+
# Running directly with ruby some_spec.rb
unless ENV['MSPEC_RUNNER']
begin