summaryrefslogtreecommitdiff
path: root/spec/ruby
diff options
context:
space:
mode:
authoreregon <eregon@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-10-28 15:15:48 +0000
committereregon <eregon@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-10-28 15:15:48 +0000
commit8c5b60eb22d6d661e87992a65d54e3a5bc0aeed4 (patch)
tree7905b284cb5b3d62c17ad8a939e339621a498a2c /spec/ruby
parent6530b14cee76e2512424d225e64d3c61dd1f6511 (diff)
Update to ruby/spec@a6b8805
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60525 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'spec/ruby')
-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 a776517b738..d8b9aa7f8a1 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 cb91f43ead3..1d68068121d 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 1a2e64ff84f..e8a9106ac17 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 e675a61afaf..fc88475970e 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 e40c26f2ccb..f2af0e13a15 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 4d6c2a12d3f..e399509ea73 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 cf6a48c2e38..db1d755645b 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 53fe4e06922..59f3814da2e 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 00000000000..928f7db731b
--- /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 8a80b93c3bc..c0eba57a3e7 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 313dc4189eb..ea649c65850 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 e5d25e20506..a7b6f58392c 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 00000000000..6548655c353
--- /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 cf99bb4937f..3df43aec2db 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 00000000000..e9ee19bef3e
--- /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 00000000000..79792c31695
--- /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 00000000000..861a538f849
--- /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 b65b738b611..4a9230f8b3e 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 b9d6288bb27..ed479c6b13b 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 f92c95c6d55..cba654b9fe8 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 69ce59e89bd..3ed1ad9956b 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 41320c52075..428b292c68d 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 75514e5229a..09379acc5d7 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 4a7aba20446..742184250f1 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 984862646c0..0489ad82bf9 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 4f7af68b075..4a7511f6493 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 2f5760992db..9089a94963e 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 1bcdc0ee9a2..4013a639ce1 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 0ede0170ceb..5ca7556aed5 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 03ff9a0fb6e..1a218c1b0fc 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 00000000000..b04e641a41c
--- /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 00000000000..766aa95e46a
--- /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 6db2c09780b..b529cd1355c 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 80e37b3fffe..9b423ae47e3 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 8a050fd25e7..7f72f95e94e 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 8037164c684..f1d9dcd8234 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 00000000000..775dc2913c4
--- /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 63a5138366b..6da5d5c5eee 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 46d23b36d09..56668d5856b 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 85ee8ef5801..7feeb817358 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 a45b8cd1716..a41fad3586b 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 7e4ff45bea6..0c9e43d6214 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 7a49ede0df1..31c56f378d0 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 00000000000..3546a654eb8
--- /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 00000000000..f46bdf89bda
--- /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 b533a84ad41..9babcd9a3e6 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 a6f406cba00..393f072563b 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 5cc9aa38812..5a46e6cba64 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 00000000000..ecbda1bb4a5
--- /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 00000000000..b7d9ef441b2
--- /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 b503b1e4e89..429ab1a3124 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 460b50a59d8..44cd32df942 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 fb431d5023f..a771e3d929e 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 d984e795c28..6e0518b5125 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 39706948eb4..a1cddafe5cf 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 dc07434ecd2..d87303b54a3 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 4cb821274a3..f545d8876ab 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 670987ead20..a66493f2835 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 0b740804921..6aba948ce03 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 00000000000..2dc6de52ca8
--- /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 00000000000..48620c325fe
--- /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 00000000000..ed18cdca391
--- /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 00000000000..46975361ddf
--- /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 00000000000..0ed9355af10
--- /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 00000000000..03e70915e28
--- /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 00000000000..32e8f8f96b3
--- /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 98deabe0563..b5c2b168e83 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 00000000000..10b1209736a
--- /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 9b6297d5da8..820d900dd56 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 00000000000..9fb2252845e
--- /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 00000000000..a527cb43700
--- /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 8e1ac763f11..d1f3a47b7f4 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 2434a4e72ec..d954261329f 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 e2d2b68caa1..497e1453cde 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 fdb888ff2b6..c77d97815c7 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 9ebc4f2bd1e..f591c0fa099 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 6aa47ea7285..e5f24816afc 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 0a246f6f534..b429ac48d2b 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 2f7280a95f0..c1cf324dc52 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 1ee13c82f47..68f82b44686 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 fe8b76b47b6..dee741e2702 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 501247078d2..1180d647123 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 e9af647727e..c2b583acab7 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 00000000000..6941bc11732
--- /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 2fdcce86b95..00943806643 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 59fc5ef9aaa..989459114af 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 cf7e8a007f3..73850a2a8c5 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 942bd15998d..352c5b99cb3 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 0b2422ad3e0..6eb19e087a2 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 00000000000..2ca4d840787
--- /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 fdc42ec4775..3124f782bc7 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 fce62af1002..fe2c88d294b 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 47b4d06328f..b76078f685c 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 b572c8dd82d..601e515e3e0 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 a6dd2da9a31..249b3d333ee 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 6cdfc3ca7f3..d82a21ab396 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 93e0f048b1e..8724d262020 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 00000000000..4128dad4707
--- /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 f15da360fd1..0c9198c538b 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 82c0cbf7620..3d900959df4 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 f570aeedd23..c35115fcf40 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 87b52d9f8d1..120d8d3af1c 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 00000000000..b7571027d60
--- /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 00000000000..fd22ac319dd
--- /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 00000000000..cdf60e5bd67
--- /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 00000000000..44e9eb707bc
--- /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 b9d969ba1e5..74eaf587092 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 219d61e2bf4..733e90211c9 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 794eed2dd93..da3c3bd2728 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 cb0e8150bfc..25f5d0efc43 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 354570e5e9b..ba4af3d8800 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 e68ba495be0..1d3cecd9c62 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 458c74258f1..1247658381d 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 13575fccc55..ae04feb7394 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 00000000000..2ddf565820b
--- /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 4e89d59beda..09a454bdf47 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 bd4fdcae817..284d852462a 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 c92a8ee51b7..ca939dbab61 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 c104d082538..0ab28985ed1 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 a0930eb2140..f827fb2eb59 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 74568a0beb7..ce66d8e65f2 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 03dec26f3f7..a7052a941cf 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 66366cd1a04..281bb8fde88 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 323f74aad38..6a98fa6d124 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 fb7e089fb48..3d3f5d6f747 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 41be5b2236c..90540f7d1d3 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 d78c1377085..92f699350c0 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 0d722987b5e..85aa74741cc 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 dc8498dcb43..6f615c0d238 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 ed65b20abd6..b6d81d2e0e5 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 00000000000..f32b784eaae
--- /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 00000000000..99cedbcd226
--- /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 41d37ca9a41..47d7ebbde16 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 387730db165..452effd3431 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 00000000000..369b9434190
--- /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 b6b20c55787..fbe5cb8593f 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 09da595872c..fd7f3fd14cc 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 00000000000..f7d968b6d6c
--- /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 1ccb4df257e..795bfecf0ab 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 22699a39a59..9becd7e37fb 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 8a42824154b..149bfe9fa9a 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 eaf7f67ee00..440c17ffc9b 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 00000000000..1360050a69b
--- /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 00000000000..d805006264c
--- /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 00000000000..a59ca3f6cf1
--- /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 09e8ed60066..d487be089f3 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 00000000000..10ed6755d15
--- /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 1d40b0c96c1..73034231234 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 00000000000..99478f21c28
--- /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 a8275a19518..14ef329d56f 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 e8c93aa6049..a5bf590affd 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 915e1ac87a3..387eda92299 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 e289f8ce366..e4db9558f19 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 893cc93283d..9d9dfc629f9 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 aa2902930c9..f5b7cb8a23f 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 ae52942a92b..43e654bda69 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 8709d011425..389757b7bd2 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 79319a7d392..ad501c1d74e 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 ad9f9a16233..66d318527bf 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 3f54efd4869..6d884780e39 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 255f686d251..b3eed42f000 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 c88a92b5cdd..ddf5a8d2926 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 cbfea433c27..e108ba1e341 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 140909dcc2e..5f0b8e6362b 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 2e76b5924c6..78f5c1be5d2 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 7098c460153..f40de4f58ff 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 53f962c0e2c..c34a3235106 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 e322a5a3ce2..0ea5586a6df 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 a6741820ff3..65339cfaf91 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 7e9927c3c86..243d3fc1753 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 c2ae2360d3e..198fef36fb0 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 a50663a01d3..66a00f06708 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 8855a7db662..71fe863bb20 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 009eafde856..d93eb3a6086 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 00000000000..6c6e03ecc88
--- /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 00000000000..f13793773c3
--- /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 00000000000..ffe00c32e48
--- /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 b3bc85e3071..416eaa1a501 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 aa64b677cad..d4c0f0a6e2d 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 5d116ee6d3d..2f77b5f9f74 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 00000000000..eb01169137c
--- /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 68e61c9ecb8..57db25fa29e 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 691392a7b93..8690d8458c8 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 00000000000..437af9dd0b4
--- /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 9439715da73..52807709c31 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 ec57015ac22..cf50ff0eb26 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 aa35c1a5c3a..f8ab0cbd9de 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 f7b017d0144..e7a1d87dbec 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 ddbe96d89d8..adbc3f303e6 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 90b22d7eb18..3921dadd9dd 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 e4deb9b3e98..d770c18e67a 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 07ad0701920..cebaa345d89 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 f7e98d2a339..804502d8ba4 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 c7fdfe9080c..d6f652424e5 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 307f564a6e9..f94448688b2 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 550b25549e2..c3af8020730 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 90890e3ad1a..1deb52c4924 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 215a6cbb2a7..11217d1e59b 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 0fde23634e0..55ed27c1c71 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 00000000000..a02ec31cb9f
--- /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 fc8d1d7691e..f904107c6ce 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 5d9d240005e..999123dc2a4 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 d129fe2d790..afe583d5020 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 9408c0c6c57..d6b0bacd70c 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 f126bd0a4a0..226354e18af 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 12c71d98b0d..aab74b88aee 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 0568b42212d..929d69f9e5d 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 47f368b517b..73928b3154b 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 b16d26ce47c..cf7ea2e8cf8 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 1cd8de9a867..ca6163b574a 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 21d2cd04c53..a5f64b51fb0 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 25ef10b6f68..73e6deb4986 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 0ca701e35d9..ab3d609bcff 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 a680839a4b6..058ef4e15af 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 01c743be72a..e23430111e7 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 d078a414257..e37c757c135 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 8874daceeaa..c7a4cc6d07a 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 c275e320ecc..e7873ce594d 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